145 lines
4.4 KiB
Go
145 lines
4.4 KiB
Go
package autonat
|
|
|
|
import (
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/libp2p/go-libp2p-core/host"
|
|
"github.com/libp2p/go-libp2p-core/network"
|
|
)
|
|
|
|
// config holds configurable options for the autonat subsystem.
|
|
type config struct {
|
|
host host.Host
|
|
|
|
addressFunc AddrFunc
|
|
dialPolicy dialPolicy
|
|
dialer network.Network
|
|
forceReachability bool
|
|
reachability network.Reachability
|
|
|
|
// client
|
|
bootDelay time.Duration
|
|
retryInterval time.Duration
|
|
refreshInterval time.Duration
|
|
requestTimeout time.Duration
|
|
throttlePeerPeriod time.Duration
|
|
|
|
// server
|
|
dialTimeout time.Duration
|
|
maxPeerAddresses int
|
|
throttleGlobalMax int
|
|
throttlePeerMax int
|
|
throttleResetPeriod time.Duration
|
|
throttleResetJitter time.Duration
|
|
}
|
|
|
|
var defaults = func(c *config) error {
|
|
c.bootDelay = 15 * time.Second
|
|
c.retryInterval = 90 * time.Second
|
|
c.refreshInterval = 15 * time.Minute
|
|
c.requestTimeout = 30 * time.Second
|
|
c.throttlePeerPeriod = 90 * time.Second
|
|
|
|
c.dialTimeout = 15 * time.Second
|
|
c.maxPeerAddresses = 16
|
|
c.throttleGlobalMax = 30
|
|
c.throttlePeerMax = 3
|
|
c.throttleResetPeriod = 1 * time.Minute
|
|
c.throttleResetJitter = 15 * time.Second
|
|
return nil
|
|
}
|
|
|
|
// EnableService specifies that AutoNAT should be allowed to run a NAT service to help
|
|
// other peers determine their own NAT status. The provided Network should not be the
|
|
// default network/dialer of the host passed to `New`, as the NAT system will need to
|
|
// make parallel connections, and as such will modify both the associated peerstore
|
|
// and terminate connections of this dialer. The dialer provided
|
|
// should be compatible (TCP/UDP) however with the transports of the libp2p network.
|
|
func EnableService(dialer network.Network) Option {
|
|
return func(c *config) error {
|
|
if dialer == c.host.Network() || dialer.Peerstore() == c.host.Peerstore() {
|
|
return errors.New("dialer should not be that of the host")
|
|
}
|
|
c.dialer = dialer
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithReachability overrides autonat to simply report an over-ridden reachability
|
|
// status.
|
|
func WithReachability(reachability network.Reachability) Option {
|
|
return func(c *config) error {
|
|
c.forceReachability = true
|
|
c.reachability = reachability
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// UsingAddresses allows overriding which Addresses the AutoNAT client believes
|
|
// are "its own". Useful for testing, or for more exotic port-forwarding
|
|
// scenarios where the host may be listening on different ports than it wants
|
|
// to externally advertise or verify connectability on.
|
|
func UsingAddresses(addrFunc AddrFunc) Option {
|
|
return func(c *config) error {
|
|
if addrFunc == nil {
|
|
return errors.New("invalid address function supplied")
|
|
}
|
|
c.addressFunc = addrFunc
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithSchedule configures how agressively probes will be made to verify the
|
|
// address of the host. retryInterval indicates how often probes should be made
|
|
// when the host lacks confident about its address, while refresh interval
|
|
// is the schedule of periodic probes when the host believes it knows its
|
|
// steady-state reachability.
|
|
func WithSchedule(retryInterval, refreshInterval time.Duration) Option {
|
|
return func(c *config) error {
|
|
c.retryInterval = retryInterval
|
|
c.refreshInterval = refreshInterval
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithoutStartupDelay removes the initial delay the NAT subsystem typically
|
|
// uses as a buffer for ensuring that connectivity and guesses as to the hosts
|
|
// local interfaces have settled down during startup.
|
|
func WithoutStartupDelay() Option {
|
|
return func(c *config) error {
|
|
c.bootDelay = 1
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithoutThrottling indicates that this autonat service should not place
|
|
// restrictions on how many peers it is willing to help when acting as
|
|
// a server.
|
|
func WithoutThrottling() Option {
|
|
return func(c *config) error {
|
|
c.throttleGlobalMax = 0
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithThrottling specifies how many peers (`amount`) it is willing to help
|
|
// ever `interval` amount of time when acting as a server.
|
|
func WithThrottling(amount int, interval time.Duration) Option {
|
|
return func(c *config) error {
|
|
c.throttleGlobalMax = amount
|
|
c.throttleResetPeriod = interval
|
|
c.throttleResetJitter = interval / 4
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithPeerThrottling specifies a limit for the maximum number of IP checks
|
|
// this node will provide to an individual peer in each `interval`.
|
|
func WithPeerThrottling(amount int) Option {
|
|
return func(c *config) error {
|
|
c.throttlePeerMax = amount
|
|
return nil
|
|
}
|
|
}
|