100 lines
2.9 KiB
Go
100 lines
2.9 KiB
Go
|
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"
|
||
|
}
|