From db7c7b2eeba375bfcd17280a7827ae4a98210533 Mon Sep 17 00:00:00 2001 From: sukun Date: Mon, 16 Oct 2023 22:10:44 +0530 Subject: [PATCH] webrtcprivate: advertise /webrtc addresses --- p2p/host/autorelay/relay_finder.go | 2 +- p2p/host/basic/basic_host.go | 30 ++++++++++++++++++++ p2p/protocol/holepunch/holepuncher.go | 5 +++- p2p/protocol/holepunch/svc.go | 5 +++- p2p/test/basichost/basic_host_test.go | 41 +++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 3 deletions(-) diff --git a/p2p/host/autorelay/relay_finder.go b/p2p/host/autorelay/relay_finder.go index ef79950b7b..de041b9ad9 100644 --- a/p2p/host/autorelay/relay_finder.go +++ b/p2p/host/autorelay/relay_finder.go @@ -726,7 +726,7 @@ func (rf *relayFinder) relayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr { // only keep private addrs from the original addr set for _, addr := range addrs { - if manet.IsPrivateAddr(addr) { + if !manet.IsPublicAddr(addr) { raddrs = append(raddrs, addr) } } diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index 50ab8dfb08..318d96fd1e 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -27,6 +27,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" "github.com/libp2p/go-libp2p/p2p/protocol/identify" "github.com/libp2p/go-libp2p/p2p/protocol/ping" + libp2pwebrtcprivate "github.com/libp2p/go-libp2p/p2p/transport/webrtcprivate" libp2pwebtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" "github.com/prometheus/client_golang/prometheus" @@ -801,9 +802,38 @@ func (h *BasicHost) Addrs() []ma.Multiaddr { addrs[i] = addrWithCerthash } } + + // Append webrtc addresses to circuit-v2 addresses + hasWebRTCPrivate := false + for _, addr := range addrs { + if addr.Equal(libp2pwebrtcprivate.WebRTCAddr) { + hasWebRTCPrivate = true + break + } + } + if hasWebRTCPrivate { + for _, addr := range addrs { + if _, err := addr.ValueForProtocol(ma.P_CIRCUIT); err == nil { + if isBrowserDialableAddr(addr) { + addrs = append(addrs, addr.Encapsulate(libp2pwebrtcprivate.WebRTCAddr)) + } + } + } + } return addrs } +var browserProtocols = []int{ma.P_WEBTRANSPORT, ma.P_WEBRTC_DIRECT, ma.P_WSS} + +func isBrowserDialableAddr(addr ma.Multiaddr) bool { + for _, p := range browserProtocols { + if _, err := addr.ValueForProtocol(p); err == nil { + return true + } + } + return false +} + // NormalizeMultiaddr returns a multiaddr suitable for equality checks. // If the multiaddr is a webtransport component, it removes the certhashes. func (h *BasicHost) NormalizeMultiaddr(addr ma.Multiaddr) ma.Multiaddr { diff --git a/p2p/protocol/holepunch/holepuncher.go b/p2p/protocol/holepunch/holepuncher.go index 18b950f9e3..cdcba85186 100644 --- a/p2p/protocol/holepunch/holepuncher.go +++ b/p2p/protocol/holepunch/holepuncher.go @@ -180,7 +180,10 @@ func (hp *holePuncher) maybeDialWebRTC(p peer.ID) { for _, a := range addrs { if _, err := a.ValueForProtocol(ma.P_WEBRTC); err == nil { ctx := network.WithForceDirectDial(hp.ctx, "webrtc holepunch") - hp.host.Connect(ctx, peer.AddrInfo{ID: p}) // address is already in peerstore + err := hp.host.Connect(ctx, peer.AddrInfo{ID: p}) // address is already in peerstore + if err != nil { + log.Debugf("holepunch attempt to %s over /webrtc failed: %s", p, err) + } return } } diff --git a/p2p/protocol/holepunch/svc.go b/p2p/protocol/holepunch/svc.go index 4b19e5f811..1796ec9701 100644 --- a/p2p/protocol/holepunch/svc.go +++ b/p2p/protocol/holepunch/svc.go @@ -310,7 +310,10 @@ func (s *Service) Connected(_ network.Network, conn network.Conn) { for _, addr := range s.host.Peerstore().Addrs(p) { if _, err := addr.ValueForProtocol(ma.P_WEBRTC); err == nil { ctx := network.WithForceDirectDial(s.ctx, "webrtc holepunch") - s.host.Connect(ctx, peer.AddrInfo{ID: p}) // address is already in peerstore + err := s.host.Connect(ctx, peer.AddrInfo{ID: p}) // address is already in peerstore + if err != nil { + log.Debugf("holepunch attempt to %s over /webrtc failed: %s", p, err) + } return } } diff --git a/p2p/test/basichost/basic_host_test.go b/p2p/test/basichost/basic_host_test.go index 13800fef99..134f8630fd 100644 --- a/p2p/test/basichost/basic_host_test.go +++ b/p2p/test/basichost/basic_host_test.go @@ -10,6 +10,7 @@ import ( "github.com/libp2p/go-libp2p/core/network" "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" + "github.com/libp2p/go-libp2p/p2p/host/autorelay" "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" ma "github.com/multiformats/go-multiaddr" @@ -154,3 +155,43 @@ func TestNewStreamTransientConnection(t *testing.T) { <-done <-done } + +func TestWebRTCPrivateAddressAdvertisement(t *testing.T) { + r, err := libp2p.New( + // We need a public address for the relay + libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr { + return append(addrs, ma.StringCast("/ip4/1.2.3.4/udp/1/quic-v1/webtransport")) + }), + libp2p.EnableRelayService(), + libp2p.ForceReachabilityPublic(), + ) + require.NoError(t, err) + + relay1info := peer.AddrInfo{ + ID: r.ID(), + Addrs: r.Addrs(), + } + + h, err := libp2p.New( + libp2p.ListenAddrStrings("/ip4/127.0.0.1/udp/0/quic-v1"), + libp2p.EnableRelay(), + libp2p.EnableWebRTCPrivate(nil), + libp2p.EnableAutoRelayWithStaticRelays( + []peer.AddrInfo{relay1info}, + autorelay.WithBootDelay(0), + ), + libp2p.ForceReachabilityPrivate(), + ) + require.NoError(t, err) + + require.Eventually(t, func() bool { + for _, a := range h.Addrs() { + _, rerr := a.ValueForProtocol(ma.P_CIRCUIT) + _, werr := a.ValueForProtocol(ma.P_WEBRTC) + if rerr == nil && werr == nil { + return true + } + } + return false + }, 5*time.Second, 50*time.Millisecond) +}