2019-01-22 11:02:08 +00:00
|
|
|
package libp2pwebrtcdirect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
2019-06-02 10:20:25 +00:00
|
|
|
smux "github.com/libp2p/go-libp2p-core/mux"
|
|
|
|
peer "github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
tpt "github.com/libp2p/go-libp2p-core/transport"
|
2019-01-22 11:02:08 +00:00
|
|
|
ma "github.com/multiformats/go-multiaddr"
|
2019-02-28 14:37:40 +00:00
|
|
|
mafmt "github.com/multiformats/go-multiaddr-fmt"
|
2019-04-06 15:47:28 +00:00
|
|
|
"github.com/pion/webrtc/v2"
|
2019-01-22 11:02:08 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Transport is the WebRTC transport.
|
|
|
|
type Transport struct {
|
2019-02-21 14:19:05 +00:00
|
|
|
webrtcOptions webrtc.Configuration
|
2019-06-02 10:20:25 +00:00
|
|
|
muxer smux.Multiplexer
|
2019-02-25 19:36:24 +00:00
|
|
|
localID peer.ID
|
2019-01-22 11:02:08 +00:00
|
|
|
api *webrtc.API
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewTransport creates a WebRTC transport that signals over a direct HTTP connection.
|
|
|
|
// It is currently required to provide a muxer.
|
2019-06-02 10:20:25 +00:00
|
|
|
func NewTransport(webrtcOptions webrtc.Configuration, muxer smux.Multiplexer) *Transport {
|
2019-01-22 11:02:08 +00:00
|
|
|
s := webrtc.SettingEngine{}
|
|
|
|
// Use Detach data channels mode
|
|
|
|
s.DetachDataChannels()
|
2019-02-25 19:36:24 +00:00
|
|
|
|
2019-01-22 11:02:08 +00:00
|
|
|
api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
|
|
|
|
return &Transport{
|
|
|
|
webrtcOptions: webrtcOptions,
|
|
|
|
muxer: muxer, // TODO: Make the muxer optional
|
2019-02-25 19:36:24 +00:00
|
|
|
localID: peer.ID(1),
|
2019-01-22 11:02:08 +00:00
|
|
|
api: api,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// CanDial returns true if this transport believes it can dial the given
|
|
|
|
// multiaddr.
|
|
|
|
func (t *Transport) CanDial(addr ma.Multiaddr) bool {
|
|
|
|
return mafmt.WebRTCDirect.Matches(addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dial dials the peer at the remote address.
|
2019-06-02 10:20:25 +00:00
|
|
|
func (t *Transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tpt.CapableConn, error) {
|
2019-01-22 11:02:08 +00:00
|
|
|
if !t.CanDial(raddr) {
|
|
|
|
return nil, fmt.Errorf("can't dial address %s", raddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg, err := newConnConfig(t, raddr, false)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to get dial args: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-02-25 19:36:24 +00:00
|
|
|
cfg.remoteID = p
|
|
|
|
|
2019-01-22 11:02:08 +00:00
|
|
|
conn, err := dial(ctx, cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to create connection: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Listen listens on the given multiaddr.
|
|
|
|
func (t *Transport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
|
|
|
|
if !t.CanDial(laddr) {
|
|
|
|
return nil, fmt.Errorf("can't listen on address %s", laddr)
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg, err := newConnConfig(t, laddr, true)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to get dial args: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
l, err := newListener(cfg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("failed to listen: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return l, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Protocols returns the list of terminal protocols this transport can dial.
|
|
|
|
func (t *Transport) Protocols() []int {
|
|
|
|
return []int{ma.P_P2P_WEBRTC_DIRECT}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Proxy always returns false for the TCP transport.
|
|
|
|
func (t *Transport) Proxy() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *Transport) String() string {
|
|
|
|
return "p2p-webrtc-direct"
|
|
|
|
}
|