go-libp2p-webrtc-direct/webrtcdirect.go

100 lines
2.9 KiB
Go
Raw Normal View History

2018-09-30 19:33:55 +00:00
package libp2pwebrtcdirect
import (
"context"
"fmt"
logging "github.com/ipfs/go-log"
peer "github.com/libp2p/go-libp2p-peer"
tpt "github.com/libp2p/go-libp2p-transport"
tptu "github.com/libp2p/go-libp2p-transport-upgrader"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"
"github.com/pions/dcnet"
"github.com/pions/webrtc"
mafmt "github.com/whyrusleeping/mafmt"
)
var log = logging.Logger("webrtcdirect-tpt")
var webrtcma, _ = ma.NewMultiaddr("/p2p-webrtc-direct")
// WebRTCDirectTransport is the TCP transport.
type WebRTCDirectTransport struct {
webrtcOptions webrtc.RTCConfiguration
// Connection upgrader for upgrading insecure stream connections to
// secure multiplex connections.
Upgrader *tptu.Upgrader
}
var _ tpt.Transport = &WebRTCDirectTransport{}
// NewWebRTCDirectTransport creates a WebRTC transport that signals over a direct HTTP connection.
func NewWebRTCDirectTransport(webrtcOptions webrtc.RTCConfiguration, upgrader *tptu.Upgrader) *WebRTCDirectTransport {
return &WebRTCDirectTransport{
webrtcOptions: webrtcOptions,
Upgrader: upgrader,
}
}
// CanDial returns true if this transport believes it can dial the given
// multiaddr.
func (t *WebRTCDirectTransport) CanDial(addr ma.Multiaddr) bool {
return mafmt.WebRTCDirect.Matches(addr)
}
// Dial dials the peer at the remote address.
func (t *WebRTCDirectTransport) 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)
}
httpMa := raddr.Decapsulate(webrtcma)
_, httpAddr, err := manet.DialArgs(httpMa)
if err != nil {
return nil, fmt.Errorf("failed to get dial args: %v", err)
}
signaler := NewHTTPDirectSignaler(t.webrtcOptions, httpAddr)
conn, err := dcnet.Dial(signaler)
if err != nil {
return nil, fmt.Errorf("failed to dial: %v", err)
}
wrappedConn := wrapNetConn(conn, raddr, raddr)
return t.Upgrader.UpgradeOutbound(ctx, t, wrappedConn, p)
}
// Listen listens on the given multiaddr.
func (t *WebRTCDirectTransport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
if !t.CanDial(laddr) {
return nil, fmt.Errorf("can't listen on address %s", laddr)
}
httpMa := laddr.Decapsulate(webrtcma)
_, httpAddr, err := manet.DialArgs(httpMa)
if err != nil {
return nil, fmt.Errorf("failed to get dial args: %v", err)
}
signaler := NewHTTPDirectSignaler(t.webrtcOptions, httpAddr)
listener := dcnet.NewListener(signaler)
wrappedListener := wrapNetListener(listener, laddr, laddr)
return t.Upgrader.UpgradeListener(t, wrappedListener), nil
}
// Protocols returns the list of terminal protocols this transport can dial.
func (t *WebRTCDirectTransport) Protocols() []int {
return []int{ma.P_P2P_WEBRTC_DIRECT}
}
// Proxy always returns false for the TCP transport.
func (t *WebRTCDirectTransport) Proxy() bool {
return false
}
func (t *WebRTCDirectTransport) String() string {
return "p2p-webrtc-direct"
}