Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

WIP: Add support for new Protocol and Multiaddr format #26

Open
wants to merge 1 commit into
base: webrtc-signal-protocol
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions addr_util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package libp2pwebrtcdirect

import (
"fmt"
"net"

peer "github.com/libp2p/go-libp2p-peer"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"
)

func newMultiaddrFromNetAddr(netAddr net.Addr, peerID peer.ID) (ma.Multiaddr, error) {
tcpMa, err := manet.FromNetAddr(netAddr)
if err != nil {
return nil, fmt.Errorf("failed create ma: %v", err)
}
httpMa := tcpMa.Encapsulate(httpma)
webrtcMa, err := ma.NewMultiaddr("/p2p-webrtc/" + peer.IDB58Encode(peerID))
if err != nil {
return nil, err
}
maAddr := httpMa.Encapsulate(webrtcMa)
return maAddr, nil
}

func getPeerIDFromMultiAddr(addr ma.Multiaddr) (peer.ID, error) {
idString, err := addr.ValueForProtocol(protoCode)
if err != nil {
return "", err
}
return peer.IDB58Decode(idString)
}
21 changes: 16 additions & 5 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,32 @@ type connConfig struct {
addr net.Addr
isServer bool
remoteID peer.ID
localID peer.ID
}

func newConnConfig(transport *Transport, maAddr ma.Multiaddr, isServer bool) (*connConfig, error) {
httpMa := maAddr.Decapsulate(webrtcma)

func getNetAddr(addr ma.Multiaddr) (net.Addr, error) {
if !Fmt.Matches(addr) {
return nil, fmt.Errorf("misformatted multiaddress: %q (expected %q)", addr.String(), Fmt.String())
}
httpMa, _ := ma.SplitLast(addr)
tcpMa := httpMa.Decapsulate(httpma)
addr, err := manet.ToNetAddr(tcpMa)
netAddr, err := manet.ToNetAddr(tcpMa)
if err != nil {
return nil, fmt.Errorf("failed to get net addr: %v", err)
}
return netAddr, nil
}

func newConnConfig(transport *Transport, maAddr ma.Multiaddr, isServer bool) (*connConfig, error) {
netAddr, err := getNetAddr(maAddr)
if err != nil {
return nil, err
}

return &connConfig{
transport: transport,
maAddr: maAddr,
addr: addr,
addr: netAddr,
isServer: isServer,
}, nil
}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/libp2p/go-libp2p-peerstore v0.0.1
github.com/libp2p/go-libp2p-transport v0.0.4
github.com/libp2p/go-stream-muxer v0.0.1
github.com/libp2p/go-ws-transport v0.0.1
github.com/multiformats/go-multiaddr v0.0.2
github.com/multiformats/go-multiaddr-fmt v0.0.1
github.com/multiformats/go-multiaddr-net v0.0.1
Expand All @@ -23,6 +24,7 @@ require (
github.com/pions/datachannel v1.2.2-0.20190402055840-9276b506f1f3
github.com/pions/quic-go v0.10.2 // indirect
github.com/pions/webrtc v1.2.1-0.20190402062217-69e5725007d2
github.com/stretchr/testify v1.3.0
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc
github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c // indirect
Expand Down
2 changes: 1 addition & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324 h1:PV190X5/DzQ/tbFFG5Y
github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
github.com/ipfs/go-cid v0.0.1 h1:GBjWPktLnNyX0JiQCNFpUuUSoMw5KMyqrsejHYlILBE=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
github.com/ipfs/go-datastore v0.0.1/go.mod h1:bYmHO9fuKO1Ca7dpdDBWQl0mndy5b0HFqSJjGlNYtzs=
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was seeing some errors about a checksum mismatch. Manually changing this line fixed them.

Copy link
Contributor

@backkem backkem Apr 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this can be fixed (dependency removed entirely) by dropping the examples.

github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
Expand Down
9 changes: 2 additions & 7 deletions listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

tpt "github.com/libp2p/go-libp2p-transport"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr-net"
)

// Listener is an interface closely resembling the net.Listener interface.
Expand All @@ -28,14 +27,10 @@ func newListener(config *connConfig) (*Listener, error) {
}

// Update the addr after listening
tcpMa, err := manet.FromNetAddr(ln.Addr())
maAddr, err := newMultiaddrFromNetAddr(ln.Addr(), config.localID)
if err != nil {
return nil, fmt.Errorf("failed create ma: %v", err)
return nil, err
}

httpMa := tcpMa.Encapsulate(httpma)
maAddr := httpMa.Encapsulate(webrtcma)

config.addr = ln.Addr()
config.maAddr = maAddr

Expand Down
54 changes: 54 additions & 0 deletions protocol.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package libp2pwebrtcdirect

import (
"fmt"

peer "github.com/libp2p/go-libp2p-peer"
ma "github.com/multiformats/go-multiaddr"
)

func init() {
if err := ma.AddProtocol(Protocol); err != nil {
panic(fmt.Errorf("error registering p2p-webrtc protocol: %s", err))
}
}

const protoCode = 0x1992

var Protocol = ma.Protocol{
Name: "p2p-webrtc",
Code: protoCode,
VCode: ma.CodeToVarint(protoCode),
Size: -1,
Transcoder: Transcoder,
}

var Transcoder ma.Transcoder = transcoder{}

// transcoder handles encoding/decoding peer ids as base58.
type transcoder struct {
strtobyte func(string) ([]byte, error)
bytetostr func([]byte) (string, error)
validbyte func([]byte) error
}

func (t transcoder) StringToBytes(s string) ([]byte, error) {
id, err := peer.IDB58Decode(s)
if err != nil {
return nil, err
}
return []byte(id), nil
}

func (t transcoder) BytesToString(b []byte) (string, error) {
id, err := peer.IDFromBytes(b)
if err != nil {
return "", err
}
return peer.IDB58Encode(id), nil
}

func (t transcoder) ValidateBytes(b []byte) error {
_, err := peer.IDFromBytes(b)
return err
}
23 changes: 18 additions & 5 deletions transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ import (

peer "github.com/libp2p/go-libp2p-peer"
tpt "github.com/libp2p/go-libp2p-transport"
transport "github.com/libp2p/go-libp2p-transport"
smux "github.com/libp2p/go-stream-muxer"
ma "github.com/multiformats/go-multiaddr"
mafmt "github.com/multiformats/go-multiaddr-fmt"
"github.com/pions/webrtc"
)

// Ensure that our Transport implements the correct interface.
var _ transport.Transport = &Transport{}

// Fmt is the Multiaddress format for WebRTC
var Fmt = mafmt.And(mafmt.HTTP, mafmt.Base(Protocol.Code))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, we're only supporting signaling over HTTP. In the future it should be possible to support many different transports. Hopefully we can rely on existing code in libp2p to set up a connection (likely a Stream) using an arbitrary transport.


// Transport is the WebRTC transport.
type Transport struct {
webrtcOptions webrtc.Configuration
Expand Down Expand Up @@ -39,7 +46,7 @@ func NewTransport(webrtcOptions webrtc.Configuration, muxer smux.Transport) *Tra
// 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)
return Fmt.Matches(addr)
}

// Dial dials the peer at the remote address.
Expand All @@ -48,11 +55,12 @@ func (t *Transport) Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (tp
return nil, fmt.Errorf("can't dial address %s", raddr)
}

// TODO: Check that the peer id in raddr is equal to p.

cfg, err := newConnConfig(t, raddr, false)
if err != nil {
return nil, fmt.Errorf("failed to get dial args: %v", err)
}

cfg.remoteID = p

conn, err := dial(ctx, cfg)
Expand All @@ -73,6 +81,11 @@ func (t *Transport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {
if err != nil {
return nil, fmt.Errorf("failed to get dial args: %v", err)
}
localID, err := getPeerIDFromMultiAddr(laddr)
if err != nil {
return nil, err
}
cfg.localID = localID

l, err := newListener(cfg)
if err != nil {
Expand All @@ -84,14 +97,14 @@ func (t *Transport) Listen(laddr ma.Multiaddr) (tpt.Listener, error) {

// Protocols returns the list of terminal protocols this transport can dial.
func (t *Transport) Protocols() []int {
return []int{ma.P_P2P_WEBRTC_DIRECT}
return []int{protoCode}
}

// Proxy always returns false for the TCP transport.
// Proxy always returns false for the WebRTC transport.
func (t *Transport) Proxy() bool {
return false
}

func (t *Transport) String() string {
return "p2p-webrtc-direct"
return "p2p-webrtc"
}
1 change: 0 additions & 1 deletion webrtcdirect.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

var log = logging.Logger("webrtcdirect-tpt")

var webrtcma, _ = ma.NewMultiaddr("/p2p-webrtc-direct")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the new Multiaddress format requires a peer id after p2p-webrtc, we can't create it statically anymore.

var httpma, _ = ma.NewMultiaddr("/http")

var _ tpt.Transport = &Transport{}
Expand Down
23 changes: 20 additions & 3 deletions webrtcdirect_test.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
package libp2pwebrtcdirect

import (
"math/rand"
"testing"

logging "github.com/ipfs/go-log"

crypto "github.com/libp2p/go-libp2p-crypto"
peer "github.com/libp2p/go-libp2p-peer"
utils "github.com/libp2p/go-libp2p-transport/test"
ma "github.com/multiformats/go-multiaddr"
"github.com/pions/webrtc"
mplex "github.com/whyrusleeping/go-smux-multiplex"
)

func newTestPeerID(t *testing.T) peer.ID {
t.Helper()
seededReader := rand.New(rand.NewSource(12345678))
priv, _, err := crypto.GenerateEd25519Key(seededReader)
if err != nil {
t.Fatal(err)
}
id, err := peer.IDFromPrivateKey(priv)
if err != nil {
t.Fatal(err)
}
return id
}

func TestTransport(t *testing.T) {
logging.SetLogLevel("*", "warning")

Expand All @@ -23,8 +39,9 @@ func TestTransport(t *testing.T) {
new(mplex.Transport),
)

addr := "/ip4/127.0.0.1/tcp/0/http/p2p-webrtc-direct"
utils.SubtestTransport(t, ta, tb, addr, "peerA")
peerID := newTestPeerID(t)
addr := "/ip4/127.0.0.1/tcp/0/http/p2p-webrtc/" + peer.IDB58Encode(peerID)
utils.SubtestTransport(t, ta, tb, addr, peerID)
}

func TestTransportCantListenUtp(t *testing.T) {
Expand Down