93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
package libp2pwebrtcdirect
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
peer "github.com/libp2p/go-libp2p-peer"
|
|
tpt "github.com/libp2p/go-libp2p-transport"
|
|
smux "github.com/libp2p/go-stream-muxer"
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
"github.com/pions/webrtc"
|
|
mafmt "github.com/whyrusleeping/mafmt"
|
|
)
|
|
|
|
// Transport is the WebRTC transport.
|
|
type Transport struct {
|
|
webrtcOptions webrtc.RTCConfiguration
|
|
muxer smux.Transport
|
|
api *webrtc.API
|
|
}
|
|
|
|
// NewTransport creates a WebRTC transport that signals over a direct HTTP connection.
|
|
// It is currently required to provide a muxer.
|
|
func NewTransport(webrtcOptions webrtc.RTCConfiguration, muxer smux.Transport) *Transport {
|
|
s := webrtc.SettingEngine{}
|
|
// Use Detach data channels mode
|
|
s.DetachDataChannels()
|
|
api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
|
|
return &Transport{
|
|
webrtcOptions: webrtcOptions,
|
|
muxer: muxer, // TODO: Make the muxer optional
|
|
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.
|
|
func (t *Transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tpt.Conn, error) {
|
|
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)
|
|
}
|
|
|
|
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"
|
|
}
|