From 912a8ee9e02662eec79690dc0c9ff6510b936dda Mon Sep 17 00:00:00 2001 From: sukun Date: Mon, 25 Sep 2023 18:35:23 +0530 Subject: [PATCH] autorelay: advertise /webrtc addresses on relay reservation --- p2p/host/autorelay/autorelay_test.go | 46 ++++++++++++++++++++++++++++ p2p/host/autorelay/relay_finder.go | 18 +++++++++++ 2 files changed, 64 insertions(+) diff --git a/p2p/host/autorelay/autorelay_test.go b/p2p/host/autorelay/autorelay_test.go index 410f8cb6dc..8f7e7ee6d3 100644 --- a/p2p/host/autorelay/autorelay_test.go +++ b/p2p/host/autorelay/autorelay_test.go @@ -517,3 +517,49 @@ func TestNoBusyLoop0MinInterval(t *testing.T) { val := atomic.LoadUint64(&calledTimes) require.Less(t, val, uint64(2)) } + +func TestRelayAddrs(t *testing.T) { + const numCandidates = 3 + var called bool + peerChan := make(chan peer.AddrInfo, numCandidates) + for i := 0; i < numCandidates; i++ { + r := newRelay(t) + t.Cleanup(func() { r.Close() }) + peerChan <- peer.AddrInfo{ID: r.ID(), Addrs: r.Addrs()} + } + close(peerChan) + + h := newPrivateNode(t, + func(_ context.Context, num int) <-chan peer.AddrInfo { + require.False(t, called, "expected the peer source callback to only have been called once") + called = true + require.Equal(t, numCandidates, num) + return peerChan + }, + autorelay.WithMaxCandidates(numCandidates), + autorelay.WithNumRelays(1), + autorelay.WithBootDelay(0), + autorelay.WithMinInterval(time.Hour), + ) + defer h.Close() + + require.Eventually( + t, + func() bool { + if numRelays(h) <= 0 { + return false + } + addrs := h.Addrs() + var foundCircuit, foundWebRTC bool + for _, addr := range addrs { + _, cerr := addr.ValueForProtocol(ma.P_CIRCUIT) + _, werr := addr.ValueForProtocol(ma.P_WEBRTC) + foundCircuit = foundCircuit || cerr == nil + foundWebRTC = foundWebRTC || (cerr == nil && werr == nil) + } + return foundCircuit && foundWebRTC + }, + 5*time.Second, + 100*time.Millisecond, + ) +} diff --git a/p2p/host/autorelay/relay_finder.go b/p2p/host/autorelay/relay_finder.go index ef79950b7b..aa5e20bfef 100644 --- a/p2p/host/autorelay/relay_finder.go +++ b/p2p/host/autorelay/relay_finder.go @@ -17,6 +17,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/host/eventbus" circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" circuitv2_proto "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/proto" + libp2pwebrtcprivate "github.com/libp2p/go-libp2p/p2p/transport/webrtcprivate" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" @@ -737,9 +738,15 @@ func (rf *relayFinder) relayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { addrs := cleanupAddressSet(rf.host.Peerstore().Addrs(p)) relayAddrCnt += len(addrs) circuit := ma.StringCast(fmt.Sprintf("/p2p/%s/p2p-circuit", p)) + webrtc := libp2pwebrtcprivate.WebRTCAddr for _, addr := range addrs { pub := addr.Encapsulate(circuit) raddrs = append(raddrs, pub) + if isBrowserDialableAddr(addr) { + waddr := pub.Encapsulate(webrtc) + raddrs = append(raddrs, waddr) + relayAddrCnt++ + } } } @@ -808,3 +815,14 @@ func (rf *relayFinder) resetMetrics() { rf.metricsTracer.RelayAddressCount(0) rf.metricsTracer.ScheduledWorkUpdated(&scheduledWorkTimes{}) } + +var browserProtocols []int = []int{ma.P_WEBTRANSPORT, ma.P_WEBRTC_DIRECT, ma.P_WS, ma.P_WSS} + +func isBrowserDialableAddr(addr ma.Multiaddr) bool { + for _, p := range browserProtocols { + if _, err := addr.ValueForProtocol(p); err == nil { + return true + } + } + return false +}