From fc13f5f82f7b06bf3574afc3d5ac842abe18c039 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sun, 4 May 2025 20:25:36 +0300 Subject: [PATCH 01/13] fix: omit webrtc transport from compilation except some utilities and types --- defaults.go | 223 +--------------------- defaults_js.go | 15 ++ defaults_shared.go | 227 +++++++++++++++++++++++ libp2p_test.go | 3 + p2p/host/basic/basic_host.go | 19 -- p2p/transport/webrtc/connection.go | 3 + p2p/transport/webrtc/listener.go | 3 + p2p/transport/webrtc/stream_test.go | 3 + p2p/transport/webrtc/transport.go | 37 +--- p2p/transport/webrtc/transport_shared.go | 41 ++++ p2p/transport/webrtc/transport_test.go | 3 + 11 files changed, 304 insertions(+), 273 deletions(-) create mode 100644 defaults_js.go create mode 100644 defaults_shared.go create mode 100644 p2p/transport/webrtc/transport_shared.go diff --git a/defaults.go b/defaults.go index 31de6f025d..1b3e49fc42 100644 --- a/defaults.go +++ b/defaults.go @@ -1,47 +1,16 @@ -package libp2p +//go:build !js +// +build !js -// This file contains all the default configuration options. +package libp2p import ( - "crypto/rand" - - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" - rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" - "github.com/libp2p/go-libp2p/p2p/muxer/yamux" - "github.com/libp2p/go-libp2p/p2p/net/connmgr" - "github.com/libp2p/go-libp2p/p2p/net/swarm" - "github.com/libp2p/go-libp2p/p2p/security/noise" - tls "github.com/libp2p/go-libp2p/p2p/security/tls" quic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/tcp" libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" - "github.com/prometheus/client_golang/prometheus" - - "github.com/multiformats/go-multiaddr" ) -// DefaultSecurity is the default security option. -// -// Useful when you want to extend, but not replace, the supported transport -// security protocols. -var DefaultSecurity = ChainOptions( - Security(tls.ID, tls.New), - Security(noise.ID, noise.New), -) - -// DefaultMuxers configures libp2p to use the stream connection multiplexers. -// -// Use this option when you want to *extend* the set of multiplexers used by -// libp2p instead of replacing them. -var DefaultMuxers = Muxer(yamux.ID, yamux.DefaultTransport) - -// DefaultTransports are the default libp2p transports. -// -// Use this option when you want to *extend* the set of transports used by -// libp2p instead of replacing them. var DefaultTransports = ChainOptions( Transport(tcp.NewTCPTransport), Transport(quic.NewTransport), @@ -49,189 +18,3 @@ var DefaultTransports = ChainOptions( Transport(webtransport.New), Transport(libp2pwebrtc.New), ) - -// DefaultPrivateTransports are the default libp2p transports when a PSK is supplied. -// -// Use this option when you want to *extend* the set of transports used by -// libp2p instead of replacing them. -var DefaultPrivateTransports = ChainOptions( - Transport(tcp.NewTCPTransport), - Transport(ws.New), -) - -// DefaultPeerstore configures libp2p to use the default peerstore. -var DefaultPeerstore Option = func(cfg *Config) error { - ps, err := pstoremem.NewPeerstore() - if err != nil { - return err - } - return cfg.Apply(Peerstore(ps)) -} - -// RandomIdentity generates a random identity. (default behaviour) -var RandomIdentity = func(cfg *Config) error { - priv, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return err - } - return cfg.Apply(Identity(priv)) -} - -// DefaultListenAddrs configures libp2p to use default listen address. -var DefaultListenAddrs = func(cfg *Config) error { - addrs := []string{ - "/ip4/0.0.0.0/tcp/0", - "/ip4/0.0.0.0/udp/0/quic-v1", - "/ip4/0.0.0.0/udp/0/quic-v1/webtransport", - "/ip4/0.0.0.0/udp/0/webrtc-direct", - "/ip6/::/tcp/0", - "/ip6/::/udp/0/quic-v1", - "/ip6/::/udp/0/quic-v1/webtransport", - "/ip6/::/udp/0/webrtc-direct", - } - listenAddrs := make([]multiaddr.Multiaddr, 0, len(addrs)) - for _, s := range addrs { - addr, err := multiaddr.NewMultiaddr(s) - if err != nil { - return err - } - listenAddrs = append(listenAddrs, addr) - } - return cfg.Apply(ListenAddrs(listenAddrs...)) -} - -// DefaultEnableRelay enables relay dialing and listening by default. -var DefaultEnableRelay = func(cfg *Config) error { - return cfg.Apply(EnableRelay()) -} - -var DefaultResourceManager = func(cfg *Config) error { - // Default memory limit: 1/8th of total memory, minimum 128MB, maximum 1GB - limits := rcmgr.DefaultLimits - SetDefaultServiceLimits(&limits) - mgr, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(limits.AutoScale())) - if err != nil { - return err - } - - return cfg.Apply(ResourceManager(mgr)) -} - -// DefaultConnectionManager creates a default connection manager -var DefaultConnectionManager = func(cfg *Config) error { - mgr, err := connmgr.NewConnManager(160, 192) - if err != nil { - return err - } - - return cfg.Apply(ConnectionManager(mgr)) -} - -// DefaultPrometheusRegisterer configures libp2p to use the default registerer -var DefaultPrometheusRegisterer = func(cfg *Config) error { - return cfg.Apply(PrometheusRegisterer(prometheus.DefaultRegisterer)) -} - -var defaultUDPBlackHoleDetector = func(cfg *Config) error { - // A black hole is a binary property. On a network if UDP dials are blocked, all dials will - // fail. So a low success rate of 5 out 100 dials is good enough. - return cfg.Apply(UDPBlackHoleSuccessCounter(&swarm.BlackHoleSuccessCounter{N: 100, MinSuccesses: 5, Name: "UDP"})) -} - -var defaultIPv6BlackHoleDetector = func(cfg *Config) error { - // A black hole is a binary property. On a network if there is no IPv6 connectivity, all - // dials will fail. So a low success rate of 5 out 100 dials is good enough. - return cfg.Apply(IPv6BlackHoleSuccessCounter(&swarm.BlackHoleSuccessCounter{N: 100, MinSuccesses: 5, Name: "IPv6"})) -} - -// Complete list of default options and when to fallback on them. -// -// Please *DON'T* specify default options any other way. Putting this all here -// makes tracking defaults *much* easier. -var defaults = []struct { - fallback func(cfg *Config) bool - opt Option -}{ - { - fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.ListenAddrs == nil }, - opt: DefaultListenAddrs, - }, - { - fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.PSK == nil }, - opt: DefaultTransports, - }, - { - fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.PSK != nil }, - opt: DefaultPrivateTransports, - }, - { - fallback: func(cfg *Config) bool { return cfg.Muxers == nil }, - opt: DefaultMuxers, - }, - { - fallback: func(cfg *Config) bool { return !cfg.Insecure && cfg.SecurityTransports == nil }, - opt: DefaultSecurity, - }, - { - fallback: func(cfg *Config) bool { return cfg.PeerKey == nil }, - opt: RandomIdentity, - }, - { - fallback: func(cfg *Config) bool { return cfg.Peerstore == nil }, - opt: DefaultPeerstore, - }, - { - fallback: func(cfg *Config) bool { return !cfg.RelayCustom }, - opt: DefaultEnableRelay, - }, - { - fallback: func(cfg *Config) bool { return cfg.ResourceManager == nil }, - opt: DefaultResourceManager, - }, - { - fallback: func(cfg *Config) bool { return cfg.ConnManager == nil }, - opt: DefaultConnectionManager, - }, - { - fallback: func(cfg *Config) bool { return !cfg.DisableMetrics && cfg.PrometheusRegisterer == nil }, - opt: DefaultPrometheusRegisterer, - }, - { - fallback: func(cfg *Config) bool { - return !cfg.CustomUDPBlackHoleSuccessCounter && cfg.UDPBlackHoleSuccessCounter == nil - }, - opt: defaultUDPBlackHoleDetector, - }, - { - fallback: func(cfg *Config) bool { - return !cfg.CustomIPv6BlackHoleSuccessCounter && cfg.IPv6BlackHoleSuccessCounter == nil - }, - opt: defaultIPv6BlackHoleDetector, - }, -} - -// Defaults configures libp2p to use the default options. Can be combined with -// other options to *extend* the default options. -var Defaults Option = func(cfg *Config) error { - for _, def := range defaults { - if err := cfg.Apply(def.opt); err != nil { - return err - } - } - return nil -} - -// FallbackDefaults applies default options to the libp2p node if and only if no -// other relevant options have been applied. will be appended to the options -// passed into New. -var FallbackDefaults Option = func(cfg *Config) error { - for _, def := range defaults { - if !def.fallback(cfg) { - continue - } - if err := cfg.Apply(def.opt); err != nil { - return err - } - } - return nil -} diff --git a/defaults_js.go b/defaults_js.go new file mode 100644 index 0000000000..39cc43f492 --- /dev/null +++ b/defaults_js.go @@ -0,0 +1,15 @@ +//go:build js +// +build js + +package libp2p + +import ( + ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" + webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" +) + +// Only WebSocket and WebTransport are supported in the browser. +var DefaultTransports = ChainOptions( + Transport(ws.New), + Transport(webtransport.New), +) diff --git a/defaults_shared.go b/defaults_shared.go new file mode 100644 index 0000000000..9bd57e4608 --- /dev/null +++ b/defaults_shared.go @@ -0,0 +1,227 @@ +package libp2p + +// This file contains all the default configuration options. + +import ( + "crypto/rand" + + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" + rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" + "github.com/libp2p/go-libp2p/p2p/muxer/yamux" + "github.com/libp2p/go-libp2p/p2p/net/connmgr" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + "github.com/libp2p/go-libp2p/p2p/security/noise" + tls "github.com/libp2p/go-libp2p/p2p/security/tls" + "github.com/libp2p/go-libp2p/p2p/transport/tcp" + ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" + "github.com/prometheus/client_golang/prometheus" + + "github.com/multiformats/go-multiaddr" +) + +// DefaultSecurity is the default security option. +// +// Useful when you want to extend, but not replace, the supported transport +// security protocols. +var DefaultSecurity = ChainOptions( + Security(tls.ID, tls.New), + Security(noise.ID, noise.New), +) + +// DefaultMuxers configures libp2p to use the stream connection multiplexers. +// +// Use this option when you want to *extend* the set of multiplexers used by +// libp2p instead of replacing them. +var DefaultMuxers = Muxer(yamux.ID, yamux.DefaultTransport) + +// DefaultTransports are the default libp2p transports. +// +// Use this option when you want to *extend* the set of transports used by +// libp2p instead of replacing them. + +// DefaultPrivateTransports are the default libp2p transports when a PSK is supplied. +// +// Use this option when you want to *extend* the set of transports used by +// libp2p instead of replacing them. +var DefaultPrivateTransports = ChainOptions( + Transport(tcp.NewTCPTransport), + Transport(ws.New), +) + +// DefaultPeerstore configures libp2p to use the default peerstore. +var DefaultPeerstore Option = func(cfg *Config) error { + ps, err := pstoremem.NewPeerstore() + if err != nil { + return err + } + return cfg.Apply(Peerstore(ps)) +} + +// RandomIdentity generates a random identity. (default behaviour) +var RandomIdentity = func(cfg *Config) error { + priv, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return err + } + return cfg.Apply(Identity(priv)) +} + +// DefaultListenAddrs configures libp2p to use default listen address. +var DefaultListenAddrs = func(cfg *Config) error { + addrs := []string{ + "/ip4/0.0.0.0/tcp/0", + "/ip4/0.0.0.0/udp/0/quic-v1", + "/ip4/0.0.0.0/udp/0/quic-v1/webtransport", + "/ip4/0.0.0.0/udp/0/webrtc-direct", + "/ip6/::/tcp/0", + "/ip6/::/udp/0/quic-v1", + "/ip6/::/udp/0/quic-v1/webtransport", + "/ip6/::/udp/0/webrtc-direct", + } + listenAddrs := make([]multiaddr.Multiaddr, 0, len(addrs)) + for _, s := range addrs { + addr, err := multiaddr.NewMultiaddr(s) + if err != nil { + return err + } + listenAddrs = append(listenAddrs, addr) + } + return cfg.Apply(ListenAddrs(listenAddrs...)) +} + +// DefaultEnableRelay enables relay dialing and listening by default. +var DefaultEnableRelay = func(cfg *Config) error { + return cfg.Apply(EnableRelay()) +} + +var DefaultResourceManager = func(cfg *Config) error { + // Default memory limit: 1/8th of total memory, minimum 128MB, maximum 1GB + limits := rcmgr.DefaultLimits + SetDefaultServiceLimits(&limits) + mgr, err := rcmgr.NewResourceManager(rcmgr.NewFixedLimiter(limits.AutoScale())) + if err != nil { + return err + } + + return cfg.Apply(ResourceManager(mgr)) +} + +// DefaultConnectionManager creates a default connection manager +var DefaultConnectionManager = func(cfg *Config) error { + mgr, err := connmgr.NewConnManager(160, 192) + if err != nil { + return err + } + + return cfg.Apply(ConnectionManager(mgr)) +} + +// DefaultPrometheusRegisterer configures libp2p to use the default registerer +var DefaultPrometheusRegisterer = func(cfg *Config) error { + return cfg.Apply(PrometheusRegisterer(prometheus.DefaultRegisterer)) +} + +var defaultUDPBlackHoleDetector = func(cfg *Config) error { + // A black hole is a binary property. On a network if UDP dials are blocked, all dials will + // fail. So a low success rate of 5 out 100 dials is good enough. + return cfg.Apply(UDPBlackHoleSuccessCounter(&swarm.BlackHoleSuccessCounter{N: 100, MinSuccesses: 5, Name: "UDP"})) +} + +var defaultIPv6BlackHoleDetector = func(cfg *Config) error { + // A black hole is a binary property. On a network if there is no IPv6 connectivity, all + // dials will fail. So a low success rate of 5 out 100 dials is good enough. + return cfg.Apply(IPv6BlackHoleSuccessCounter(&swarm.BlackHoleSuccessCounter{N: 100, MinSuccesses: 5, Name: "IPv6"})) +} + +// Complete list of default options and when to fallback on them. +// +// Please *DON'T* specify default options any other way. Putting this all here +// makes tracking defaults *much* easier. +var defaults = []struct { + fallback func(cfg *Config) bool + opt Option +}{ + { + fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.ListenAddrs == nil }, + opt: DefaultListenAddrs, + }, + { + fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.PSK == nil }, + opt: DefaultTransports, + }, + { + fallback: func(cfg *Config) bool { return cfg.Transports == nil && cfg.PSK != nil }, + opt: DefaultPrivateTransports, + }, + { + fallback: func(cfg *Config) bool { return cfg.Muxers == nil }, + opt: DefaultMuxers, + }, + { + fallback: func(cfg *Config) bool { return !cfg.Insecure && cfg.SecurityTransports == nil }, + opt: DefaultSecurity, + }, + { + fallback: func(cfg *Config) bool { return cfg.PeerKey == nil }, + opt: RandomIdentity, + }, + { + fallback: func(cfg *Config) bool { return cfg.Peerstore == nil }, + opt: DefaultPeerstore, + }, + { + fallback: func(cfg *Config) bool { return !cfg.RelayCustom }, + opt: DefaultEnableRelay, + }, + { + fallback: func(cfg *Config) bool { return cfg.ResourceManager == nil }, + opt: DefaultResourceManager, + }, + { + fallback: func(cfg *Config) bool { return cfg.ConnManager == nil }, + opt: DefaultConnectionManager, + }, + { + fallback: func(cfg *Config) bool { return !cfg.DisableMetrics && cfg.PrometheusRegisterer == nil }, + opt: DefaultPrometheusRegisterer, + }, + { + fallback: func(cfg *Config) bool { + return !cfg.CustomUDPBlackHoleSuccessCounter && cfg.UDPBlackHoleSuccessCounter == nil + }, + opt: defaultUDPBlackHoleDetector, + }, + { + fallback: func(cfg *Config) bool { + return !cfg.CustomIPv6BlackHoleSuccessCounter && cfg.IPv6BlackHoleSuccessCounter == nil + }, + opt: defaultIPv6BlackHoleDetector, + }, +} + +// Defaults configures libp2p to use the default options. Can be combined with +// other options to *extend* the default options. +var Defaults Option = func(cfg *Config) error { + for _, def := range defaults { + if err := cfg.Apply(def.opt); err != nil { + return err + } + } + return nil +} + +// FallbackDefaults applies default options to the libp2p node if and only if no +// other relevant options have been applied. will be appended to the options +// passed into New. +var FallbackDefaults Option = func(cfg *Config) error { + for _, def := range defaults { + if !def.fallback(cfg) { + continue + } + if err := cfg.Apply(def.opt); err != nil { + return err + } + } + return nil +} diff --git a/libp2p_test.go b/libp2p_test.go index f10bbb9b75..64d12e7d40 100644 --- a/libp2p_test.go +++ b/libp2p_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2p import ( diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index b4db8c2091..b2f58d45ac 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -28,8 +28,6 @@ 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" - libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" - libp2pwebtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" "github.com/prometheus/client_golang/prometheus" logging "github.com/ipfs/go-log/v2" @@ -732,23 +730,6 @@ func (h *BasicHost) Addrs() []ma.Multiaddr { return h.addressManager.Addrs() } -// 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 { - ok, n := libp2pwebtransport.IsWebtransportMultiaddr(addr) - if !ok { - ok, n = libp2pwebrtc.IsWebRTCDirectMultiaddr(addr) - } - if ok && n > 0 { - out := addr - for i := 0; i < n; i++ { - out, _ = ma.SplitLast(out) - } - return out - } - return addr -} - // AllAddrs returns all the addresses the host is listening on except circuit addresses. func (h *BasicHost) AllAddrs() []ma.Multiaddr { return h.addressManager.DirectAddrs() diff --git a/p2p/transport/webrtc/connection.go b/p2p/transport/webrtc/connection.go index d75c309c51..3b8f584bfa 100644 --- a/p2p/transport/webrtc/connection.go +++ b/p2p/transport/webrtc/connection.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/listener.go b/p2p/transport/webrtc/listener.go index 0ec05ec0e9..0814bc385e 100644 --- a/p2p/transport/webrtc/listener.go +++ b/p2p/transport/webrtc/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/stream_test.go b/p2p/transport/webrtc/stream_test.go index 461ed27ff8..44c48e40e3 100644 --- a/p2p/transport/webrtc/stream_test.go +++ b/p2p/transport/webrtc/stream_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/transport.go b/p2p/transport/webrtc/transport.go index f3322c8117..68c7c2c13a 100644 --- a/p2p/transport/webrtc/transport.go +++ b/p2p/transport/webrtc/transport.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + // Package libp2pwebrtc implements the WebRTC transport for go-libp2p, // as described in https://github.com/libp2p/specs/tree/master/webrtc. package libp2pwebrtc @@ -104,8 +107,6 @@ type iceTimeouts struct { Keepalive time.Duration } -type ListenUDPFn func(network string, laddr *net.UDPAddr) (net.PacketConn, error) - func New(privKey ic.PrivKey, psk pnet.PSK, gater connmgr.ConnectionGater, rcmgr network.ResourceManager, listenUDP ListenUDPFn, opts ...Option) (*WebRTCTransport, error) { if psk != nil { log.Error("WebRTC doesn't support private networks yet.") @@ -638,35 +639,3 @@ func newWebRTCConnection(settings webrtc.SettingEngine, config webrtc.Configurat PeerConnectionClosedCh: connectionClosedCh, }, nil } - -// IsWebRTCDirectMultiaddr returns whether addr is a /webrtc-direct multiaddr with the count of certhashes -// in addr -func IsWebRTCDirectMultiaddr(addr ma.Multiaddr) (bool, int) { - var foundUDP, foundWebRTC bool - certHashCount := 0 - ma.ForEach(addr, func(c ma.Component) bool { - if !foundUDP { - if c.Protocol().Code == ma.P_UDP { - foundUDP = true - } - return true - } - if !foundWebRTC && foundUDP { - // protocol after udp must be webrtc-direct - if c.Protocol().Code != ma.P_WEBRTC_DIRECT { - return false - } - foundWebRTC = true - return true - } - if foundWebRTC { - if c.Protocol().Code == ma.P_CERTHASH { - certHashCount++ - } else { - return false - } - } - return true - }) - return foundUDP && foundWebRTC, certHashCount -} diff --git a/p2p/transport/webrtc/transport_shared.go b/p2p/transport/webrtc/transport_shared.go new file mode 100644 index 0000000000..8fc9f8d413 --- /dev/null +++ b/p2p/transport/webrtc/transport_shared.go @@ -0,0 +1,41 @@ +package libp2pwebrtc + +import ( + "net" + + ma "github.com/multiformats/go-multiaddr" +) + +type ListenUDPFn func(network string, laddr *net.UDPAddr) (net.PacketConn, error) + +// IsWebRTCDirectMultiaddr returns whether addr is a /webrtc-direct multiaddr with the count of certhashes +// in addr +func IsWebRTCDirectMultiaddr(addr ma.Multiaddr) (bool, int) { + var foundUDP, foundWebRTC bool + certHashCount := 0 + ma.ForEach(addr, func(c ma.Component) bool { + if !foundUDP { + if c.Protocol().Code == ma.P_UDP { + foundUDP = true + } + return true + } + if !foundWebRTC && foundUDP { + // protocol after udp must be webrtc-direct + if c.Protocol().Code != ma.P_WEBRTC_DIRECT { + return false + } + foundWebRTC = true + return true + } + if foundWebRTC { + if c.Protocol().Code == ma.P_CERTHASH { + certHashCount++ + } else { + return false + } + } + return true + }) + return foundUDP && foundWebRTC, certHashCount +} diff --git a/p2p/transport/webrtc/transport_test.go b/p2p/transport/webrtc/transport_test.go index 83f65c8c3f..94006b62e4 100644 --- a/p2p/transport/webrtc/transport_test.go +++ b/p2p/transport/webrtc/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( From 143693a985b9ea7ce67e81429e8ce1ecf2a05b28 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Fri, 9 May 2025 20:28:29 +0300 Subject: [PATCH 02/13] fix: omit all transports for wasm by default --- defaults_js.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/defaults_js.go b/defaults_js.go index 39cc43f492..5baad2e7cc 100644 --- a/defaults_js.go +++ b/defaults_js.go @@ -3,13 +3,5 @@ package libp2p -import ( - ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" - webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" -) - // Only WebSocket and WebTransport are supported in the browser. -var DefaultTransports = ChainOptions( - Transport(ws.New), - Transport(webtransport.New), -) +var DefaultTransports = ChainOptions() From bb916bbb996cac583a0065f8e1d5733fa1b99285 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 20:38:39 +0300 Subject: [PATCH 03/13] exclude tests and quic stuff from WASM target --- config/config.go | 342 +--------- config/config_js.go | 319 +++++++++ config/config_shared.go | 360 ++++++++++ options.go | 624 +---------------- options_shared.go | 629 ++++++++++++++++++ p2p/http/libp2phttp_test.go | 3 + p2p/net/connmgr/bench_test.go | 3 + p2p/net/connmgr/connmgr_test.go | 3 + p2p/net/swarm/dial_test.go | 3 + p2p/net/swarm/dial_worker_test.go | 3 + p2p/net/swarm/simul_test.go | 3 + p2p/net/swarm/swarm_addr_test.go | 3 + p2p/net/swarm/swarm_dial_test.go | 3 + p2p/net/swarm/swarm_event_test.go | 3 + p2p/net/swarm/swarm_net_test.go | 3 + p2p/net/swarm/swarm_notif_test.go | 3 + p2p/net/swarm/swarm_test.go | 3 + p2p/net/swarm/testing/testing.go | 3 + p2p/net/swarm/testing/testing_test.go | 3 + p2p/net/swarm/transport_test.go | 3 + p2p/protocol/ping/ping_test.go | 3 + p2p/test/backpressure/backpressure_test.go | 3 + p2p/test/basichost/basic_host_test.go | 3 + p2p/test/notifications/notification_test.go | 3 + p2p/test/quic/quic_test.go | 3 + p2p/test/reconnects/reconnect_test.go | 3 + p2p/test/transport/deadline_test.go | 3 + p2p/test/transport/gating_test.go | 3 + .../transport/mock_connection_gater_test.go | 2 + p2p/test/transport/rcmgr_test.go | 3 + p2p/test/transport/transport_test.go | 3 + p2p/transport/quic/cmd/client/main.go | 3 + p2p/transport/quic/cmd/lib/lib.go | 3 + p2p/transport/quic/cmd/lib/lib_test.go | 3 + p2p/transport/quic/cmd/server/main.go | 3 + p2p/transport/quic/conn.go | 3 + p2p/transport/quic/conn_test.go | 3 + p2p/transport/quic/listener.go | 3 + p2p/transport/quic/listener_test.go | 3 + p2p/transport/quic/stream.go | 3 + p2p/transport/quic/transport.go | 3 + p2p/transport/quic/transport_test.go | 3 + p2p/transport/quic/virtuallistener.go | 3 + p2p/transport/quicreuse/config.go | 3 + p2p/transport/quicreuse/connmgr.go | 3 + p2p/transport/quicreuse/connmgr_test.go | 3 + p2p/transport/quicreuse/listener.go | 3 + p2p/transport/quicreuse/nonquic_packetconn.go | 3 + p2p/transport/quicreuse/options.go | 3 + p2p/transport/quicreuse/quic_multiaddr.go | 3 + .../quicreuse/quic_multiaddr_test.go | 3 + p2p/transport/quicreuse/reuse.go | 3 + p2p/transport/quicreuse/reuse_test.go | 3 + p2p/transport/quicreuse/tracer.go | 3 + p2p/transport/quicreuse/tracer_test.go | 3 + 55 files changed, 1464 insertions(+), 959 deletions(-) create mode 100644 config/config_js.go create mode 100644 config/config_shared.go create mode 100644 options_shared.go diff --git a/config/config.go b/config/config.go index 607dceba49..ea638145a2 100644 --- a/config/config.go +++ b/config/config.go @@ -1,12 +1,13 @@ +//go:build !js +// +build !js + package config import ( "context" - "crypto/rand" "errors" "fmt" "net" - "slices" "time" "github.com/libp2p/go-libp2p/core/connmgr" @@ -18,17 +19,13 @@ import ( "github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peerstore" "github.com/libp2p/go-libp2p/core/pnet" - "github.com/libp2p/go-libp2p/core/protocol" "github.com/libp2p/go-libp2p/core/routing" "github.com/libp2p/go-libp2p/core/sec" "github.com/libp2p/go-libp2p/core/sec/insecure" "github.com/libp2p/go-libp2p/core/transport" - "github.com/libp2p/go-libp2p/p2p/host/autonat" "github.com/libp2p/go-libp2p/p2p/host/autorelay" bhost "github.com/libp2p/go-libp2p/p2p/host/basic" - blankhost "github.com/libp2p/go-libp2p/p2p/host/blank" "github.com/libp2p/go-libp2p/p2p/host/eventbus" - "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" routed "github.com/libp2p/go-libp2p/p2p/host/routed" "github.com/libp2p/go-libp2p/p2p/net/swarm" @@ -40,38 +37,14 @@ import ( "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" "github.com/libp2p/go-libp2p/p2p/transport/tcpreuse" libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" - "github.com/prometheus/client_golang/prometheus" - ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" + "github.com/prometheus/client_golang/prometheus" "github.com/quic-go/quic-go" "go.uber.org/fx" "go.uber.org/fx/fxevent" ) -// AddrsFactory is a function that takes a set of multiaddrs we're listening on and -// returns the set of multiaddrs we should advertise to the network. -type AddrsFactory = bhost.AddrsFactory - -// NATManagerC is a NATManager constructor. -type NATManagerC func(network.Network) bhost.NATManager - -type RoutingC func(host.Host) (routing.PeerRouting, error) - -// AutoNATConfig defines the AutoNAT behavior for the libp2p host. -type AutoNATConfig struct { - ForceReachability *network.Reachability - EnableService bool - ThrottleGlobalLimit int - ThrottlePeerLimit int - ThrottleInterval time.Duration -} - -type Security struct { - ID protocol.ID - Constructor interface{} -} - // Config describes a set of settings for a libp2p node // // This is *not* a stable interface. Use the options defined in the root @@ -150,140 +123,6 @@ type Config struct { ShareTCPListener bool } -func (cfg *Config) makeSwarm(eventBus event.Bus, enableMetrics bool) (*swarm.Swarm, error) { - if cfg.Peerstore == nil { - return nil, fmt.Errorf("no peerstore specified") - } - - // Check this early. Prevents us from even *starting* without verifying this. - if pnet.ForcePrivateNetwork && len(cfg.PSK) == 0 { - log.Error("tried to create a libp2p node with no Private" + - " Network Protector but usage of Private Networks" + - " is forced by the environment") - // Note: This is *also* checked the upgrader itself, so it'll be - // enforced even *if* you don't use the libp2p constructor. - return nil, pnet.ErrNotInPrivateNetwork - } - - if cfg.PeerKey == nil { - return nil, fmt.Errorf("no peer key specified") - } - - // Obtain Peer ID from public key - pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic()) - if err != nil { - return nil, err - } - - if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil { - return nil, err - } - if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil { - return nil, err - } - - opts := append(cfg.SwarmOpts, - swarm.WithUDPBlackHoleSuccessCounter(cfg.UDPBlackHoleSuccessCounter), - swarm.WithIPv6BlackHoleSuccessCounter(cfg.IPv6BlackHoleSuccessCounter), - ) - if cfg.Reporter != nil { - opts = append(opts, swarm.WithMetrics(cfg.Reporter)) - } - if cfg.ConnectionGater != nil { - opts = append(opts, swarm.WithConnectionGater(cfg.ConnectionGater)) - } - if cfg.DialTimeout != 0 { - opts = append(opts, swarm.WithDialTimeout(cfg.DialTimeout)) - } - if cfg.ResourceManager != nil { - opts = append(opts, swarm.WithResourceManager(cfg.ResourceManager)) - } - if cfg.MultiaddrResolver != nil { - opts = append(opts, swarm.WithMultiaddrResolver(cfg.MultiaddrResolver)) - } - if cfg.DialRanker != nil { - opts = append(opts, swarm.WithDialRanker(cfg.DialRanker)) - } - - if enableMetrics { - opts = append(opts, - swarm.WithMetricsTracer(swarm.NewMetricsTracer(swarm.WithRegisterer(cfg.PrometheusRegisterer)))) - } - // TODO: Make the swarm implementation configurable. - return swarm.NewSwarm(pid, cfg.Peerstore, eventBus, opts...) -} - -func (cfg *Config) makeAutoNATV2Host() (host.Host, error) { - autonatPrivKey, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return nil, err - } - ps, err := pstoremem.NewPeerstore() - if err != nil { - return nil, err - } - - autoNatCfg := Config{ - Transports: cfg.Transports, - Muxers: cfg.Muxers, - SecurityTransports: cfg.SecurityTransports, - Insecure: cfg.Insecure, - PSK: cfg.PSK, - ConnectionGater: cfg.ConnectionGater, - Reporter: cfg.Reporter, - PeerKey: autonatPrivKey, - Peerstore: ps, - DialRanker: swarm.NoDelayDialRanker, - UDPBlackHoleSuccessCounter: cfg.UDPBlackHoleSuccessCounter, - IPv6BlackHoleSuccessCounter: cfg.IPv6BlackHoleSuccessCounter, - ResourceManager: cfg.ResourceManager, - SwarmOpts: []swarm.Option{ - // Don't update black hole state for failed autonat dials - swarm.WithReadOnlyBlackHoleDetector(), - }, - } - fxopts, err := autoNatCfg.addTransports() - if err != nil { - return nil, err - } - var dialerHost host.Host - fxopts = append(fxopts, - fx.Provide(eventbus.NewBus), - fx.Provide(func(lifecycle fx.Lifecycle, b event.Bus) (*swarm.Swarm, error) { - lifecycle.Append(fx.Hook{ - OnStop: func(context.Context) error { - return ps.Close() - }}) - sw, err := autoNatCfg.makeSwarm(b, false) - return sw, err - }), - fx.Provide(func(sw *swarm.Swarm) *blankhost.BlankHost { - return blankhost.NewBlankHost(sw) - }), - fx.Provide(func(bh *blankhost.BlankHost) host.Host { - return bh - }), - fx.Provide(func() crypto.PrivKey { return autonatPrivKey }), - fx.Provide(func(bh host.Host) peer.ID { return bh.ID() }), - fx.Invoke(func(bh *blankhost.BlankHost) { - dialerHost = bh - }), - ) - app := fx.New(fxopts...) - if err := app.Err(); err != nil { - return nil, err - } - err = app.Start(context.Background()) - if err != nil { - return nil, err - } - go func() { - <-dialerHost.Network().(*swarm.Swarm).Done() - app.Stop(context.Background()) - }() - return dialerHost, nil -} - func (cfg *Config) addTransports() ([]fx.Option, error) { fxopts := []fx.Option{ fx.WithLogger(func() fxevent.Logger { return getFXLogger() }), @@ -413,59 +252,6 @@ func (cfg *Config) addTransports() ([]fx.Option, error) { return fxopts, nil } -func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.BasicHost, error) { - var autonatv2Dialer host.Host - if cfg.EnableAutoNATv2 { - ah, err := cfg.makeAutoNATV2Host() - if err != nil { - return nil, err - } - autonatv2Dialer = ah - } - h, err := bhost.NewHost(swrm, &bhost.HostOpts{ - EventBus: eventBus, - ConnManager: cfg.ConnManager, - AddrsFactory: cfg.AddrsFactory, - NATManager: cfg.NATManager, - EnablePing: !cfg.DisablePing, - UserAgent: cfg.UserAgent, - ProtocolVersion: cfg.ProtocolVersion, - EnableHolePunching: cfg.EnableHolePunching, - HolePunchingOptions: cfg.HolePunchingOptions, - EnableRelayService: cfg.EnableRelayService, - RelayServiceOpts: cfg.RelayServiceOpts, - EnableMetrics: !cfg.DisableMetrics, - PrometheusRegisterer: cfg.PrometheusRegisterer, - DisableIdentifyAddressDiscovery: cfg.DisableIdentifyAddressDiscovery, - EnableAutoNATv2: cfg.EnableAutoNATv2, - AutoNATv2Dialer: autonatv2Dialer, - }) - if err != nil { - return nil, err - } - return h, nil -} - -func (cfg *Config) validate() error { - if cfg.EnableAutoRelay && !cfg.Relay { - return fmt.Errorf("cannot enable autorelay; relay is not enabled") - } - // If possible check that the resource manager conn limit is higher than the - // limit set in the conn manager. - if l, ok := cfg.ResourceManager.(connmgr.GetConnLimiter); ok { - err := cfg.ConnManager.CheckLimit(l) - if err != nil { - log.Warn(fmt.Sprintf("rcmgr limit conflicts with connmgr limit: %v", err)) - } - } - - if len(cfg.PSK) > 0 && cfg.ShareTCPListener { - return errors.New("cannot use shared TCP listener with PSK") - } - - return nil -} - // NewNode constructs a new libp2p Host from the Config. // // This function consumes the config. Do not reuse it (really!). @@ -597,123 +383,3 @@ func (cfg *Config) NewNode() (host.Host, error) { } return &closableBasicHost{App: app, BasicHost: bh}, nil } - -func (cfg *Config) addAutoNAT(h *bhost.BasicHost) error { - // Only use public addresses for autonat - addrFunc := func() []ma.Multiaddr { - return slices.DeleteFunc(h.AllAddrs(), func(a ma.Multiaddr) bool { return !manet.IsPublicAddr(a) }) - } - if cfg.AddrsFactory != nil { - addrFunc = func() []ma.Multiaddr { - return slices.DeleteFunc( - slices.Clone(cfg.AddrsFactory(h.AllAddrs())), - func(a ma.Multiaddr) bool { return !manet.IsPublicAddr(a) }) - } - } - autonatOpts := []autonat.Option{ - autonat.UsingAddresses(addrFunc), - } - if !cfg.DisableMetrics { - autonatOpts = append(autonatOpts, autonat.WithMetricsTracer( - autonat.NewMetricsTracer(autonat.WithRegisterer(cfg.PrometheusRegisterer)), - )) - } - if cfg.AutoNATConfig.ThrottleInterval != 0 { - autonatOpts = append(autonatOpts, - autonat.WithThrottling(cfg.AutoNATConfig.ThrottleGlobalLimit, cfg.AutoNATConfig.ThrottleInterval), - autonat.WithPeerThrottling(cfg.AutoNATConfig.ThrottlePeerLimit)) - } - if cfg.AutoNATConfig.EnableService { - autonatPrivKey, _, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return err - } - ps, err := pstoremem.NewPeerstore() - if err != nil { - return err - } - - // Pull out the pieces of the config that we _actually_ care about. - // Specifically, don't set up things like listeners, identify, etc. - autoNatCfg := Config{ - Transports: cfg.Transports, - Muxers: cfg.Muxers, - SecurityTransports: cfg.SecurityTransports, - Insecure: cfg.Insecure, - PSK: cfg.PSK, - ConnectionGater: cfg.ConnectionGater, - Reporter: cfg.Reporter, - PeerKey: autonatPrivKey, - Peerstore: ps, - DialRanker: swarm.NoDelayDialRanker, - ResourceManager: cfg.ResourceManager, - SwarmOpts: []swarm.Option{ - swarm.WithUDPBlackHoleSuccessCounter(nil), - swarm.WithIPv6BlackHoleSuccessCounter(nil), - }, - } - - fxopts, err := autoNatCfg.addTransports() - if err != nil { - return err - } - var dialer *swarm.Swarm - - fxopts = append(fxopts, - fx.Provide(eventbus.NewBus), - fx.Provide(func(lifecycle fx.Lifecycle, b event.Bus) (*swarm.Swarm, error) { - lifecycle.Append(fx.Hook{ - OnStop: func(context.Context) error { - return ps.Close() - }}) - var err error - dialer, err = autoNatCfg.makeSwarm(b, false) - return dialer, err - - }), - fx.Provide(func(s *swarm.Swarm) peer.ID { return s.LocalPeer() }), - fx.Provide(func() crypto.PrivKey { return autonatPrivKey }), - ) - app := fx.New(fxopts...) - if err := app.Err(); err != nil { - return err - } - err = app.Start(context.Background()) - if err != nil { - return err - } - go func() { - <-dialer.Done() // The swarm used for autonat has closed, we can cleanup now - app.Stop(context.Background()) - }() - autonatOpts = append(autonatOpts, autonat.EnableService(dialer)) - } - if cfg.AutoNATConfig.ForceReachability != nil { - autonatOpts = append(autonatOpts, autonat.WithReachability(*cfg.AutoNATConfig.ForceReachability)) - } - - autonat, err := autonat.New(h, autonatOpts...) - if err != nil { - return fmt.Errorf("autonat init failed: %w", err) - } - h.SetAutoNat(autonat) - return nil -} - -// Option is a libp2p config option that can be given to the libp2p constructor -// (`libp2p.New`). -type Option func(cfg *Config) error - -// Apply applies the given options to the config, returning the first error -// encountered (if any). -func (cfg *Config) Apply(opts ...Option) error { - for _, opt := range opts { - if opt == nil { - continue - } - if err := opt(cfg); err != nil { - return err - } - } - return nil -} diff --git a/config/config_js.go b/config/config_js.go new file mode 100644 index 0000000000..f88af0a7fd --- /dev/null +++ b/config/config_js.go @@ -0,0 +1,319 @@ +//go:build js +// +build js + +package config + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/libp2p/go-libp2p/core/connmgr" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/event" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/metrics" + "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/core/pnet" + "github.com/libp2p/go-libp2p/core/routing" + "github.com/libp2p/go-libp2p/core/sec" + "github.com/libp2p/go-libp2p/core/sec/insecure" + "github.com/libp2p/go-libp2p/core/transport" + "github.com/libp2p/go-libp2p/p2p/host/autorelay" + bhost "github.com/libp2p/go-libp2p/p2p/host/basic" + "github.com/libp2p/go-libp2p/p2p/host/eventbus" + rcmgr "github.com/libp2p/go-libp2p/p2p/host/resource-manager" + routed "github.com/libp2p/go-libp2p/p2p/host/routed" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" + circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" + relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" + "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" + "github.com/libp2p/go-libp2p/p2p/protocol/identify" + "github.com/libp2p/go-libp2p/p2p/transport/tcpreuse" + ma "github.com/multiformats/go-multiaddr" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/fx" + "go.uber.org/fx/fxevent" +) + +// Config describes a set of settings for a libp2p node +// +// This is *not* a stable interface. Use the options defined in the root +// package. +type Config struct { + // UserAgent is the identifier this node will send to other peers when + // identifying itself, e.g. via the identify protocol. + // + // Set it via the UserAgent option function. + UserAgent string + + // ProtocolVersion is the protocol version that identifies the family + // of protocols used by the peer in the Identify protocol. It is set + // using the [ProtocolVersion] option. + ProtocolVersion string + + PeerKey crypto.PrivKey + + Transports []fx.Option + Muxers []tptu.StreamMuxer + SecurityTransports []Security + Insecure bool + PSK pnet.PSK + + DialTimeout time.Duration + + RelayCustom bool + Relay bool // should the relay transport be used + + EnableRelayService bool // should we run a circuitv2 relay (if publicly reachable) + RelayServiceOpts []relayv2.Option + + ListenAddrs []ma.Multiaddr + AddrsFactory bhost.AddrsFactory + ConnectionGater connmgr.ConnectionGater + + ConnManager connmgr.ConnManager + ResourceManager network.ResourceManager + + NATManager NATManagerC + Peerstore peerstore.Peerstore + Reporter metrics.Reporter + + MultiaddrResolver network.MultiaddrDNSResolver + + DisablePing bool + + Routing RoutingC + + EnableAutoRelay bool + AutoRelayOpts []autorelay.Option + AutoNATConfig + + EnableHolePunching bool + HolePunchingOptions []holepunch.Option + + DisableMetrics bool + PrometheusRegisterer prometheus.Registerer + + DialRanker network.DialRanker + + SwarmOpts []swarm.Option + + DisableIdentifyAddressDiscovery bool + + EnableAutoNATv2 bool + + UDPBlackHoleSuccessCounter *swarm.BlackHoleSuccessCounter + CustomUDPBlackHoleSuccessCounter bool + IPv6BlackHoleSuccessCounter *swarm.BlackHoleSuccessCounter + CustomIPv6BlackHoleSuccessCounter bool + + UserFxOptions []fx.Option + + ShareTCPListener bool +} + +func (cfg *Config) addTransports() ([]fx.Option, error) { + fxopts := []fx.Option{ + fx.WithLogger(func() fxevent.Logger { return getFXLogger() }), + fx.Provide(fx.Annotate(tptu.New, fx.ParamTags(`name:"security"`))), + fx.Supply(cfg.Muxers), + fx.Provide(func() connmgr.ConnectionGater { return cfg.ConnectionGater }), + fx.Provide(func() pnet.PSK { return cfg.PSK }), + fx.Provide(func() network.ResourceManager { return cfg.ResourceManager }), + fx.Provide(func(upgrader transport.Upgrader) *tcpreuse.ConnMgr { + if !cfg.ShareTCPListener { + return nil + } + return tcpreuse.NewConnMgr(tcpreuse.EnvReuseportVal, upgrader) + }), + } + fxopts = append(fxopts, cfg.Transports...) + if cfg.Insecure { + fxopts = append(fxopts, + fx.Provide( + fx.Annotate( + func(id peer.ID, priv crypto.PrivKey) []sec.SecureTransport { + return []sec.SecureTransport{insecure.NewWithIdentity(insecure.ID, id, priv)} + }, + fx.ResultTags(`name:"security"`), + ), + ), + ) + } else { + // fx groups are unordered, but we need to preserve the order of the security transports + // First of all, we construct the security transports that are needed, + // and save them to a group call security_unordered. + for _, s := range cfg.SecurityTransports { + fxName := fmt.Sprintf(`name:"security_%s"`, s.ID) + fxopts = append(fxopts, fx.Supply(fx.Annotate(s.ID, fx.ResultTags(fxName)))) + fxopts = append(fxopts, + fx.Provide(fx.Annotate( + s.Constructor, + fx.ParamTags(fxName), + fx.As(new(sec.SecureTransport)), + fx.ResultTags(`group:"security_unordered"`), + )), + ) + } + // Then we consume the group security_unordered, and order them by the user's preference. + fxopts = append(fxopts, fx.Provide( + fx.Annotate( + func(secs []sec.SecureTransport) ([]sec.SecureTransport, error) { + if len(secs) != len(cfg.SecurityTransports) { + return nil, errors.New("inconsistent length for security transports") + } + t := make([]sec.SecureTransport, 0, len(secs)) + for _, s := range cfg.SecurityTransports { + for _, st := range secs { + if s.ID != st.ID() { + continue + } + t = append(t, st) + } + } + return t, nil + }, + fx.ParamTags(`group:"security_unordered"`), + fx.ResultTags(`name:"security"`), + ))) + } + + fxopts = append(fxopts, fx.Provide(PrivKeyToStatelessResetKey)) + fxopts = append(fxopts, fx.Provide(PrivKeyToTokenGeneratorKey)) + + fxopts = append(fxopts, fx.Invoke( + fx.Annotate( + func(swrm *swarm.Swarm, tpts []transport.Transport) error { + for _, t := range tpts { + if err := swrm.AddTransport(t); err != nil { + return err + } + } + return nil + }, + fx.ParamTags("", `group:"transport"`), + )), + ) + if cfg.Relay { + fxopts = append(fxopts, fx.Invoke(circuitv2.AddTransport)) + } + return fxopts, nil +} + +// NewNode constructs a new libp2p Host from the Config. +// +// This function consumes the config. Do not reuse it (really!). +func (cfg *Config) NewNode() (host.Host, error) { + + validateErr := cfg.validate() + if validateErr != nil { + if cfg.ResourceManager != nil { + cfg.ResourceManager.Close() + } + if cfg.ConnManager != nil { + cfg.ConnManager.Close() + } + if cfg.Peerstore != nil { + cfg.Peerstore.Close() + } + + return nil, validateErr + } + + if !cfg.DisableMetrics { + rcmgr.MustRegisterWith(cfg.PrometheusRegisterer) + } + + fxopts := []fx.Option{ + fx.Provide(func() event.Bus { + return eventbus.NewBus(eventbus.WithMetricsTracer(eventbus.NewMetricsTracer(eventbus.WithRegisterer(cfg.PrometheusRegisterer)))) + }), + fx.Provide(func() crypto.PrivKey { + return cfg.PeerKey + }), + + fx.Provide(cfg.newBasicHost), + fx.Provide(func(bh *bhost.BasicHost) identify.IDService { + return bh.IDService() + }), + fx.Provide(func(bh *bhost.BasicHost) host.Host { + return bh + }), + fx.Provide(func(h *swarm.Swarm) peer.ID { return h.LocalPeer() }), + } + transportOpts, err := cfg.addTransports() + if err != nil { + return nil, err + } + fxopts = append(fxopts, transportOpts...) + + // Configure routing + if cfg.Routing != nil { + fxopts = append(fxopts, + fx.Provide(cfg.Routing), + fx.Provide(func(h host.Host, router routing.PeerRouting) *routed.RoutedHost { + return routed.Wrap(h, router) + }), + ) + } + + // enable autorelay + fxopts = append(fxopts, + fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) error { + if cfg.EnableAutoRelay { + if !cfg.DisableMetrics { + mt := autorelay.WithMetricsTracer( + autorelay.NewMetricsTracer(autorelay.WithRegisterer(cfg.PrometheusRegisterer))) + mtOpts := []autorelay.Option{mt} + cfg.AutoRelayOpts = append(mtOpts, cfg.AutoRelayOpts...) + } + + ar, err := autorelay.NewAutoRelay(h, cfg.AutoRelayOpts...) + if err != nil { + return err + } + lifecycle.Append(fx.StartStopHook(ar.Start, ar.Close)) + return nil + } + return nil + }), + ) + + var bh *bhost.BasicHost + fxopts = append(fxopts, fx.Invoke(func(bho *bhost.BasicHost) { bh = bho })) + fxopts = append(fxopts, fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) { + lifecycle.Append(fx.StartHook(h.Start)) + })) + + var rh *routed.RoutedHost + if cfg.Routing != nil { + fxopts = append(fxopts, fx.Invoke(func(bho *routed.RoutedHost) { rh = bho })) + } + + fxopts = append(fxopts, cfg.UserFxOptions...) + + app := fx.New(fxopts...) + if err := app.Start(context.Background()); err != nil { + return nil, err + } + + if err := cfg.addAutoNAT(bh); err != nil { + app.Stop(context.Background()) + if cfg.Routing != nil { + rh.Close() + } else { + bh.Close() + } + return nil, err + } + + if cfg.Routing != nil { + return &closableRoutedHost{App: app, RoutedHost: rh}, nil + } + return &closableBasicHost{App: app, BasicHost: bh}, nil +} diff --git a/config/config_shared.go b/config/config_shared.go new file mode 100644 index 0000000000..0256a2314f --- /dev/null +++ b/config/config_shared.go @@ -0,0 +1,360 @@ +package config + +import ( + "context" + "crypto/rand" + "errors" + "fmt" + "slices" + "time" + + "github.com/libp2p/go-libp2p/core/connmgr" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/event" + "github.com/libp2p/go-libp2p/core/host" + "github.com/libp2p/go-libp2p/core/network" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/libp2p/go-libp2p/core/pnet" + "github.com/libp2p/go-libp2p/core/protocol" + "github.com/libp2p/go-libp2p/core/routing" + "github.com/libp2p/go-libp2p/p2p/host/autonat" + bhost "github.com/libp2p/go-libp2p/p2p/host/basic" + blankhost "github.com/libp2p/go-libp2p/p2p/host/blank" + "github.com/libp2p/go-libp2p/p2p/host/eventbus" + "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + + ma "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" + "go.uber.org/fx" +) + +// AddrsFactory is a function that takes a set of multiaddrs we're listening on and +// returns the set of multiaddrs we should advertise to the network. +type AddrsFactory = bhost.AddrsFactory + +// NATManagerC is a NATManager constructor. +type NATManagerC func(network.Network) bhost.NATManager + +type RoutingC func(host.Host) (routing.PeerRouting, error) + +// AutoNATConfig defines the AutoNAT behavior for the libp2p host. +type AutoNATConfig struct { + ForceReachability *network.Reachability + EnableService bool + ThrottleGlobalLimit int + ThrottlePeerLimit int + ThrottleInterval time.Duration +} + +type Security struct { + ID protocol.ID + Constructor interface{} +} + +func (cfg *Config) makeSwarm(eventBus event.Bus, enableMetrics bool) (*swarm.Swarm, error) { + if cfg.Peerstore == nil { + return nil, fmt.Errorf("no peerstore specified") + } + + // Check this early. Prevents us from even *starting* without verifying this. + if pnet.ForcePrivateNetwork && len(cfg.PSK) == 0 { + log.Error("tried to create a libp2p node with no Private" + + " Network Protector but usage of Private Networks" + + " is forced by the environment") + // Note: This is *also* checked the upgrader itself, so it'll be + // enforced even *if* you don't use the libp2p constructor. + return nil, pnet.ErrNotInPrivateNetwork + } + + if cfg.PeerKey == nil { + return nil, fmt.Errorf("no peer key specified") + } + + // Obtain Peer ID from public key + pid, err := peer.IDFromPublicKey(cfg.PeerKey.GetPublic()) + if err != nil { + return nil, err + } + + if err := cfg.Peerstore.AddPrivKey(pid, cfg.PeerKey); err != nil { + return nil, err + } + if err := cfg.Peerstore.AddPubKey(pid, cfg.PeerKey.GetPublic()); err != nil { + return nil, err + } + + opts := append(cfg.SwarmOpts, + swarm.WithUDPBlackHoleSuccessCounter(cfg.UDPBlackHoleSuccessCounter), + swarm.WithIPv6BlackHoleSuccessCounter(cfg.IPv6BlackHoleSuccessCounter), + ) + if cfg.Reporter != nil { + opts = append(opts, swarm.WithMetrics(cfg.Reporter)) + } + if cfg.ConnectionGater != nil { + opts = append(opts, swarm.WithConnectionGater(cfg.ConnectionGater)) + } + if cfg.DialTimeout != 0 { + opts = append(opts, swarm.WithDialTimeout(cfg.DialTimeout)) + } + if cfg.ResourceManager != nil { + opts = append(opts, swarm.WithResourceManager(cfg.ResourceManager)) + } + if cfg.MultiaddrResolver != nil { + opts = append(opts, swarm.WithMultiaddrResolver(cfg.MultiaddrResolver)) + } + if cfg.DialRanker != nil { + opts = append(opts, swarm.WithDialRanker(cfg.DialRanker)) + } + + if enableMetrics { + opts = append(opts, + swarm.WithMetricsTracer(swarm.NewMetricsTracer(swarm.WithRegisterer(cfg.PrometheusRegisterer)))) + } + // TODO: Make the swarm implementation configurable. + return swarm.NewSwarm(pid, cfg.Peerstore, eventBus, opts...) +} + +func (cfg *Config) makeAutoNATV2Host() (host.Host, error) { + autonatPrivKey, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, err + } + ps, err := pstoremem.NewPeerstore() + if err != nil { + return nil, err + } + + autoNatCfg := Config{ + Transports: cfg.Transports, + Muxers: cfg.Muxers, + SecurityTransports: cfg.SecurityTransports, + Insecure: cfg.Insecure, + PSK: cfg.PSK, + ConnectionGater: cfg.ConnectionGater, + Reporter: cfg.Reporter, + PeerKey: autonatPrivKey, + Peerstore: ps, + DialRanker: swarm.NoDelayDialRanker, + UDPBlackHoleSuccessCounter: cfg.UDPBlackHoleSuccessCounter, + IPv6BlackHoleSuccessCounter: cfg.IPv6BlackHoleSuccessCounter, + ResourceManager: cfg.ResourceManager, + SwarmOpts: []swarm.Option{ + // Don't update black hole state for failed autonat dials + swarm.WithReadOnlyBlackHoleDetector(), + }, + } + fxopts, err := autoNatCfg.addTransports() + if err != nil { + return nil, err + } + var dialerHost host.Host + fxopts = append(fxopts, + fx.Provide(eventbus.NewBus), + fx.Provide(func(lifecycle fx.Lifecycle, b event.Bus) (*swarm.Swarm, error) { + lifecycle.Append(fx.Hook{ + OnStop: func(context.Context) error { + return ps.Close() + }}) + sw, err := autoNatCfg.makeSwarm(b, false) + return sw, err + }), + fx.Provide(func(sw *swarm.Swarm) *blankhost.BlankHost { + return blankhost.NewBlankHost(sw) + }), + fx.Provide(func(bh *blankhost.BlankHost) host.Host { + return bh + }), + fx.Provide(func() crypto.PrivKey { return autonatPrivKey }), + fx.Provide(func(bh host.Host) peer.ID { return bh.ID() }), + fx.Invoke(func(bh *blankhost.BlankHost) { + dialerHost = bh + }), + ) + app := fx.New(fxopts...) + if err := app.Err(); err != nil { + return nil, err + } + err = app.Start(context.Background()) + if err != nil { + return nil, err + } + go func() { + <-dialerHost.Network().(*swarm.Swarm).Done() + app.Stop(context.Background()) + }() + return dialerHost, nil +} + +func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.BasicHost, error) { + var autonatv2Dialer host.Host + if cfg.EnableAutoNATv2 { + ah, err := cfg.makeAutoNATV2Host() + if err != nil { + return nil, err + } + autonatv2Dialer = ah + } + h, err := bhost.NewHost(swrm, &bhost.HostOpts{ + EventBus: eventBus, + ConnManager: cfg.ConnManager, + AddrsFactory: cfg.AddrsFactory, + NATManager: cfg.NATManager, + EnablePing: !cfg.DisablePing, + UserAgent: cfg.UserAgent, + ProtocolVersion: cfg.ProtocolVersion, + EnableHolePunching: cfg.EnableHolePunching, + HolePunchingOptions: cfg.HolePunchingOptions, + EnableRelayService: cfg.EnableRelayService, + RelayServiceOpts: cfg.RelayServiceOpts, + EnableMetrics: !cfg.DisableMetrics, + PrometheusRegisterer: cfg.PrometheusRegisterer, + DisableIdentifyAddressDiscovery: cfg.DisableIdentifyAddressDiscovery, + EnableAutoNATv2: cfg.EnableAutoNATv2, + AutoNATv2Dialer: autonatv2Dialer, + }) + if err != nil { + return nil, err + } + return h, nil +} + +func (cfg *Config) validate() error { + if cfg.EnableAutoRelay && !cfg.Relay { + return fmt.Errorf("cannot enable autorelay; relay is not enabled") + } + // If possible check that the resource manager conn limit is higher than the + // limit set in the conn manager. + if l, ok := cfg.ResourceManager.(connmgr.GetConnLimiter); ok { + err := cfg.ConnManager.CheckLimit(l) + if err != nil { + log.Warn(fmt.Sprintf("rcmgr limit conflicts with connmgr limit: %v", err)) + } + } + + if len(cfg.PSK) > 0 && cfg.ShareTCPListener { + return errors.New("cannot use shared TCP listener with PSK") + } + + return nil +} + +func (cfg *Config) addAutoNAT(h *bhost.BasicHost) error { + // Only use public addresses for autonat + addrFunc := func() []ma.Multiaddr { + return slices.DeleteFunc(h.AllAddrs(), func(a ma.Multiaddr) bool { return !manet.IsPublicAddr(a) }) + } + if cfg.AddrsFactory != nil { + addrFunc = func() []ma.Multiaddr { + return slices.DeleteFunc( + slices.Clone(cfg.AddrsFactory(h.AllAddrs())), + func(a ma.Multiaddr) bool { return !manet.IsPublicAddr(a) }) + } + } + autonatOpts := []autonat.Option{ + autonat.UsingAddresses(addrFunc), + } + if !cfg.DisableMetrics { + autonatOpts = append(autonatOpts, autonat.WithMetricsTracer( + autonat.NewMetricsTracer(autonat.WithRegisterer(cfg.PrometheusRegisterer)), + )) + } + if cfg.AutoNATConfig.ThrottleInterval != 0 { + autonatOpts = append(autonatOpts, + autonat.WithThrottling(cfg.AutoNATConfig.ThrottleGlobalLimit, cfg.AutoNATConfig.ThrottleInterval), + autonat.WithPeerThrottling(cfg.AutoNATConfig.ThrottlePeerLimit)) + } + if cfg.AutoNATConfig.EnableService { + autonatPrivKey, _, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return err + } + ps, err := pstoremem.NewPeerstore() + if err != nil { + return err + } + + // Pull out the pieces of the config that we _actually_ care about. + // Specifically, don't set up things like listeners, identify, etc. + autoNatCfg := Config{ + Transports: cfg.Transports, + Muxers: cfg.Muxers, + SecurityTransports: cfg.SecurityTransports, + Insecure: cfg.Insecure, + PSK: cfg.PSK, + ConnectionGater: cfg.ConnectionGater, + Reporter: cfg.Reporter, + PeerKey: autonatPrivKey, + Peerstore: ps, + DialRanker: swarm.NoDelayDialRanker, + ResourceManager: cfg.ResourceManager, + SwarmOpts: []swarm.Option{ + swarm.WithUDPBlackHoleSuccessCounter(nil), + swarm.WithIPv6BlackHoleSuccessCounter(nil), + }, + } + + fxopts, err := autoNatCfg.addTransports() + if err != nil { + return err + } + var dialer *swarm.Swarm + + fxopts = append(fxopts, + fx.Provide(eventbus.NewBus), + fx.Provide(func(lifecycle fx.Lifecycle, b event.Bus) (*swarm.Swarm, error) { + lifecycle.Append(fx.Hook{ + OnStop: func(context.Context) error { + return ps.Close() + }}) + var err error + dialer, err = autoNatCfg.makeSwarm(b, false) + return dialer, err + + }), + fx.Provide(func(s *swarm.Swarm) peer.ID { return s.LocalPeer() }), + fx.Provide(func() crypto.PrivKey { return autonatPrivKey }), + ) + app := fx.New(fxopts...) + if err := app.Err(); err != nil { + return err + } + err = app.Start(context.Background()) + if err != nil { + return err + } + go func() { + <-dialer.Done() // The swarm used for autonat has closed, we can cleanup now + app.Stop(context.Background()) + }() + autonatOpts = append(autonatOpts, autonat.EnableService(dialer)) + } + if cfg.AutoNATConfig.ForceReachability != nil { + autonatOpts = append(autonatOpts, autonat.WithReachability(*cfg.AutoNATConfig.ForceReachability)) + } + + autonat, err := autonat.New(h, autonatOpts...) + if err != nil { + return fmt.Errorf("autonat init failed: %w", err) + } + h.SetAutoNat(autonat) + return nil +} + +// Option is a libp2p config option that can be given to the libp2p constructor +// (`libp2p.New`). +type Option func(cfg *Config) error + +// Apply applies the given options to the config, returning the first error +// encountered (if any). +func (cfg *Config) Apply(opts ...Option) error { + for _, opt := range opts { + if opt == nil { + continue + } + if err := opt(cfg); err != nil { + return err + } + } + return nil +} diff --git a/options.go b/options.go index 0329b7e60b..4818e37c59 100644 --- a/options.go +++ b/options.go @@ -1,104 +1,16 @@ -package libp2p +//go:build !js +// +build !js -// This file contains all libp2p configuration options (except the defaults, -// those are in defaults.go). +package libp2p import ( - "crypto/rand" - "encoding/binary" "errors" - "fmt" "reflect" - "time" - "github.com/libp2p/go-libp2p/config" - "github.com/libp2p/go-libp2p/core/connmgr" - "github.com/libp2p/go-libp2p/core/crypto" - "github.com/libp2p/go-libp2p/core/metrics" - "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/core/pnet" - "github.com/libp2p/go-libp2p/core/protocol" - "github.com/libp2p/go-libp2p/core/transport" - "github.com/libp2p/go-libp2p/p2p/host/autorelay" - bhost "github.com/libp2p/go-libp2p/p2p/host/basic" - "github.com/libp2p/go-libp2p/p2p/net/swarm" - tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" - relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" - "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" "github.com/libp2p/go-libp2p/p2p/transport/quicreuse" - "github.com/prometheus/client_golang/prometheus" - - ma "github.com/multiformats/go-multiaddr" "go.uber.org/fx" ) -// ListenAddrStrings configures libp2p to listen on the given (unparsed) -// addresses. -func ListenAddrStrings(s ...string) Option { - return func(cfg *Config) error { - for _, addrstr := range s { - a, err := ma.NewMultiaddr(addrstr) - if err != nil { - return err - } - cfg.ListenAddrs = append(cfg.ListenAddrs, a) - } - return nil - } -} - -// ListenAddrs configures libp2p to listen on the given addresses. -func ListenAddrs(addrs ...ma.Multiaddr) Option { - return func(cfg *Config) error { - cfg.ListenAddrs = append(cfg.ListenAddrs, addrs...) - return nil - } -} - -// Security configures libp2p to use the given security transport (or transport -// constructor). -// -// Name is the protocol name. -// -// The transport can be a constructed security.Transport or a function taking -// any subset of this libp2p node's: -// * Public key -// * Private key -// * Peer ID -// * Host -// * Network -// * Peerstore -func Security(name string, constructor interface{}) Option { - return func(cfg *Config) error { - if cfg.Insecure { - return fmt.Errorf("cannot use security transports with an insecure libp2p configuration") - } - cfg.SecurityTransports = append(cfg.SecurityTransports, config.Security{ID: protocol.ID(name), Constructor: constructor}) - return nil - } -} - -// NoSecurity is an option that completely disables all transport security. -// It's incompatible with all other transport security protocols. -var NoSecurity Option = func(cfg *Config) error { - if len(cfg.SecurityTransports) > 0 { - return fmt.Errorf("cannot use security transports with an insecure libp2p configuration") - } - cfg.Insecure = true - return nil -} - -// Muxer configures libp2p to use the given stream multiplexer. -// name is the protocol name. -func Muxer(name string, muxer network.Multiplexer) Option { - return func(cfg *Config) error { - cfg.Muxers = append(cfg.Muxers, tptu.StreamMuxer{Muxer: muxer, ID: protocol.ID(name)}) - return nil - } -} - func QUICReuse(constructor interface{}, opts ...quicreuse.Option) Option { return func(cfg *Config) error { tag := `group:"quicreuseopts"` @@ -125,533 +37,3 @@ func QUICReuse(constructor interface{}, opts ...quicreuse.Option) Option { return nil } } - -// Transport configures libp2p to use the given transport (or transport -// constructor). -// -// The transport can be a constructed transport.Transport or a function taking -// any subset of this libp2p node's: -// * Transport Upgrader (*tptu.Upgrader) -// * Host -// * Stream muxer (muxer.Transport) -// * Security transport (security.Transport) -// * Private network protector (pnet.Protector) -// * Peer ID -// * Private Key -// * Public Key -// * Address filter (filter.Filter) -// * Peerstore -func Transport(constructor interface{}, opts ...interface{}) Option { - return func(cfg *Config) error { - // generate a random identifier, so that fx can associate the constructor with its options - b := make([]byte, 8) - rand.Read(b) - id := binary.BigEndian.Uint64(b) - - tag := fmt.Sprintf(`group:"transportopt_%d"`, id) - - typ := reflect.ValueOf(constructor).Type() - numParams := typ.NumIn() - isVariadic := typ.IsVariadic() - - if !isVariadic && len(opts) > 0 { - return errors.New("transport constructor doesn't take any options") - } - if isVariadic && numParams >= 1 { - paramType := typ.In(numParams - 1).Elem() - for _, opt := range opts { - if typ := reflect.TypeOf(opt); !typ.AssignableTo(paramType) { - return fmt.Errorf("transport option of type %s not assignable to %s", typ, paramType) - } - } - } - - var params []string - if isVariadic && len(opts) > 0 { - // If there are transport options, apply the tag. - // Since options are variadic, they have to be the last argument of the constructor. - params = make([]string, numParams) - params[len(params)-1] = tag - } - - cfg.Transports = append(cfg.Transports, fx.Provide( - fx.Annotate( - constructor, - fx.ParamTags(params...), - fx.As(new(transport.Transport)), - fx.ResultTags(`group:"transport"`), - ), - )) - for _, opt := range opts { - cfg.Transports = append(cfg.Transports, fx.Supply( - fx.Annotate( - opt, - fx.ResultTags(tag), - ), - )) - } - return nil - } -} - -// Peerstore configures libp2p to use the given peerstore. -func Peerstore(ps peerstore.Peerstore) Option { - return func(cfg *Config) error { - if cfg.Peerstore != nil { - return fmt.Errorf("cannot specify multiple peerstore options") - } - - cfg.Peerstore = ps - return nil - } -} - -// PrivateNetwork configures libp2p to use the given private network protector. -func PrivateNetwork(psk pnet.PSK) Option { - return func(cfg *Config) error { - if cfg.PSK != nil { - return fmt.Errorf("cannot specify multiple private network options") - } - - cfg.PSK = psk - return nil - } -} - -// BandwidthReporter configures libp2p to use the given bandwidth reporter. -func BandwidthReporter(rep metrics.Reporter) Option { - return func(cfg *Config) error { - if cfg.Reporter != nil { - return fmt.Errorf("cannot specify multiple bandwidth reporter options") - } - - cfg.Reporter = rep - return nil - } -} - -// Identity configures libp2p to use the given private key to identify itself. -func Identity(sk crypto.PrivKey) Option { - return func(cfg *Config) error { - if cfg.PeerKey != nil { - return fmt.Errorf("cannot specify multiple identities") - } - - cfg.PeerKey = sk - return nil - } -} - -// ConnectionManager configures libp2p to use the given connection manager. -// -// The current "standard" connection manager lives in github.com/libp2p/go-libp2p-connmgr. See -// https://pkg.go.dev/github.com/libp2p/go-libp2p-connmgr?utm_source=godoc#NewConnManager. -func ConnectionManager(connman connmgr.ConnManager) Option { - return func(cfg *Config) error { - if cfg.ConnManager != nil { - return fmt.Errorf("cannot specify multiple connection managers") - } - cfg.ConnManager = connman - return nil - } -} - -// AddrsFactory configures libp2p to use the given address factory. -func AddrsFactory(factory config.AddrsFactory) Option { - return func(cfg *Config) error { - if cfg.AddrsFactory != nil { - return fmt.Errorf("cannot specify multiple address factories") - } - cfg.AddrsFactory = factory - return nil - } -} - -// EnableRelay configures libp2p to enable the relay transport. -// This option only configures libp2p to accept inbound connections from relays -// and make outbound connections_through_ relays when requested by the remote peer. -// This option supports both circuit v1 and v2 connections. -// (default: enabled) -func EnableRelay() Option { - return func(cfg *Config) error { - cfg.RelayCustom = true - cfg.Relay = true - return nil - } -} - -// DisableRelay configures libp2p to disable the relay transport. -func DisableRelay() Option { - return func(cfg *Config) error { - cfg.RelayCustom = true - cfg.Relay = false - return nil - } -} - -// EnableRelayService configures libp2p to run a circuit v2 relay, -// if we detect that we're publicly reachable. -func EnableRelayService(opts ...relayv2.Option) Option { - return func(cfg *Config) error { - cfg.EnableRelayService = true - cfg.RelayServiceOpts = opts - return nil - } -} - -// EnableAutoRelay configures libp2p to enable the AutoRelay subsystem. -// -// Dependencies: -// - Relay (enabled by default) -// - Either: -// 1. A list of static relays -// 2. A PeerSource function that provides a chan of relays. See `autorelay.WithPeerSource` -// -// This subsystem performs automatic address rewriting to advertise relay addresses when it -// detects that the node is publicly unreachable (e.g. behind a NAT). -// -// Deprecated: Use EnableAutoRelayWithStaticRelays or EnableAutoRelayWithPeerSource -func EnableAutoRelay(opts ...autorelay.Option) Option { - return func(cfg *Config) error { - cfg.EnableAutoRelay = true - cfg.AutoRelayOpts = opts - return nil - } -} - -// EnableAutoRelayWithStaticRelays configures libp2p to enable the AutoRelay subsystem using -// the provided relays as relay candidates. -// This subsystem performs automatic address rewriting to advertise relay addresses when it -// detects that the node is publicly unreachable (e.g. behind a NAT). -func EnableAutoRelayWithStaticRelays(static []peer.AddrInfo, opts ...autorelay.Option) Option { - return func(cfg *Config) error { - cfg.EnableAutoRelay = true - cfg.AutoRelayOpts = append([]autorelay.Option{autorelay.WithStaticRelays(static)}, opts...) - return nil - } -} - -// EnableAutoRelayWithPeerSource configures libp2p to enable the AutoRelay -// subsystem using the provided PeerSource callback to get more relay -// candidates. This subsystem performs automatic address rewriting to advertise -// relay addresses when it detects that the node is publicly unreachable (e.g. -// behind a NAT). -func EnableAutoRelayWithPeerSource(peerSource autorelay.PeerSource, opts ...autorelay.Option) Option { - return func(cfg *Config) error { - cfg.EnableAutoRelay = true - cfg.AutoRelayOpts = append([]autorelay.Option{autorelay.WithPeerSource(peerSource)}, opts...) - return nil - } -} - -// ForceReachabilityPublic overrides automatic reachability detection in the AutoNAT subsystem, -// forcing the local node to believe it is reachable externally. -func ForceReachabilityPublic() Option { - return func(cfg *Config) error { - public := network.ReachabilityPublic - cfg.AutoNATConfig.ForceReachability = &public - return nil - } -} - -// ForceReachabilityPrivate overrides automatic reachability detection in the AutoNAT subsystem, -// forceing the local node to believe it is behind a NAT and not reachable externally. -func ForceReachabilityPrivate() Option { - return func(cfg *Config) error { - private := network.ReachabilityPrivate - cfg.AutoNATConfig.ForceReachability = &private - return nil - } -} - -// EnableNATService configures libp2p to provide a service to peers for determining -// their reachability status. When enabled, the host will attempt to dial back -// to peers, and then tell them if it was successful in making such connections. -func EnableNATService() Option { - return func(cfg *Config) error { - cfg.AutoNATConfig.EnableService = true - return nil - } -} - -// AutoNATServiceRateLimit changes the default rate limiting configured in helping -// other peers determine their reachability status. When set, the host will limit -// the number of requests it responds to in each 60 second period to the set -// numbers. A value of '0' disables throttling. -func AutoNATServiceRateLimit(global, perPeer int, interval time.Duration) Option { - return func(cfg *Config) error { - cfg.AutoNATConfig.ThrottleGlobalLimit = global - cfg.AutoNATConfig.ThrottlePeerLimit = perPeer - cfg.AutoNATConfig.ThrottleInterval = interval - return nil - } -} - -// ConnectionGater configures libp2p to use the given ConnectionGater -// to actively reject inbound/outbound connections based on the lifecycle stage -// of the connection. -// -// For more information, refer to go-libp2p/core.ConnectionGater. -func ConnectionGater(cg connmgr.ConnectionGater) Option { - return func(cfg *Config) error { - if cfg.ConnectionGater != nil { - return errors.New("cannot configure multiple connection gaters, or cannot configure both Filters and ConnectionGater") - } - cfg.ConnectionGater = cg - return nil - } -} - -// ResourceManager configures libp2p to use the given ResourceManager. -// When using the p2p/host/resource-manager implementation of the ResourceManager interface, -// it is recommended to set limits for libp2p protocol by calling SetDefaultServiceLimits. -func ResourceManager(rcmgr network.ResourceManager) Option { - return func(cfg *Config) error { - if cfg.ResourceManager != nil { - return errors.New("cannot configure multiple resource managers") - } - cfg.ResourceManager = rcmgr - return nil - } -} - -// NATPortMap configures libp2p to use the default NATManager. The default -// NATManager will attempt to open a port in your network's firewall using UPnP. -func NATPortMap() Option { - return NATManager(bhost.NewNATManager) -} - -// NATManager will configure libp2p to use the requested NATManager. This -// function should be passed a NATManager *constructor* that takes a libp2p Network. -func NATManager(nm config.NATManagerC) Option { - return func(cfg *Config) error { - if cfg.NATManager != nil { - return fmt.Errorf("cannot specify multiple NATManagers") - } - cfg.NATManager = nm - return nil - } -} - -// Ping will configure libp2p to support the ping service; enable by default. -func Ping(enable bool) Option { - return func(cfg *Config) error { - cfg.DisablePing = !enable - return nil - } -} - -// Routing will configure libp2p to use routing. -func Routing(rt config.RoutingC) Option { - return func(cfg *Config) error { - if cfg.Routing != nil { - return fmt.Errorf("cannot specify multiple routing options") - } - cfg.Routing = rt - return nil - } -} - -// NoListenAddrs will configure libp2p to not listen by default. -// -// This will both clear any configured listen addrs and prevent libp2p from -// applying the default listen address option. It also disables relay, unless the -// user explicitly specifies with an option, as the transport creates an implicit -// listen address that would make the node dialable through any relay it was connected to. -var NoListenAddrs = func(cfg *Config) error { - cfg.ListenAddrs = []ma.Multiaddr{} - if !cfg.RelayCustom { - cfg.RelayCustom = true - cfg.Relay = false - } - return nil -} - -// NoTransports will configure libp2p to not enable any transports. -// -// This will both clear any configured transports (specified in prior libp2p -// options) and prevent libp2p from applying the default transports. -var NoTransports = func(cfg *Config) error { - cfg.Transports = []fx.Option{} - return nil -} - -// ProtocolVersion sets the protocolVersion string required by the -// libp2p Identify protocol. -func ProtocolVersion(s string) Option { - return func(cfg *Config) error { - cfg.ProtocolVersion = s - return nil - } -} - -// UserAgent sets the libp2p user-agent sent along with the identify protocol -func UserAgent(userAgent string) Option { - return func(cfg *Config) error { - cfg.UserAgent = userAgent - return nil - } -} - -// MultiaddrResolver sets the libp2p dns resolver -func MultiaddrResolver(rslv network.MultiaddrDNSResolver) Option { - return func(cfg *Config) error { - cfg.MultiaddrResolver = rslv - return nil - } -} - -// Experimental -// EnableHolePunching enables NAT traversal by enabling NATT'd peers to both initiate and respond to hole punching attempts -// to create direct/NAT-traversed connections with other peers. (default: disabled) -// -// Dependencies: -// - Relay (enabled by default) -// -// This subsystem performs two functions: -// -// 1. On receiving an inbound Relay connection, it attempts to create a direct connection with the remote peer -// by initiating and co-ordinating a hole punch over the Relayed connection. -// 2. If a peer sees a request to co-ordinate a hole punch on an outbound Relay connection, -// it will participate in the hole-punch to create a direct connection with the remote peer. -// -// If the hole punch is successful, all new streams will thereafter be created on the hole-punched connection. -// The Relayed connection will eventually be closed after a grace period. -// -// All existing indefinite long-lived streams on the Relayed connection will have to re-opened on the hole-punched connection by the user. -// Users can make use of the `Connected`/`Disconnected` notifications emitted by the Network for this purpose. -// -// It is not mandatory but nice to also enable the `AutoRelay` option (See `EnableAutoRelay`) -// so the peer can discover and connect to Relay servers if it discovers that it is NATT'd and has private reachability via AutoNAT. -// This will then enable it to advertise Relay addresses which can be used to accept inbound Relay connections to then co-ordinate -// a hole punch. -// -// If `EnableAutoRelay` is configured and the user is confident that the peer has private reachability/is NATT'd, -// the `ForceReachabilityPrivate` option can be configured to short-circuit reachability discovery via AutoNAT -// so the peer can immediately start connecting to Relay servers. -// -// If `EnableAutoRelay` is configured, the `StaticRelays` option can be used to configure a static set of Relay servers -// for `AutoRelay` to connect to so that it does not need to discover Relay servers via Routing. -func EnableHolePunching(opts ...holepunch.Option) Option { - return func(cfg *Config) error { - cfg.EnableHolePunching = true - cfg.HolePunchingOptions = opts - return nil - } -} - -func WithDialTimeout(t time.Duration) Option { - return func(cfg *Config) error { - if t <= 0 { - return errors.New("dial timeout needs to be non-negative") - } - cfg.DialTimeout = t - return nil - } -} - -// DisableMetrics configures libp2p to disable prometheus metrics -func DisableMetrics() Option { - return func(cfg *Config) error { - cfg.DisableMetrics = true - return nil - } -} - -// PrometheusRegisterer configures libp2p to use reg as the Registerer for all metrics subsystems -func PrometheusRegisterer(reg prometheus.Registerer) Option { - return func(cfg *Config) error { - if cfg.DisableMetrics { - return errors.New("cannot set registerer when metrics are disabled") - } - if cfg.PrometheusRegisterer != nil { - return errors.New("registerer already set") - } - if reg == nil { - return errors.New("registerer cannot be nil") - } - cfg.PrometheusRegisterer = reg - return nil - } -} - -// DialRanker configures libp2p to use d as the dial ranker. To enable smart -// dialing use `swarm.DefaultDialRanker`. use `swarm.NoDelayDialRanker` to -// disable smart dialing. -// -// Deprecated: use SwarmOpts(swarm.WithDialRanker(d)) instead -func DialRanker(d network.DialRanker) Option { - return func(cfg *Config) error { - if cfg.DialRanker != nil { - return errors.New("dial ranker already configured") - } - cfg.DialRanker = d - return nil - } -} - -// SwarmOpts configures libp2p to use swarm with opts -func SwarmOpts(opts ...swarm.Option) Option { - return func(cfg *Config) error { - cfg.SwarmOpts = opts - return nil - } -} - -// DisableIdentifyAddressDiscovery disables address discovery using peer provided observed addresses -// in identify. If you know your public addresses upfront, the recommended way is to use -// AddressFactory to provide the external adddress to the host and use this option to disable -// discovery from identify. -func DisableIdentifyAddressDiscovery() Option { - return func(cfg *Config) error { - cfg.DisableIdentifyAddressDiscovery = true - return nil - } -} - -// EnableAutoNATv2 enables autonat v2 -func EnableAutoNATv2() Option { - return func(cfg *Config) error { - cfg.EnableAutoNATv2 = true - return nil - } -} - -// UDPBlackHoleSuccessCounter configures libp2p to use f as the black hole filter for UDP addrs -func UDPBlackHoleSuccessCounter(f *swarm.BlackHoleSuccessCounter) Option { - return func(cfg *Config) error { - cfg.UDPBlackHoleSuccessCounter = f - cfg.CustomUDPBlackHoleSuccessCounter = true - return nil - } -} - -// IPv6BlackHoleSuccessCounter configures libp2p to use f as the black hole filter for IPv6 addrs -func IPv6BlackHoleSuccessCounter(f *swarm.BlackHoleSuccessCounter) Option { - return func(cfg *Config) error { - cfg.IPv6BlackHoleSuccessCounter = f - cfg.CustomIPv6BlackHoleSuccessCounter = true - return nil - } -} - -// WithFxOption adds a user provided fx.Option to the libp2p constructor. -// Experimental: This option is subject to change or removal. -func WithFxOption(opts ...fx.Option) Option { - return func(cfg *Config) error { - cfg.UserFxOptions = append(cfg.UserFxOptions, opts...) - return nil - } -} - -// ShareTCPListener shares the same listen address between TCP and Websocket -// transports. This lets both transports use the same TCP port. -// -// Currently this behavior is Opt-in. In a future release this will be the -// default, and this option will be removed. -func ShareTCPListener() Option { - return func(cfg *Config) error { - cfg.ShareTCPListener = true - return nil - } -} diff --git a/options_shared.go b/options_shared.go new file mode 100644 index 0000000000..c982c03438 --- /dev/null +++ b/options_shared.go @@ -0,0 +1,629 @@ +package libp2p + +// This file contains all libp2p configuration options (except the defaults, +// those are in defaults.go). + +import ( + "crypto/rand" + "encoding/binary" + "errors" + "fmt" + "reflect" + "time" + + "github.com/libp2p/go-libp2p/config" + "github.com/libp2p/go-libp2p/core/connmgr" + "github.com/libp2p/go-libp2p/core/crypto" + "github.com/libp2p/go-libp2p/core/metrics" + "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/core/pnet" + "github.com/libp2p/go-libp2p/core/protocol" + "github.com/libp2p/go-libp2p/core/transport" + "github.com/libp2p/go-libp2p/p2p/host/autorelay" + bhost "github.com/libp2p/go-libp2p/p2p/host/basic" + "github.com/libp2p/go-libp2p/p2p/net/swarm" + tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" + relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" + "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" + "github.com/prometheus/client_golang/prometheus" + + ma "github.com/multiformats/go-multiaddr" + "go.uber.org/fx" +) + +// ListenAddrStrings configures libp2p to listen on the given (unparsed) +// addresses. +func ListenAddrStrings(s ...string) Option { + return func(cfg *Config) error { + for _, addrstr := range s { + a, err := ma.NewMultiaddr(addrstr) + if err != nil { + return err + } + cfg.ListenAddrs = append(cfg.ListenAddrs, a) + } + return nil + } +} + +// ListenAddrs configures libp2p to listen on the given addresses. +func ListenAddrs(addrs ...ma.Multiaddr) Option { + return func(cfg *Config) error { + cfg.ListenAddrs = append(cfg.ListenAddrs, addrs...) + return nil + } +} + +// Security configures libp2p to use the given security transport (or transport +// constructor). +// +// Name is the protocol name. +// +// The transport can be a constructed security.Transport or a function taking +// any subset of this libp2p node's: +// * Public key +// * Private key +// * Peer ID +// * Host +// * Network +// * Peerstore +func Security(name string, constructor interface{}) Option { + return func(cfg *Config) error { + if cfg.Insecure { + return fmt.Errorf("cannot use security transports with an insecure libp2p configuration") + } + cfg.SecurityTransports = append(cfg.SecurityTransports, config.Security{ID: protocol.ID(name), Constructor: constructor}) + return nil + } +} + +// NoSecurity is an option that completely disables all transport security. +// It's incompatible with all other transport security protocols. +var NoSecurity Option = func(cfg *Config) error { + if len(cfg.SecurityTransports) > 0 { + return fmt.Errorf("cannot use security transports with an insecure libp2p configuration") + } + cfg.Insecure = true + return nil +} + +// Muxer configures libp2p to use the given stream multiplexer. +// name is the protocol name. +func Muxer(name string, muxer network.Multiplexer) Option { + return func(cfg *Config) error { + cfg.Muxers = append(cfg.Muxers, tptu.StreamMuxer{Muxer: muxer, ID: protocol.ID(name)}) + return nil + } +} + +// Transport configures libp2p to use the given transport (or transport +// constructor). +// +// The transport can be a constructed transport.Transport or a function taking +// any subset of this libp2p node's: +// * Transport Upgrader (*tptu.Upgrader) +// * Host +// * Stream muxer (muxer.Transport) +// * Security transport (security.Transport) +// * Private network protector (pnet.Protector) +// * Peer ID +// * Private Key +// * Public Key +// * Address filter (filter.Filter) +// * Peerstore +func Transport(constructor interface{}, opts ...interface{}) Option { + return func(cfg *Config) error { + // generate a random identifier, so that fx can associate the constructor with its options + b := make([]byte, 8) + rand.Read(b) + id := binary.BigEndian.Uint64(b) + + tag := fmt.Sprintf(`group:"transportopt_%d"`, id) + + typ := reflect.ValueOf(constructor).Type() + numParams := typ.NumIn() + isVariadic := typ.IsVariadic() + + if !isVariadic && len(opts) > 0 { + return errors.New("transport constructor doesn't take any options") + } + if isVariadic && numParams >= 1 { + paramType := typ.In(numParams - 1).Elem() + for _, opt := range opts { + if typ := reflect.TypeOf(opt); !typ.AssignableTo(paramType) { + return fmt.Errorf("transport option of type %s not assignable to %s", typ, paramType) + } + } + } + + var params []string + if isVariadic && len(opts) > 0 { + // If there are transport options, apply the tag. + // Since options are variadic, they have to be the last argument of the constructor. + params = make([]string, numParams) + params[len(params)-1] = tag + } + + cfg.Transports = append(cfg.Transports, fx.Provide( + fx.Annotate( + constructor, + fx.ParamTags(params...), + fx.As(new(transport.Transport)), + fx.ResultTags(`group:"transport"`), + ), + )) + for _, opt := range opts { + cfg.Transports = append(cfg.Transports, fx.Supply( + fx.Annotate( + opt, + fx.ResultTags(tag), + ), + )) + } + return nil + } +} + +// Peerstore configures libp2p to use the given peerstore. +func Peerstore(ps peerstore.Peerstore) Option { + return func(cfg *Config) error { + if cfg.Peerstore != nil { + return fmt.Errorf("cannot specify multiple peerstore options") + } + + cfg.Peerstore = ps + return nil + } +} + +// PrivateNetwork configures libp2p to use the given private network protector. +func PrivateNetwork(psk pnet.PSK) Option { + return func(cfg *Config) error { + if cfg.PSK != nil { + return fmt.Errorf("cannot specify multiple private network options") + } + + cfg.PSK = psk + return nil + } +} + +// BandwidthReporter configures libp2p to use the given bandwidth reporter. +func BandwidthReporter(rep metrics.Reporter) Option { + return func(cfg *Config) error { + if cfg.Reporter != nil { + return fmt.Errorf("cannot specify multiple bandwidth reporter options") + } + + cfg.Reporter = rep + return nil + } +} + +// Identity configures libp2p to use the given private key to identify itself. +func Identity(sk crypto.PrivKey) Option { + return func(cfg *Config) error { + if cfg.PeerKey != nil { + return fmt.Errorf("cannot specify multiple identities") + } + + cfg.PeerKey = sk + return nil + } +} + +// ConnectionManager configures libp2p to use the given connection manager. +// +// The current "standard" connection manager lives in github.com/libp2p/go-libp2p-connmgr. See +// https://pkg.go.dev/github.com/libp2p/go-libp2p-connmgr?utm_source=godoc#NewConnManager. +func ConnectionManager(connman connmgr.ConnManager) Option { + return func(cfg *Config) error { + if cfg.ConnManager != nil { + return fmt.Errorf("cannot specify multiple connection managers") + } + cfg.ConnManager = connman + return nil + } +} + +// AddrsFactory configures libp2p to use the given address factory. +func AddrsFactory(factory config.AddrsFactory) Option { + return func(cfg *Config) error { + if cfg.AddrsFactory != nil { + return fmt.Errorf("cannot specify multiple address factories") + } + cfg.AddrsFactory = factory + return nil + } +} + +// EnableRelay configures libp2p to enable the relay transport. +// This option only configures libp2p to accept inbound connections from relays +// and make outbound connections_through_ relays when requested by the remote peer. +// This option supports both circuit v1 and v2 connections. +// (default: enabled) +func EnableRelay() Option { + return func(cfg *Config) error { + cfg.RelayCustom = true + cfg.Relay = true + return nil + } +} + +// DisableRelay configures libp2p to disable the relay transport. +func DisableRelay() Option { + return func(cfg *Config) error { + cfg.RelayCustom = true + cfg.Relay = false + return nil + } +} + +// EnableRelayService configures libp2p to run a circuit v2 relay, +// if we detect that we're publicly reachable. +func EnableRelayService(opts ...relayv2.Option) Option { + return func(cfg *Config) error { + cfg.EnableRelayService = true + cfg.RelayServiceOpts = opts + return nil + } +} + +// EnableAutoRelay configures libp2p to enable the AutoRelay subsystem. +// +// Dependencies: +// - Relay (enabled by default) +// - Either: +// 1. A list of static relays +// 2. A PeerSource function that provides a chan of relays. See `autorelay.WithPeerSource` +// +// This subsystem performs automatic address rewriting to advertise relay addresses when it +// detects that the node is publicly unreachable (e.g. behind a NAT). +// +// Deprecated: Use EnableAutoRelayWithStaticRelays or EnableAutoRelayWithPeerSource +func EnableAutoRelay(opts ...autorelay.Option) Option { + return func(cfg *Config) error { + cfg.EnableAutoRelay = true + cfg.AutoRelayOpts = opts + return nil + } +} + +// EnableAutoRelayWithStaticRelays configures libp2p to enable the AutoRelay subsystem using +// the provided relays as relay candidates. +// This subsystem performs automatic address rewriting to advertise relay addresses when it +// detects that the node is publicly unreachable (e.g. behind a NAT). +func EnableAutoRelayWithStaticRelays(static []peer.AddrInfo, opts ...autorelay.Option) Option { + return func(cfg *Config) error { + cfg.EnableAutoRelay = true + cfg.AutoRelayOpts = append([]autorelay.Option{autorelay.WithStaticRelays(static)}, opts...) + return nil + } +} + +// EnableAutoRelayWithPeerSource configures libp2p to enable the AutoRelay +// subsystem using the provided PeerSource callback to get more relay +// candidates. This subsystem performs automatic address rewriting to advertise +// relay addresses when it detects that the node is publicly unreachable (e.g. +// behind a NAT). +func EnableAutoRelayWithPeerSource(peerSource autorelay.PeerSource, opts ...autorelay.Option) Option { + return func(cfg *Config) error { + cfg.EnableAutoRelay = true + cfg.AutoRelayOpts = append([]autorelay.Option{autorelay.WithPeerSource(peerSource)}, opts...) + return nil + } +} + +// ForceReachabilityPublic overrides automatic reachability detection in the AutoNAT subsystem, +// forcing the local node to believe it is reachable externally. +func ForceReachabilityPublic() Option { + return func(cfg *Config) error { + public := network.ReachabilityPublic + cfg.AutoNATConfig.ForceReachability = &public + return nil + } +} + +// ForceReachabilityPrivate overrides automatic reachability detection in the AutoNAT subsystem, +// forceing the local node to believe it is behind a NAT and not reachable externally. +func ForceReachabilityPrivate() Option { + return func(cfg *Config) error { + private := network.ReachabilityPrivate + cfg.AutoNATConfig.ForceReachability = &private + return nil + } +} + +// EnableNATService configures libp2p to provide a service to peers for determining +// their reachability status. When enabled, the host will attempt to dial back +// to peers, and then tell them if it was successful in making such connections. +func EnableNATService() Option { + return func(cfg *Config) error { + cfg.AutoNATConfig.EnableService = true + return nil + } +} + +// AutoNATServiceRateLimit changes the default rate limiting configured in helping +// other peers determine their reachability status. When set, the host will limit +// the number of requests it responds to in each 60 second period to the set +// numbers. A value of '0' disables throttling. +func AutoNATServiceRateLimit(global, perPeer int, interval time.Duration) Option { + return func(cfg *Config) error { + cfg.AutoNATConfig.ThrottleGlobalLimit = global + cfg.AutoNATConfig.ThrottlePeerLimit = perPeer + cfg.AutoNATConfig.ThrottleInterval = interval + return nil + } +} + +// ConnectionGater configures libp2p to use the given ConnectionGater +// to actively reject inbound/outbound connections based on the lifecycle stage +// of the connection. +// +// For more information, refer to go-libp2p/core.ConnectionGater. +func ConnectionGater(cg connmgr.ConnectionGater) Option { + return func(cfg *Config) error { + if cfg.ConnectionGater != nil { + return errors.New("cannot configure multiple connection gaters, or cannot configure both Filters and ConnectionGater") + } + cfg.ConnectionGater = cg + return nil + } +} + +// ResourceManager configures libp2p to use the given ResourceManager. +// When using the p2p/host/resource-manager implementation of the ResourceManager interface, +// it is recommended to set limits for libp2p protocol by calling SetDefaultServiceLimits. +func ResourceManager(rcmgr network.ResourceManager) Option { + return func(cfg *Config) error { + if cfg.ResourceManager != nil { + return errors.New("cannot configure multiple resource managers") + } + cfg.ResourceManager = rcmgr + return nil + } +} + +// NATPortMap configures libp2p to use the default NATManager. The default +// NATManager will attempt to open a port in your network's firewall using UPnP. +func NATPortMap() Option { + return NATManager(bhost.NewNATManager) +} + +// NATManager will configure libp2p to use the requested NATManager. This +// function should be passed a NATManager *constructor* that takes a libp2p Network. +func NATManager(nm config.NATManagerC) Option { + return func(cfg *Config) error { + if cfg.NATManager != nil { + return fmt.Errorf("cannot specify multiple NATManagers") + } + cfg.NATManager = nm + return nil + } +} + +// Ping will configure libp2p to support the ping service; enable by default. +func Ping(enable bool) Option { + return func(cfg *Config) error { + cfg.DisablePing = !enable + return nil + } +} + +// Routing will configure libp2p to use routing. +func Routing(rt config.RoutingC) Option { + return func(cfg *Config) error { + if cfg.Routing != nil { + return fmt.Errorf("cannot specify multiple routing options") + } + cfg.Routing = rt + return nil + } +} + +// NoListenAddrs will configure libp2p to not listen by default. +// +// This will both clear any configured listen addrs and prevent libp2p from +// applying the default listen address option. It also disables relay, unless the +// user explicitly specifies with an option, as the transport creates an implicit +// listen address that would make the node dialable through any relay it was connected to. +var NoListenAddrs = func(cfg *Config) error { + cfg.ListenAddrs = []ma.Multiaddr{} + if !cfg.RelayCustom { + cfg.RelayCustom = true + cfg.Relay = false + } + return nil +} + +// NoTransports will configure libp2p to not enable any transports. +// +// This will both clear any configured transports (specified in prior libp2p +// options) and prevent libp2p from applying the default transports. +var NoTransports = func(cfg *Config) error { + cfg.Transports = []fx.Option{} + return nil +} + +// ProtocolVersion sets the protocolVersion string required by the +// libp2p Identify protocol. +func ProtocolVersion(s string) Option { + return func(cfg *Config) error { + cfg.ProtocolVersion = s + return nil + } +} + +// UserAgent sets the libp2p user-agent sent along with the identify protocol +func UserAgent(userAgent string) Option { + return func(cfg *Config) error { + cfg.UserAgent = userAgent + return nil + } +} + +// MultiaddrResolver sets the libp2p dns resolver +func MultiaddrResolver(rslv network.MultiaddrDNSResolver) Option { + return func(cfg *Config) error { + cfg.MultiaddrResolver = rslv + return nil + } +} + +// Experimental +// EnableHolePunching enables NAT traversal by enabling NATT'd peers to both initiate and respond to hole punching attempts +// to create direct/NAT-traversed connections with other peers. (default: disabled) +// +// Dependencies: +// - Relay (enabled by default) +// +// This subsystem performs two functions: +// +// 1. On receiving an inbound Relay connection, it attempts to create a direct connection with the remote peer +// by initiating and co-ordinating a hole punch over the Relayed connection. +// 2. If a peer sees a request to co-ordinate a hole punch on an outbound Relay connection, +// it will participate in the hole-punch to create a direct connection with the remote peer. +// +// If the hole punch is successful, all new streams will thereafter be created on the hole-punched connection. +// The Relayed connection will eventually be closed after a grace period. +// +// All existing indefinite long-lived streams on the Relayed connection will have to re-opened on the hole-punched connection by the user. +// Users can make use of the `Connected`/`Disconnected` notifications emitted by the Network for this purpose. +// +// It is not mandatory but nice to also enable the `AutoRelay` option (See `EnableAutoRelay`) +// so the peer can discover and connect to Relay servers if it discovers that it is NATT'd and has private reachability via AutoNAT. +// This will then enable it to advertise Relay addresses which can be used to accept inbound Relay connections to then co-ordinate +// a hole punch. +// +// If `EnableAutoRelay` is configured and the user is confident that the peer has private reachability/is NATT'd, +// the `ForceReachabilityPrivate` option can be configured to short-circuit reachability discovery via AutoNAT +// so the peer can immediately start connecting to Relay servers. +// +// If `EnableAutoRelay` is configured, the `StaticRelays` option can be used to configure a static set of Relay servers +// for `AutoRelay` to connect to so that it does not need to discover Relay servers via Routing. +func EnableHolePunching(opts ...holepunch.Option) Option { + return func(cfg *Config) error { + cfg.EnableHolePunching = true + cfg.HolePunchingOptions = opts + return nil + } +} + +func WithDialTimeout(t time.Duration) Option { + return func(cfg *Config) error { + if t <= 0 { + return errors.New("dial timeout needs to be non-negative") + } + cfg.DialTimeout = t + return nil + } +} + +// DisableMetrics configures libp2p to disable prometheus metrics +func DisableMetrics() Option { + return func(cfg *Config) error { + cfg.DisableMetrics = true + return nil + } +} + +// PrometheusRegisterer configures libp2p to use reg as the Registerer for all metrics subsystems +func PrometheusRegisterer(reg prometheus.Registerer) Option { + return func(cfg *Config) error { + if cfg.DisableMetrics { + return errors.New("cannot set registerer when metrics are disabled") + } + if cfg.PrometheusRegisterer != nil { + return errors.New("registerer already set") + } + if reg == nil { + return errors.New("registerer cannot be nil") + } + cfg.PrometheusRegisterer = reg + return nil + } +} + +// DialRanker configures libp2p to use d as the dial ranker. To enable smart +// dialing use `swarm.DefaultDialRanker`. use `swarm.NoDelayDialRanker` to +// disable smart dialing. +// +// Deprecated: use SwarmOpts(swarm.WithDialRanker(d)) instead +func DialRanker(d network.DialRanker) Option { + return func(cfg *Config) error { + if cfg.DialRanker != nil { + return errors.New("dial ranker already configured") + } + cfg.DialRanker = d + return nil + } +} + +// SwarmOpts configures libp2p to use swarm with opts +func SwarmOpts(opts ...swarm.Option) Option { + return func(cfg *Config) error { + cfg.SwarmOpts = opts + return nil + } +} + +// DisableIdentifyAddressDiscovery disables address discovery using peer provided observed addresses +// in identify. If you know your public addresses upfront, the recommended way is to use +// AddressFactory to provide the external adddress to the host and use this option to disable +// discovery from identify. +func DisableIdentifyAddressDiscovery() Option { + return func(cfg *Config) error { + cfg.DisableIdentifyAddressDiscovery = true + return nil + } +} + +// EnableAutoNATv2 enables autonat v2 +func EnableAutoNATv2() Option { + return func(cfg *Config) error { + cfg.EnableAutoNATv2 = true + return nil + } +} + +// UDPBlackHoleSuccessCounter configures libp2p to use f as the black hole filter for UDP addrs +func UDPBlackHoleSuccessCounter(f *swarm.BlackHoleSuccessCounter) Option { + return func(cfg *Config) error { + cfg.UDPBlackHoleSuccessCounter = f + cfg.CustomUDPBlackHoleSuccessCounter = true + return nil + } +} + +// IPv6BlackHoleSuccessCounter configures libp2p to use f as the black hole filter for IPv6 addrs +func IPv6BlackHoleSuccessCounter(f *swarm.BlackHoleSuccessCounter) Option { + return func(cfg *Config) error { + cfg.IPv6BlackHoleSuccessCounter = f + cfg.CustomIPv6BlackHoleSuccessCounter = true + return nil + } +} + +// WithFxOption adds a user provided fx.Option to the libp2p constructor. +// Experimental: This option is subject to change or removal. +func WithFxOption(opts ...fx.Option) Option { + return func(cfg *Config) error { + cfg.UserFxOptions = append(cfg.UserFxOptions, opts...) + return nil + } +} + +// ShareTCPListener shares the same listen address between TCP and Websocket +// transports. This lets both transports use the same TCP port. +// +// Currently this behavior is Opt-in. In a future release this will be the +// default, and this option will be removed. +func ShareTCPListener() Option { + return func(cfg *Config) error { + cfg.ShareTCPListener = true + return nil + } +} diff --git a/p2p/http/libp2phttp_test.go b/p2p/http/libp2phttp_test.go index c87c9a3aa7..e59001e2dc 100644 --- a/p2p/http/libp2phttp_test.go +++ b/p2p/http/libp2phttp_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2phttp_test import ( diff --git a/p2p/net/connmgr/bench_test.go b/p2p/net/connmgr/bench_test.go index 83442f9162..77507d9b64 100644 --- a/p2p/net/connmgr/bench_test.go +++ b/p2p/net/connmgr/bench_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package connmgr import ( diff --git a/p2p/net/connmgr/connmgr_test.go b/p2p/net/connmgr/connmgr_test.go index f47557b02c..c1136ac13e 100644 --- a/p2p/net/connmgr/connmgr_test.go +++ b/p2p/net/connmgr/connmgr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package connmgr import ( diff --git a/p2p/net/swarm/dial_test.go b/p2p/net/swarm/dial_test.go index feb9f49174..93e18773a9 100644 --- a/p2p/net/swarm/dial_test.go +++ b/p2p/net/swarm/dial_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/dial_worker_test.go b/p2p/net/swarm/dial_worker_test.go index c7298fb61e..5ed22121ee 100644 --- a/p2p/net/swarm/dial_worker_test.go +++ b/p2p/net/swarm/dial_worker_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm import ( diff --git a/p2p/net/swarm/simul_test.go b/p2p/net/swarm/simul_test.go index 33026d0e11..7dcda61ca5 100644 --- a/p2p/net/swarm/simul_test.go +++ b/p2p/net/swarm/simul_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/swarm_addr_test.go b/p2p/net/swarm/swarm_addr_test.go index 43e76716e5..91f5e78f2b 100644 --- a/p2p/net/swarm/swarm_addr_test.go +++ b/p2p/net/swarm/swarm_addr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/swarm_dial_test.go b/p2p/net/swarm/swarm_dial_test.go index 6d14730b68..af2f719086 100644 --- a/p2p/net/swarm/swarm_dial_test.go +++ b/p2p/net/swarm/swarm_dial_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm import ( diff --git a/p2p/net/swarm/swarm_event_test.go b/p2p/net/swarm/swarm_event_test.go index 5010215fc2..85f698916d 100644 --- a/p2p/net/swarm/swarm_event_test.go +++ b/p2p/net/swarm/swarm_event_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/swarm_net_test.go b/p2p/net/swarm/swarm_net_test.go index 1dbdc57bcc..55d67cff93 100644 --- a/p2p/net/swarm/swarm_net_test.go +++ b/p2p/net/swarm/swarm_net_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/swarm_notif_test.go b/p2p/net/swarm/swarm_notif_test.go index 0b6d56122e..a51c4e284c 100644 --- a/p2p/net/swarm/swarm_notif_test.go +++ b/p2p/net/swarm/swarm_notif_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/swarm_test.go b/p2p/net/swarm/swarm_test.go index 496236f826..9e2527fc66 100644 --- a/p2p/net/swarm/swarm_test.go +++ b/p2p/net/swarm/swarm_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/net/swarm/testing/testing.go b/p2p/net/swarm/testing/testing.go index 773314a1b8..fde27b64e5 100644 --- a/p2p/net/swarm/testing/testing.go +++ b/p2p/net/swarm/testing/testing.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package testing import ( diff --git a/p2p/net/swarm/testing/testing_test.go b/p2p/net/swarm/testing/testing_test.go index d4a43dfb59..04d6eb2f33 100644 --- a/p2p/net/swarm/testing/testing_test.go +++ b/p2p/net/swarm/testing/testing_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package testing import ( diff --git a/p2p/net/swarm/transport_test.go b/p2p/net/swarm/transport_test.go index fe7434753e..0ed28e4760 100644 --- a/p2p/net/swarm/transport_test.go +++ b/p2p/net/swarm/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/protocol/ping/ping_test.go b/p2p/protocol/ping/ping_test.go index d33662ee91..7490ba4773 100644 --- a/p2p/protocol/ping/ping_test.go +++ b/p2p/protocol/ping/ping_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package ping_test import ( diff --git a/p2p/test/backpressure/backpressure_test.go b/p2p/test/backpressure/backpressure_test.go index 207171a78e..4302c37a1b 100644 --- a/p2p/test/backpressure/backpressure_test.go +++ b/p2p/test/backpressure/backpressure_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package backpressure_tests import ( diff --git a/p2p/test/basichost/basic_host_test.go b/p2p/test/basichost/basic_host_test.go index 0197387b1b..932417f494 100644 --- a/p2p/test/basichost/basic_host_test.go +++ b/p2p/test/basichost/basic_host_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package basichost import ( diff --git a/p2p/test/notifications/notification_test.go b/p2p/test/notifications/notification_test.go index eb26a3fe5e..235e7657a9 100644 --- a/p2p/test/notifications/notification_test.go +++ b/p2p/test/notifications/notification_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package notifications import ( diff --git a/p2p/test/quic/quic_test.go b/p2p/test/quic/quic_test.go index fe52119b89..37d406a0cb 100644 --- a/p2p/test/quic/quic_test.go +++ b/p2p/test/quic/quic_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quic_test import ( diff --git a/p2p/test/reconnects/reconnect_test.go b/p2p/test/reconnects/reconnect_test.go index cf05c80f37..8dbd43a2e6 100644 --- a/p2p/test/reconnects/reconnect_test.go +++ b/p2p/test/reconnects/reconnect_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package reconnect import ( diff --git a/p2p/test/transport/deadline_test.go b/p2p/test/transport/deadline_test.go index 55fa7a4fbc..df174a34cf 100644 --- a/p2p/test/transport/deadline_test.go +++ b/p2p/test/transport/deadline_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package transport_integration import ( diff --git a/p2p/test/transport/gating_test.go b/p2p/test/transport/gating_test.go index c9ae4fd80d..73a0e5cb72 100644 --- a/p2p/test/transport/gating_test.go +++ b/p2p/test/transport/gating_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package transport_integration import ( diff --git a/p2p/test/transport/mock_connection_gater_test.go b/p2p/test/transport/mock_connection_gater_test.go index 5e13863f54..22d62db369 100644 --- a/p2p/test/transport/mock_connection_gater_test.go +++ b/p2p/test/transport/mock_connection_gater_test.go @@ -1,3 +1,5 @@ +//go:build !js +// +build !js // Code generated by MockGen. DO NOT EDIT. // Source: github.com/libp2p/go-libp2p/core/connmgr (interfaces: ConnectionGater) // diff --git a/p2p/test/transport/rcmgr_test.go b/p2p/test/transport/rcmgr_test.go index 9a6a09b87d..9cdc97dccc 100644 --- a/p2p/test/transport/rcmgr_test.go +++ b/p2p/test/transport/rcmgr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package transport_integration import ( diff --git a/p2p/test/transport/transport_test.go b/p2p/test/transport/transport_test.go index c8445a3997..978fba1ca3 100644 --- a/p2p/test/transport/transport_test.go +++ b/p2p/test/transport/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package transport_integration import ( diff --git a/p2p/transport/quic/cmd/client/main.go b/p2p/transport/quic/cmd/client/main.go index e9883d2a1d..04369c1f31 100644 --- a/p2p/transport/quic/cmd/client/main.go +++ b/p2p/transport/quic/cmd/client/main.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package main import ( diff --git a/p2p/transport/quic/cmd/lib/lib.go b/p2p/transport/quic/cmd/lib/lib.go index fd2a270af0..29a7c40dac 100644 --- a/p2p/transport/quic/cmd/lib/lib.go +++ b/p2p/transport/quic/cmd/lib/lib.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package cmdlib import ( diff --git a/p2p/transport/quic/cmd/lib/lib_test.go b/p2p/transport/quic/cmd/lib/lib_test.go index 2175874322..9bc8586033 100644 --- a/p2p/transport/quic/cmd/lib/lib_test.go +++ b/p2p/transport/quic/cmd/lib/lib_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package cmdlib import ( diff --git a/p2p/transport/quic/cmd/server/main.go b/p2p/transport/quic/cmd/server/main.go index c478d34b22..24068590c9 100644 --- a/p2p/transport/quic/cmd/server/main.go +++ b/p2p/transport/quic/cmd/server/main.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package main import ( diff --git a/p2p/transport/quic/conn.go b/p2p/transport/quic/conn.go index 8b381d8eda..6c682ce61b 100644 --- a/p2p/transport/quic/conn.go +++ b/p2p/transport/quic/conn.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/conn_test.go b/p2p/transport/quic/conn_test.go index 83300eb978..e0de4deb76 100644 --- a/p2p/transport/quic/conn_test.go +++ b/p2p/transport/quic/conn_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/listener.go b/p2p/transport/quic/listener.go index 30868e49eb..b21db4c39b 100644 --- a/p2p/transport/quic/listener.go +++ b/p2p/transport/quic/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/listener_test.go b/p2p/transport/quic/listener_test.go index 53d6001d35..a23114c5be 100644 --- a/p2p/transport/quic/listener_test.go +++ b/p2p/transport/quic/listener_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/stream.go b/p2p/transport/quic/stream.go index 1de4770dce..d6d9174364 100644 --- a/p2p/transport/quic/stream.go +++ b/p2p/transport/quic/stream.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/transport.go b/p2p/transport/quic/transport.go index 62d31a8d2a..ce47a9d176 100644 --- a/p2p/transport/quic/transport.go +++ b/p2p/transport/quic/transport.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/transport_test.go b/p2p/transport/quic/transport_test.go index 41e7e4e416..47be1279c0 100644 --- a/p2p/transport/quic/transport_test.go +++ b/p2p/transport/quic/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quic/virtuallistener.go b/p2p/transport/quic/virtuallistener.go index 5b23e4c507..3deaa97b34 100644 --- a/p2p/transport/quic/virtuallistener.go +++ b/p2p/transport/quic/virtuallistener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pquic import ( diff --git a/p2p/transport/quicreuse/config.go b/p2p/transport/quicreuse/config.go index 62f8919c8b..47f9b6bbf8 100644 --- a/p2p/transport/quicreuse/config.go +++ b/p2p/transport/quicreuse/config.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/connmgr.go b/p2p/transport/quicreuse/connmgr.go index c9e3088b5e..28465f5b2b 100644 --- a/p2p/transport/quicreuse/connmgr.go +++ b/p2p/transport/quicreuse/connmgr.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/connmgr_test.go b/p2p/transport/quicreuse/connmgr_test.go index d128119dab..2185514ce8 100644 --- a/p2p/transport/quicreuse/connmgr_test.go +++ b/p2p/transport/quicreuse/connmgr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/listener.go b/p2p/transport/quicreuse/listener.go index 44028197d8..552af8f4bb 100644 --- a/p2p/transport/quicreuse/listener.go +++ b/p2p/transport/quicreuse/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/nonquic_packetconn.go b/p2p/transport/quicreuse/nonquic_packetconn.go index 833bd5804a..ce86803cf8 100644 --- a/p2p/transport/quicreuse/nonquic_packetconn.go +++ b/p2p/transport/quicreuse/nonquic_packetconn.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/options.go b/p2p/transport/quicreuse/options.go index 36a7891393..af20128934 100644 --- a/p2p/transport/quicreuse/options.go +++ b/p2p/transport/quicreuse/options.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/quic_multiaddr.go b/p2p/transport/quicreuse/quic_multiaddr.go index af16547357..308002341c 100644 --- a/p2p/transport/quicreuse/quic_multiaddr.go +++ b/p2p/transport/quicreuse/quic_multiaddr.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/quic_multiaddr_test.go b/p2p/transport/quicreuse/quic_multiaddr_test.go index a6242e2674..1db63724c3 100644 --- a/p2p/transport/quicreuse/quic_multiaddr_test.go +++ b/p2p/transport/quicreuse/quic_multiaddr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/reuse.go b/p2p/transport/quicreuse/reuse.go index 6d0098e33d..f177293418 100644 --- a/p2p/transport/quicreuse/reuse.go +++ b/p2p/transport/quicreuse/reuse.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/reuse_test.go b/p2p/transport/quicreuse/reuse_test.go index ad08c75b5d..9ec4d863e3 100644 --- a/p2p/transport/quicreuse/reuse_test.go +++ b/p2p/transport/quicreuse/reuse_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/tracer.go b/p2p/transport/quicreuse/tracer.go index 16c7dce4f1..2334e50b2a 100644 --- a/p2p/transport/quicreuse/tracer.go +++ b/p2p/transport/quicreuse/tracer.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( diff --git a/p2p/transport/quicreuse/tracer_test.go b/p2p/transport/quicreuse/tracer_test.go index bea6b91dbf..7175dffcd7 100644 --- a/p2p/transport/quicreuse/tracer_test.go +++ b/p2p/transport/quicreuse/tracer_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package quicreuse import ( From 9030cf8c4fe8919b924d91a989d89d0ac4f64517 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 20:45:45 +0300 Subject: [PATCH 04/13] exclude WebTransport from wasm target --- p2p/host/basic/basic_host.go | 19 +++++++++++++++++++ p2p/host/basic/basic_host_test.go | 3 +++ p2p/host/basic/natmgr_test.go | 3 +++ p2p/host/pstoremanager/pstoremanager_test.go | 3 +++ p2p/transport/webtransport/cert_manager.go | 3 +++ .../webtransport/cert_manager_test.go | 3 +++ p2p/transport/webtransport/conn.go | 3 +++ p2p/transport/webtransport/crypto.go | 3 +++ p2p/transport/webtransport/crypto_test.go | 3 +++ p2p/transport/webtransport/listener.go | 3 +++ p2p/transport/webtransport/multiaddr.go | 3 +++ p2p/transport/webtransport/multiaddr_test.go | 3 +++ .../webtransport/noise_early_data.go | 3 +++ p2p/transport/webtransport/stream.go | 3 +++ p2p/transport/webtransport/transport.go | 3 +++ p2p/transport/webtransport/transport_test.go | 3 +++ 16 files changed, 64 insertions(+) diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index b2f58d45ac..b4db8c2091 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -28,6 +28,8 @@ 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" + libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" + libp2pwebtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport" "github.com/prometheus/client_golang/prometheus" logging "github.com/ipfs/go-log/v2" @@ -730,6 +732,23 @@ func (h *BasicHost) Addrs() []ma.Multiaddr { return h.addressManager.Addrs() } +// 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 { + ok, n := libp2pwebtransport.IsWebtransportMultiaddr(addr) + if !ok { + ok, n = libp2pwebrtc.IsWebRTCDirectMultiaddr(addr) + } + if ok && n > 0 { + out := addr + for i := 0; i < n; i++ { + out, _ = ma.SplitLast(out) + } + return out + } + return addr +} + // AllAddrs returns all the addresses the host is listening on except circuit addresses. func (h *BasicHost) AllAddrs() []ma.Multiaddr { return h.addressManager.DirectAddrs() diff --git a/p2p/host/basic/basic_host_test.go b/p2p/host/basic/basic_host_test.go index 80a1d3dd62..d8cb6cbf9a 100644 --- a/p2p/host/basic/basic_host_test.go +++ b/p2p/host/basic/basic_host_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package basichost import ( diff --git a/p2p/host/basic/natmgr_test.go b/p2p/host/basic/natmgr_test.go index c216e4f6d1..541b84120e 100644 --- a/p2p/host/basic/natmgr_test.go +++ b/p2p/host/basic/natmgr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package basichost import ( diff --git a/p2p/host/pstoremanager/pstoremanager_test.go b/p2p/host/pstoremanager/pstoremanager_test.go index 9321031c5a..2b764f8072 100644 --- a/p2p/host/pstoremanager/pstoremanager_test.go +++ b/p2p/host/pstoremanager/pstoremanager_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package pstoremanager_test import ( diff --git a/p2p/transport/webtransport/cert_manager.go b/p2p/transport/webtransport/cert_manager.go index 494d5e7616..4a4be7a1aa 100644 --- a/p2p/transport/webtransport/cert_manager.go +++ b/p2p/transport/webtransport/cert_manager.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/cert_manager_test.go b/p2p/transport/webtransport/cert_manager_test.go index 942d47174e..1a6088ac81 100644 --- a/p2p/transport/webtransport/cert_manager_test.go +++ b/p2p/transport/webtransport/cert_manager_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/conn.go b/p2p/transport/webtransport/conn.go index f76ad10438..816c282505 100644 --- a/p2p/transport/webtransport/conn.go +++ b/p2p/transport/webtransport/conn.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/crypto.go b/p2p/transport/webtransport/crypto.go index 90504ead01..258557d4d4 100644 --- a/p2p/transport/webtransport/crypto.go +++ b/p2p/transport/webtransport/crypto.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/crypto_test.go b/p2p/transport/webtransport/crypto_test.go index ba439c28af..0eddd95e47 100644 --- a/p2p/transport/webtransport/crypto_test.go +++ b/p2p/transport/webtransport/crypto_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/listener.go b/p2p/transport/webtransport/listener.go index ff611fe927..0920f706eb 100644 --- a/p2p/transport/webtransport/listener.go +++ b/p2p/transport/webtransport/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/multiaddr.go b/p2p/transport/webtransport/multiaddr.go index 6b7b37f487..b4ff935fac 100644 --- a/p2p/transport/webtransport/multiaddr.go +++ b/p2p/transport/webtransport/multiaddr.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/multiaddr_test.go b/p2p/transport/webtransport/multiaddr_test.go index 3f0a3ec0bf..2213902374 100644 --- a/p2p/transport/webtransport/multiaddr_test.go +++ b/p2p/transport/webtransport/multiaddr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/noise_early_data.go b/p2p/transport/webtransport/noise_early_data.go index 6ca8d9ddb7..d2d867536b 100644 --- a/p2p/transport/webtransport/noise_early_data.go +++ b/p2p/transport/webtransport/noise_early_data.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/stream.go b/p2p/transport/webtransport/stream.go index 115d3a8344..4a9bc33023 100644 --- a/p2p/transport/webtransport/stream.go +++ b/p2p/transport/webtransport/stream.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/transport.go b/p2p/transport/webtransport/transport.go index 8818c7b8a7..00d1929257 100644 --- a/p2p/transport/webtransport/transport.go +++ b/p2p/transport/webtransport/transport.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport import ( diff --git a/p2p/transport/webtransport/transport_test.go b/p2p/transport/webtransport/transport_test.go index 38968b110d..88edf1f156 100644 --- a/p2p/transport/webtransport/transport_test.go +++ b/p2p/transport/webtransport/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebtransport_test import ( From d6d445f6811730de7696cd9cf685df9ae14e9e2b Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 20:48:21 +0300 Subject: [PATCH 05/13] fix build --- p2p/transport/webtransport/multiaddr.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/p2p/transport/webtransport/multiaddr.go b/p2p/transport/webtransport/multiaddr.go index b4ff935fac..6b7b37f487 100644 --- a/p2p/transport/webtransport/multiaddr.go +++ b/p2p/transport/webtransport/multiaddr.go @@ -1,6 +1,3 @@ -//go:build !js -// +build !js - package libp2pwebtransport import ( From b436663e52521646aa029cc3e329620f9b232d37 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 21:14:20 +0300 Subject: [PATCH 06/13] exclude webrtc and websocket from compilation as well --- p2p/transport/webrtc/fingerprint.go | 3 +++ p2p/transport/webrtc/hex_test.go | 3 +++ p2p/transport/webrtc/logger.go | 3 +++ p2p/transport/webrtc/sdp.go | 3 +++ p2p/transport/webrtc/sdp_test.go | 3 +++ p2p/transport/webrtc/stream.go | 3 +++ p2p/transport/webrtc/stream_read.go | 3 +++ p2p/transport/webrtc/stream_write.go | 3 +++ p2p/transport/webrtc/udpmux/mux.go | 3 +++ p2p/transport/webrtc/udpmux/mux_test.go | 3 +++ p2p/transport/webrtc/udpmux/muxed_connection.go | 3 +++ p2p/transport/websocket/addrs.go | 3 +++ p2p/transport/websocket/addrs_test.go | 3 +++ p2p/transport/websocket/conn.go | 3 +++ p2p/transport/websocket/listener.go | 3 +++ p2p/transport/websocket/websocket.go | 3 +++ p2p/transport/websocket/websocket_test.go | 3 +++ test-plans/cmd/ping/main.go | 3 +++ 18 files changed, 54 insertions(+) diff --git a/p2p/transport/webrtc/fingerprint.go b/p2p/transport/webrtc/fingerprint.go index 0b1fe488b4..1cb846d208 100644 --- a/p2p/transport/webrtc/fingerprint.go +++ b/p2p/transport/webrtc/fingerprint.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/hex_test.go b/p2p/transport/webrtc/hex_test.go index c8a7147498..4cd43b63bd 100644 --- a/p2p/transport/webrtc/hex_test.go +++ b/p2p/transport/webrtc/hex_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/logger.go b/p2p/transport/webrtc/logger.go index ebe5fa309f..ae86cb4a6d 100644 --- a/p2p/transport/webrtc/logger.go +++ b/p2p/transport/webrtc/logger.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/sdp.go b/p2p/transport/webrtc/sdp.go index 878b668a18..1856f172ea 100644 --- a/p2p/transport/webrtc/sdp.go +++ b/p2p/transport/webrtc/sdp.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/sdp_test.go b/p2p/transport/webrtc/sdp_test.go index 2e7ac5b3e8..bc573cb2c1 100644 --- a/p2p/transport/webrtc/sdp_test.go +++ b/p2p/transport/webrtc/sdp_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/stream.go b/p2p/transport/webrtc/stream.go index c92457ccb0..a05f0b8bc5 100644 --- a/p2p/transport/webrtc/stream.go +++ b/p2p/transport/webrtc/stream.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/stream_read.go b/p2p/transport/webrtc/stream_read.go index 003d5f563e..d0289fac6d 100644 --- a/p2p/transport/webrtc/stream_read.go +++ b/p2p/transport/webrtc/stream_read.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/stream_write.go b/p2p/transport/webrtc/stream_write.go index 8629955191..7dc33b0bb0 100644 --- a/p2p/transport/webrtc/stream_write.go +++ b/p2p/transport/webrtc/stream_write.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2pwebrtc import ( diff --git a/p2p/transport/webrtc/udpmux/mux.go b/p2p/transport/webrtc/udpmux/mux.go index 76d68d8e89..e5faa63107 100644 --- a/p2p/transport/webrtc/udpmux/mux.go +++ b/p2p/transport/webrtc/udpmux/mux.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + // The udpmux package contains the logic for multiplexing multiple WebRTC (ICE) // connections over a single UDP socket. package udpmux diff --git a/p2p/transport/webrtc/udpmux/mux_test.go b/p2p/transport/webrtc/udpmux/mux_test.go index b75f3e8302..fdf04f90c4 100644 --- a/p2p/transport/webrtc/udpmux/mux_test.go +++ b/p2p/transport/webrtc/udpmux/mux_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package udpmux import ( diff --git a/p2p/transport/webrtc/udpmux/muxed_connection.go b/p2p/transport/webrtc/udpmux/muxed_connection.go index 84d30c84b1..26117eb644 100644 --- a/p2p/transport/webrtc/udpmux/muxed_connection.go +++ b/p2p/transport/webrtc/udpmux/muxed_connection.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package udpmux import ( diff --git a/p2p/transport/websocket/addrs.go b/p2p/transport/websocket/addrs.go index 6fbd852636..86e465d416 100644 --- a/p2p/transport/websocket/addrs.go +++ b/p2p/transport/websocket/addrs.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package websocket import ( diff --git a/p2p/transport/websocket/addrs_test.go b/p2p/transport/websocket/addrs_test.go index 1a73c28762..2bed18e6c4 100644 --- a/p2p/transport/websocket/addrs_test.go +++ b/p2p/transport/websocket/addrs_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package websocket import ( diff --git a/p2p/transport/websocket/conn.go b/p2p/transport/websocket/conn.go index 0d4746086d..34ba375f3e 100644 --- a/p2p/transport/websocket/conn.go +++ b/p2p/transport/websocket/conn.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package websocket import ( diff --git a/p2p/transport/websocket/listener.go b/p2p/transport/websocket/listener.go index b7402c0e98..590b4205bc 100644 --- a/p2p/transport/websocket/listener.go +++ b/p2p/transport/websocket/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package websocket import ( diff --git a/p2p/transport/websocket/websocket.go b/p2p/transport/websocket/websocket.go index 3a6badac5d..07c599377c 100644 --- a/p2p/transport/websocket/websocket.go +++ b/p2p/transport/websocket/websocket.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + // Package websocket implements a websocket based transport for go-libp2p. package websocket diff --git a/p2p/transport/websocket/websocket_test.go b/p2p/transport/websocket/websocket_test.go index 2c47adf326..3d207b29ed 100644 --- a/p2p/transport/websocket/websocket_test.go +++ b/p2p/transport/websocket/websocket_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package websocket import ( diff --git a/test-plans/cmd/ping/main.go b/test-plans/cmd/ping/main.go index c836a72e72..8e49653fe7 100644 --- a/test-plans/cmd/ping/main.go +++ b/test-plans/cmd/ping/main.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package main import ( From c162d219d52552e24046a93a0b188c42825d326e Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 21:18:47 +0300 Subject: [PATCH 07/13] set private transport to an empty array by default for JS --- defaults.go | 5 +++++ defaults_js.go | 1 + defaults_shared.go | 6 ------ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/defaults.go b/defaults.go index 1b3e49fc42..8d819a50c4 100644 --- a/defaults.go +++ b/defaults.go @@ -18,3 +18,8 @@ var DefaultTransports = ChainOptions( Transport(webtransport.New), Transport(libp2pwebrtc.New), ) + +var DefaultPrivateTransports = ChainOptions( + Transport(tcp.NewTCPTransport), + Transport(ws.New), +) diff --git a/defaults_js.go b/defaults_js.go index 5baad2e7cc..1ee0cdd505 100644 --- a/defaults_js.go +++ b/defaults_js.go @@ -5,3 +5,4 @@ package libp2p // Only WebSocket and WebTransport are supported in the browser. var DefaultTransports = ChainOptions() +var DefaultPrivateTransports = ChainOptions() diff --git a/defaults_shared.go b/defaults_shared.go index 9bd57e4608..6fa008c3a6 100644 --- a/defaults_shared.go +++ b/defaults_shared.go @@ -13,8 +13,6 @@ import ( "github.com/libp2p/go-libp2p/p2p/net/swarm" "github.com/libp2p/go-libp2p/p2p/security/noise" tls "github.com/libp2p/go-libp2p/p2p/security/tls" - "github.com/libp2p/go-libp2p/p2p/transport/tcp" - ws "github.com/libp2p/go-libp2p/p2p/transport/websocket" "github.com/prometheus/client_golang/prometheus" "github.com/multiformats/go-multiaddr" @@ -44,10 +42,6 @@ var DefaultMuxers = Muxer(yamux.ID, yamux.DefaultTransport) // // Use this option when you want to *extend* the set of transports used by // libp2p instead of replacing them. -var DefaultPrivateTransports = ChainOptions( - Transport(tcp.NewTCPTransport), - Transport(ws.New), -) // DefaultPeerstore configures libp2p to use the default peerstore. var DefaultPeerstore Option = func(cfg *Config) error { From 4b161b31594b6425679093238e21f412624e4c44 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 21:33:42 +0300 Subject: [PATCH 08/13] exclude tcp and tcpreuse from JS as well --- config/config_js.go | 7 ------- p2p/net/swarm/peers_test.go | 3 +++ p2p/transport/tcp/metrics.go | 2 +- p2p/transport/tcp/metrics_general.go | 2 +- p2p/transport/tcp/metrics_none.go | 2 +- p2p/transport/tcp/metrics_test.go | 3 +++ p2p/transport/tcp/tcp.go | 3 +++ p2p/transport/tcp/tcp_test.go | 3 +++ p2p/transport/tcpreuse/connwithscope.go | 3 +++ p2p/transport/tcpreuse/demultiplex.go | 3 +++ p2p/transport/tcpreuse/demultiplex_test.go | 3 +++ p2p/transport/tcpreuse/dialer.go | 3 +++ p2p/transport/tcpreuse/internal/sampledconn/sampledconn.go | 3 +++ .../tcpreuse/internal/sampledconn/sampledconn_test.go | 3 +++ p2p/transport/tcpreuse/listener.go | 3 +++ p2p/transport/tcpreuse/listener_test.go | 3 +++ p2p/transport/tcpreuse/reuseport.go | 3 +++ 17 files changed, 42 insertions(+), 10 deletions(-) diff --git a/config/config_js.go b/config/config_js.go index f88af0a7fd..79d2307447 100644 --- a/config/config_js.go +++ b/config/config_js.go @@ -33,7 +33,6 @@ import ( relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" "github.com/libp2p/go-libp2p/p2p/protocol/identify" - "github.com/libp2p/go-libp2p/p2p/transport/tcpreuse" ma "github.com/multiformats/go-multiaddr" "github.com/prometheus/client_golang/prometheus" "go.uber.org/fx" @@ -125,12 +124,6 @@ func (cfg *Config) addTransports() ([]fx.Option, error) { fx.Provide(func() connmgr.ConnectionGater { return cfg.ConnectionGater }), fx.Provide(func() pnet.PSK { return cfg.PSK }), fx.Provide(func() network.ResourceManager { return cfg.ResourceManager }), - fx.Provide(func(upgrader transport.Upgrader) *tcpreuse.ConnMgr { - if !cfg.ShareTCPListener { - return nil - } - return tcpreuse.NewConnMgr(tcpreuse.EnvReuseportVal, upgrader) - }), } fxopts = append(fxopts, cfg.Transports...) if cfg.Insecure { diff --git a/p2p/net/swarm/peers_test.go b/p2p/net/swarm/peers_test.go index 44f1309f75..34a490bc81 100644 --- a/p2p/net/swarm/peers_test.go +++ b/p2p/net/swarm/peers_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package swarm_test import ( diff --git a/p2p/transport/tcp/metrics.go b/p2p/transport/tcp/metrics.go index e3946cf348..bb68a11585 100644 --- a/p2p/transport/tcp/metrics.go +++ b/p2p/transport/tcp/metrics.go @@ -1,4 +1,4 @@ -//go:build !windows && !riscv64 && !loong64 +//go:build !js && !windows && !riscv64 && !loong64 package tcp diff --git a/p2p/transport/tcp/metrics_general.go b/p2p/transport/tcp/metrics_general.go index 419fff360e..34285a57c2 100644 --- a/p2p/transport/tcp/metrics_general.go +++ b/p2p/transport/tcp/metrics_general.go @@ -1,4 +1,4 @@ -//go:build !linux && !darwin && !windows && !riscv64 && !loong64 +//go:build !linux && !darwin && !windows && !riscv64 && !loong64 && !js package tcp diff --git a/p2p/transport/tcp/metrics_none.go b/p2p/transport/tcp/metrics_none.go index 2e561fb6cb..8a2e96cbc6 100644 --- a/p2p/transport/tcp/metrics_none.go +++ b/p2p/transport/tcp/metrics_none.go @@ -1,6 +1,6 @@ // riscv64 see: https://github.com/marten-seemann/tcp/pull/1 -//go:build windows || riscv64 || loong64 +//go:build windows || riscv64 || loong64 || js package tcp diff --git a/p2p/transport/tcp/metrics_test.go b/p2p/transport/tcp/metrics_test.go index 7645abc8df..5cd2f977b6 100644 --- a/p2p/transport/tcp/metrics_test.go +++ b/p2p/transport/tcp/metrics_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcp import ( diff --git a/p2p/transport/tcp/tcp.go b/p2p/transport/tcp/tcp.go index 0b0980c96e..be6a991e18 100644 --- a/p2p/transport/tcp/tcp.go +++ b/p2p/transport/tcp/tcp.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcp import ( diff --git a/p2p/transport/tcp/tcp_test.go b/p2p/transport/tcp/tcp_test.go index 1a712acf35..db1b8c814c 100644 --- a/p2p/transport/tcp/tcp_test.go +++ b/p2p/transport/tcp/tcp_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcp import ( diff --git a/p2p/transport/tcpreuse/connwithscope.go b/p2p/transport/tcpreuse/connwithscope.go index 23354b81cd..f9d6fffef8 100644 --- a/p2p/transport/tcpreuse/connwithscope.go +++ b/p2p/transport/tcpreuse/connwithscope.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( diff --git a/p2p/transport/tcpreuse/demultiplex.go b/p2p/transport/tcpreuse/demultiplex.go index f9175ecfdb..48530854ed 100644 --- a/p2p/transport/tcpreuse/demultiplex.go +++ b/p2p/transport/tcpreuse/demultiplex.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( diff --git a/p2p/transport/tcpreuse/demultiplex_test.go b/p2p/transport/tcpreuse/demultiplex_test.go index e201f2ca75..5455146209 100644 --- a/p2p/transport/tcpreuse/demultiplex_test.go +++ b/p2p/transport/tcpreuse/demultiplex_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import "testing" diff --git a/p2p/transport/tcpreuse/dialer.go b/p2p/transport/tcpreuse/dialer.go index d6ea1fc6a0..5511acc742 100644 --- a/p2p/transport/tcpreuse/dialer.go +++ b/p2p/transport/tcpreuse/dialer.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( diff --git a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn.go b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn.go index ff1f8caf44..5c0f081e02 100644 --- a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn.go +++ b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package sampledconn import ( diff --git a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go index 6c4e989b16..0898b7d6d3 100644 --- a/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go +++ b/p2p/transport/tcpreuse/internal/sampledconn/sampledconn_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package sampledconn import ( diff --git a/p2p/transport/tcpreuse/listener.go b/p2p/transport/tcpreuse/listener.go index 4c787acc3e..5cdf327c43 100644 --- a/p2p/transport/tcpreuse/listener.go +++ b/p2p/transport/tcpreuse/listener.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( diff --git a/p2p/transport/tcpreuse/listener_test.go b/p2p/transport/tcpreuse/listener_test.go index 0f91d4992d..bc72783c10 100644 --- a/p2p/transport/tcpreuse/listener_test.go +++ b/p2p/transport/tcpreuse/listener_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( diff --git a/p2p/transport/tcpreuse/reuseport.go b/p2p/transport/tcpreuse/reuseport.go index a2529c0bda..70b40a9b02 100644 --- a/p2p/transport/tcpreuse/reuseport.go +++ b/p2p/transport/tcpreuse/reuseport.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tcpreuse import ( From 6f3a53c24f109cd90c82357d50feb1c23a404d30 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 22:45:49 +0300 Subject: [PATCH 09/13] disable compilation for tls for wasm --- defaults.go | 7 +++++++ defaults_js.go | 6 ++++++ defaults_shared.go | 6 ------ p2p/security/tls/crypto.go | 3 +++ p2p/security/tls/transport.go | 3 +++ p2p/security/tls/transport_test.go | 3 +++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/defaults.go b/defaults.go index 8d819a50c4..e7ad90049c 100644 --- a/defaults.go +++ b/defaults.go @@ -4,6 +4,8 @@ package libp2p import ( + "github.com/libp2p/go-libp2p/p2p/security/noise" + tls "github.com/libp2p/go-libp2p/p2p/security/tls" quic "github.com/libp2p/go-libp2p/p2p/transport/quic" "github.com/libp2p/go-libp2p/p2p/transport/tcp" libp2pwebrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc" @@ -23,3 +25,8 @@ var DefaultPrivateTransports = ChainOptions( Transport(tcp.NewTCPTransport), Transport(ws.New), ) + +var DefaultSecurity = ChainOptions( + Security(tls.ID, tls.New), + Security(noise.ID, noise.New), +) diff --git a/defaults_js.go b/defaults_js.go index 1ee0cdd505..ae46b30189 100644 --- a/defaults_js.go +++ b/defaults_js.go @@ -3,6 +3,12 @@ package libp2p +import "github.com/libp2p/go-libp2p/p2p/security/noise" + // Only WebSocket and WebTransport are supported in the browser. var DefaultTransports = ChainOptions() var DefaultPrivateTransports = ChainOptions() + +var DefaultSecurity = ChainOptions( + Security(noise.ID, noise.New), +) diff --git a/defaults_shared.go b/defaults_shared.go index 6fa008c3a6..ad055814a2 100644 --- a/defaults_shared.go +++ b/defaults_shared.go @@ -11,8 +11,6 @@ import ( "github.com/libp2p/go-libp2p/p2p/muxer/yamux" "github.com/libp2p/go-libp2p/p2p/net/connmgr" "github.com/libp2p/go-libp2p/p2p/net/swarm" - "github.com/libp2p/go-libp2p/p2p/security/noise" - tls "github.com/libp2p/go-libp2p/p2p/security/tls" "github.com/prometheus/client_golang/prometheus" "github.com/multiformats/go-multiaddr" @@ -22,10 +20,6 @@ import ( // // Useful when you want to extend, but not replace, the supported transport // security protocols. -var DefaultSecurity = ChainOptions( - Security(tls.ID, tls.New), - Security(noise.ID, noise.New), -) // DefaultMuxers configures libp2p to use the stream connection multiplexers. // diff --git a/p2p/security/tls/crypto.go b/p2p/security/tls/crypto.go index 70a594d060..157cc7d4f0 100644 --- a/p2p/security/tls/crypto.go +++ b/p2p/security/tls/crypto.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2ptls import ( diff --git a/p2p/security/tls/transport.go b/p2p/security/tls/transport.go index 0c494a7fdc..3358a0d94c 100644 --- a/p2p/security/tls/transport.go +++ b/p2p/security/tls/transport.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2ptls import ( diff --git a/p2p/security/tls/transport_test.go b/p2p/security/tls/transport_test.go index b53d9bf0f6..953e008f87 100644 --- a/p2p/security/tls/transport_test.go +++ b/p2p/security/tls/transport_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2ptls import ( From b67437e9ffc4d3e9a9ac9bb45a2f63fa754971fe Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 10 May 2025 22:48:00 +0300 Subject: [PATCH 10/13] exclude more tests from wasm --- p2p/protocol/autonatv2/autonat_test.go | 3 +++ p2p/protocol/autonatv2/server_test.go | 3 +++ p2p/protocol/circuitv2/relay/relay_test.go | 3 +++ p2p/protocol/identify/id_glass_test.go | 3 +++ p2p/protocol/identify/id_test.go | 3 +++ p2p/protocol/identify/obsaddr_test.go | 3 +++ p2p/security/tls/cmd/tlsdiag.go | 3 +++ p2p/security/tls/cmd/tlsdiag/client.go | 3 +++ p2p/security/tls/cmd/tlsdiag/server.go | 3 +++ p2p/security/tls/crypto_test.go | 3 +++ 10 files changed, 30 insertions(+) diff --git a/p2p/protocol/autonatv2/autonat_test.go b/p2p/protocol/autonatv2/autonat_test.go index 11c8f02195..702d340386 100644 --- a/p2p/protocol/autonatv2/autonat_test.go +++ b/p2p/protocol/autonatv2/autonat_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package autonatv2 import ( diff --git a/p2p/protocol/autonatv2/server_test.go b/p2p/protocol/autonatv2/server_test.go index c65aa5b880..f0c605ed5c 100644 --- a/p2p/protocol/autonatv2/server_test.go +++ b/p2p/protocol/autonatv2/server_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package autonatv2 import ( diff --git a/p2p/protocol/circuitv2/relay/relay_test.go b/p2p/protocol/circuitv2/relay/relay_test.go index 7c5ec927df..207ba49d5b 100644 --- a/p2p/protocol/circuitv2/relay/relay_test.go +++ b/p2p/protocol/circuitv2/relay/relay_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package relay_test import ( diff --git a/p2p/protocol/identify/id_glass_test.go b/p2p/protocol/identify/id_glass_test.go index 3eec26cb75..287e84b759 100644 --- a/p2p/protocol/identify/id_glass_test.go +++ b/p2p/protocol/identify/id_glass_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package identify import ( diff --git a/p2p/protocol/identify/id_test.go b/p2p/protocol/identify/id_test.go index 34d6c240f6..39d5d7e5c7 100644 --- a/p2p/protocol/identify/id_test.go +++ b/p2p/protocol/identify/id_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package identify_test import ( diff --git a/p2p/protocol/identify/obsaddr_test.go b/p2p/protocol/identify/obsaddr_test.go index aad55bb375..2f05bf18ad 100644 --- a/p2p/protocol/identify/obsaddr_test.go +++ b/p2p/protocol/identify/obsaddr_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package identify import ( diff --git a/p2p/security/tls/cmd/tlsdiag.go b/p2p/security/tls/cmd/tlsdiag.go index d6f7bac674..360009858f 100644 --- a/p2p/security/tls/cmd/tlsdiag.go +++ b/p2p/security/tls/cmd/tlsdiag.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package main import ( diff --git a/p2p/security/tls/cmd/tlsdiag/client.go b/p2p/security/tls/cmd/tlsdiag/client.go index a29189a375..ba6932dfd4 100644 --- a/p2p/security/tls/cmd/tlsdiag/client.go +++ b/p2p/security/tls/cmd/tlsdiag/client.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tlsdiag import ( diff --git a/p2p/security/tls/cmd/tlsdiag/server.go b/p2p/security/tls/cmd/tlsdiag/server.go index cd702a7334..efbdddafd8 100644 --- a/p2p/security/tls/cmd/tlsdiag/server.go +++ b/p2p/security/tls/cmd/tlsdiag/server.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package tlsdiag import ( diff --git a/p2p/security/tls/crypto_test.go b/p2p/security/tls/crypto_test.go index 6171d178cd..be9da2ccf9 100644 --- a/p2p/security/tls/crypto_test.go +++ b/p2p/security/tls/crypto_test.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package libp2ptls import ( From 5549b9a96857e935d383c191c28edb4b0379c341 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sun, 11 May 2025 00:20:12 +0300 Subject: [PATCH 11/13] prevent config throwing a reflect error --- config/config_js.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/config/config_js.go b/config/config_js.go index 79d2307447..662d8d62d5 100644 --- a/config/config_js.go +++ b/config/config_js.go @@ -277,6 +277,24 @@ func (cfg *Config) NewNode() (host.Host, error) { }), ) + fxopts = append(fxopts, + fx.Provide(func(eventBus event.Bus, lifecycle fx.Lifecycle) (*swarm.Swarm, error) { + sw, err := cfg.makeSwarm(eventBus, !cfg.DisableMetrics) + if err != nil { + return nil, err + } + lifecycle.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + return sw.Listen(cfg.ListenAddrs...) + }, + OnStop: func(ctx context.Context) error { + return sw.Close() + }, + }) + return sw, nil + }), + ) + var bh *bhost.BasicHost fxopts = append(fxopts, fx.Invoke(func(bho *bhost.BasicHost) { bh = bho })) fxopts = append(fxopts, fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) { From 11c6d7319778fe4fe5db182ac0a797809859a835 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Wed, 14 May 2025 18:24:30 +0300 Subject: [PATCH 12/13] enure that quic-go doesn't end up in wasm bundle --- config/config_js.go | 3 --- config/quic.go | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config_js.go b/config/config_js.go index 662d8d62d5..fa9a784ded 100644 --- a/config/config_js.go +++ b/config/config_js.go @@ -176,9 +176,6 @@ func (cfg *Config) addTransports() ([]fx.Option, error) { ))) } - fxopts = append(fxopts, fx.Provide(PrivKeyToStatelessResetKey)) - fxopts = append(fxopts, fx.Provide(PrivKeyToTokenGeneratorKey)) - fxopts = append(fxopts, fx.Invoke( fx.Annotate( func(swrm *swarm.Swarm, tpts []transport.Transport) error { diff --git a/config/quic.go b/config/quic.go index 66c40da97f..79ca80ae5e 100644 --- a/config/quic.go +++ b/config/quic.go @@ -1,3 +1,6 @@ +//go:build !js +// +build !js + package config import ( From 3dbfc94e78144e324b53a4d122dd70dab5d1d51b Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 2 Aug 2025 13:47:00 +0300 Subject: [PATCH 13/13] autonat merge --- config/config_js.go | 13 +++++++++++-- config/config_shared.go | 14 +++----------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/config/config_js.go b/config/config_js.go index fa9a784ded..807fc4579f 100644 --- a/config/config_js.go +++ b/config/config_js.go @@ -29,6 +29,7 @@ import ( routed "github.com/libp2p/go-libp2p/p2p/host/routed" "github.com/libp2p/go-libp2p/p2p/net/swarm" tptu "github.com/libp2p/go-libp2p/p2p/net/upgrader" + "github.com/libp2p/go-libp2p/p2p/protocol/autonatv2" circuitv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client" relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay" "github.com/libp2p/go-libp2p/p2p/protocol/holepunch" @@ -226,7 +227,9 @@ func (cfg *Config) NewNode() (host.Host, error) { fx.Provide(func() crypto.PrivKey { return cfg.PeerKey }), - + fx.Provide(func() (*autonatv2.AutoNAT, error) { + return nil, nil + }), fx.Provide(cfg.newBasicHost), fx.Provide(func(bh *bhost.BasicHost) identify.IDService { return bh.IDService() @@ -321,7 +324,13 @@ func (cfg *Config) NewNode() (host.Host, error) { } if cfg.Routing != nil { - return &closableRoutedHost{App: app, RoutedHost: rh}, nil + return &closableRoutedHost{ + closableBasicHost: closableBasicHost{ + App: app, + BasicHost: bh, + }, + RoutedHost: rh, + }, nil } return &closableBasicHost{App: app, BasicHost: bh}, nil } diff --git a/config/config_shared.go b/config/config_shared.go index 0256a2314f..3599cdada7 100644 --- a/config/config_shared.go +++ b/config/config_shared.go @@ -23,6 +23,7 @@ import ( "github.com/libp2p/go-libp2p/p2p/host/eventbus" "github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem" "github.com/libp2p/go-libp2p/p2p/net/swarm" + "github.com/libp2p/go-libp2p/p2p/protocol/autonatv2" ma "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" @@ -186,15 +187,7 @@ func (cfg *Config) makeAutoNATV2Host() (host.Host, error) { return dialerHost, nil } -func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.BasicHost, error) { - var autonatv2Dialer host.Host - if cfg.EnableAutoNATv2 { - ah, err := cfg.makeAutoNATV2Host() - if err != nil { - return nil, err - } - autonatv2Dialer = ah - } +func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus, an *autonatv2.AutoNAT) (*bhost.BasicHost, error) { h, err := bhost.NewHost(swrm, &bhost.HostOpts{ EventBus: eventBus, ConnManager: cfg.ConnManager, @@ -210,8 +203,7 @@ func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.B EnableMetrics: !cfg.DisableMetrics, PrometheusRegisterer: cfg.PrometheusRegisterer, DisableIdentifyAddressDiscovery: cfg.DisableIdentifyAddressDiscovery, - EnableAutoNATv2: cfg.EnableAutoNATv2, - AutoNATv2Dialer: autonatv2Dialer, + AutoNATv2: an, }) if err != nil { return nil, err