diff --git a/config/config.go b/config/config.go index f491f92dff..f67c117c6c 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "fmt" + "time" "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/crypto" @@ -45,7 +46,14 @@ type NATManagerC func(network.Network) bhost.NATManager type RoutingC func(host.Host) (routing.PeerRouting, error) -// AutoNATMode defines the AutoNAT behavior for the libp2p host. +// autoNATConfig defines the AutoNAT behavior for the libp2p host. +type AutoNATConfig struct { + ForceReachability *network.Reachability + EnableService bool + ThrottleGlobalLimit int + ThrottlePeerLimit int + ThrottleInterval time.Duration +} // Config describes a set of settings for a libp2p node // @@ -84,9 +92,8 @@ type Config struct { Routing RoutingC EnableAutoRelay bool - Reachability network.Reachability - AutoNATService bool - StaticRelays []peer.AddrInfo + AutoNATConfig + StaticRelays []peer.AddrInfo } func (cfg *Config) makeSwarm(ctx context.Context) (*swarm.Swarm, error) { @@ -280,10 +287,17 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { } } - autonatOpts := []autonat.Option{autonat.UsingAddresses(func() []ma.Multiaddr { - return addrF(h.AllAddrs()) - })} - if cfg.AutoNATService { + autonatOpts := []autonat.Option{ + autonat.UsingAddresses(func() []ma.Multiaddr { + return addrF(h.AllAddrs()) + }), + } + 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 nil, err @@ -322,8 +336,8 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { // closed (as long as we close the underlying network). autonatOpts = append(autonatOpts, autonat.EnableService(dialerHost.Network())) } - if cfg.Reachability != network.ReachabilityUnknown { - autonatOpts = append(autonatOpts, autonat.WithReachability(cfg.Reachability)) + if cfg.AutoNATConfig.ForceReachability != nil { + autonatOpts = append(autonatOpts, autonat.WithReachability(*cfg.AutoNATConfig.ForceReachability)) } if _, err = autonat.New(ctx, h, autonatOpts...); err != nil { diff --git a/options.go b/options.go index 8efe9a834b..7dc5cdff92 100644 --- a/options.go +++ b/options.go @@ -6,6 +6,7 @@ package libp2p import ( "fmt" "net" + "time" "github.com/libp2p/go-libp2p-core/connmgr" "github.com/libp2p/go-libp2p-core/crypto" @@ -283,7 +284,8 @@ func DefaultStaticRelays() Option { // forcing the local node to believe it is reachable externally. func ForceReachabilityPublic() Option { return func(cfg *Config) error { - cfg.Reachability = network.ReachabilityPublic + public := network.Reachability(network.ReachabilityPublic) + cfg.AutoNATConfig.ForceReachability = &public return nil } } @@ -292,7 +294,8 @@ func ForceReachabilityPublic() Option { // forceing the local node to believe it is behind a NAT and not reachable externally. func ForceReachabilityPrivate() Option { return func(cfg *Config) error { - cfg.Reachability = network.ReachabilityPrivate + private := network.Reachability(network.ReachabilityPrivate) + cfg.AutoNATConfig.ForceReachability = &private return nil } } @@ -302,7 +305,20 @@ func ForceReachabilityPrivate() Option { // to peers, and then tell them if it was successful in making such connections. func EnableNATService() Option { return func(cfg *Config) error { - cfg.AutoNATService = true + 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 } }