+ Debug bool `help:"enable debugging"`
+ Logger log.Logger
+
+ // Used for torrent sources and webseeding if set.
+ WebTransport http.RoundTripper
+ // Defines proxy for HTTP requests, such as for trackers. It's commonly set from the result of
+ // "net/http".ProxyURL(HTTPProxy).
+ HTTPProxy func(*http.Request) (*url.URL, error)
+ // Defines DialContext func to use for HTTP requests, such as for fetching metainfo and webtorrent seeds
+ HTTPDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
+ // HTTPUserAgent changes default UserAgent for HTTP requests
+ HTTPUserAgent string
+ // HttpRequestDirector modifies the request before it's sent.
+ // Useful for adding authentication headers, for example
+ HttpRequestDirector func(*http.Request) error
+ // WebsocketTrackerHttpHeader returns a custom header to be used when dialing a websocket connection
+ // to the tracker. Useful for adding authentication headers
+ WebsocketTrackerHttpHeader func() http.Header
+ // Updated occasionally to when there's been some changes to client
+ // behaviour in case other clients are assuming anything of us. See also
+ // `bep20`.
+ ExtendedHandshakeClientVersion string
+ // Peer ID client identifier prefix. We'll update this occasionally to
+ // reflect changes to client behaviour that other clients may depend on.
+ // Also see `extendedHandshakeClientVersion`.
+ Bep20 string
+
+ // Peer dial timeout to use when there are limited peers.
+ NominalDialTimeout time.Duration
+ // Minimum peer dial timeout to use (even if we have lots of peers).
+ MinDialTimeout time.Duration
+ EstablishedConnsPerTorrent int
+ HalfOpenConnsPerTorrent int
+ TotalHalfOpenConns int
+ // Maximum number of peer addresses in reserve.
+ TorrentPeersHighWater int
+ // Minumum number of peers before effort is made to obtain more peers.
+ TorrentPeersLowWater int
+
+ // Limit how long handshake can take. This is to reduce the lingering
+ // impact of a few bad apples. 4s loses 1% of successful handshakes that
+ // are obtained with 60s timeout, and 5% of unsuccessful handshakes.
+ HandshakesTimeout time.Duration
+ // How long between writes before sending a keep alive message on a peer connection that we want
+ // to maintain.
+ KeepAliveTimeout time.Duration
+ // Maximum bytes to buffer per peer connection for peer request data before it is sent.
+ MaxAllocPeerRequestDataPerConn int64
+
+ // The IP addresses as our peers should see them. May differ from the
+ // local interfaces due to NAT or other network configurations.
+ PublicIp4 net.IP
+ PublicIp6 net.IP
+
+ // Accept rate limiting affects excessive connection attempts from IPs that fail during
+ // handshakes or request torrents that we don't have.
+ DisableAcceptRateLimiting bool
+ // Don't add connections that have the same peer ID as an existing
+ // connection for a given Torrent.
+ DropDuplicatePeerIds bool
+ // Drop peers that are complete if we are also complete and have no use for the peer. This is a
+ // bit of a special case, since a peer could also be useless if they're just not interested, or
+ // we don't intend to obtain all of a torrent's data.
+ DropMutuallyCompletePeers bool
+ // Whether to accept peer connections at all.
+ AcceptPeerConnections bool
+ // Whether a Client should want conns without delegating to any attached Torrents. This is
+ // useful when torrents might be added dynamically in callbacks for example.
+ AlwaysWantConns bool
+
+ Extensions PeerExtensionBits
+ // Bits that peers must have set to proceed past handshakes.
+ MinPeerExtensions PeerExtensionBits
+
+ DisableWebtorrent bool
+ DisableWebseeds bool
+
+ Callbacks Callbacks
+
+ // ICEServers defines a slice describing servers available to be used by
+ // ICE, such as STUN and TURN servers.
+ ICEServers []string
+
+ DialRateLimiter *rate.Limiter
+
+ PieceHashersPerTorrent int // default: 2
+}
+
+func (cfg *ClientConfig) SetListenAddr(addr string) *ClientConfig {
+ host, port, err := missinggo.ParseHostPort(addr)
+ if err != nil {
+ panic(err)
+ }
+ cfg.ListenHost = func(string) string { return host }
+ cfg.ListenPort = port
+ return cfg
+}
+
+func NewDefaultClientConfig() *ClientConfig {
+ cc := &ClientConfig{
+ HTTPUserAgent: version.DefaultHttpUserAgent,
+ ExtendedHandshakeClientVersion: version.DefaultExtendedHandshakeClientVersion,
+ Bep20: version.DefaultBep20Prefix,
+ UpnpID: version.DefaultUpnpId,
+ NominalDialTimeout: 20 * time.Second,
+ MinDialTimeout: 3 * time.Second,
+ EstablishedConnsPerTorrent: 50,
+ HalfOpenConnsPerTorrent: 25,
+ TotalHalfOpenConns: 100,
+ TorrentPeersHighWater: 500,
+ TorrentPeersLowWater: 50,
+ HandshakesTimeout: 4 * time.Second,
+ KeepAliveTimeout: time.Minute,
+ MaxAllocPeerRequestDataPerConn: 1 << 20,
+ ListenHost: func(string) string { return "" },
+ UploadRateLimiter: unlimited,
+ DownloadRateLimiter: unlimited,
+ DisableAcceptRateLimiting: true,
+ DropMutuallyCompletePeers: true,
+ HeaderObfuscationPolicy: HeaderObfuscationPolicy{
+ Preferred: true,
+ RequirePreferred: false,
+ },
+ CryptoSelector: mse.DefaultCryptoSelector,
+ CryptoProvides: mse.AllSupportedCrypto,
+ ListenPort: 42069,
+ Extensions: defaultPeerExtensionBytes(),
+ AcceptPeerConnections: true,
+ MaxUnverifiedBytes: 64 << 20,
+ DialRateLimiter: rate.NewLimiter(10, 10),
+ PieceHashersPerTorrent: 2,
+ }
+ cc.DhtStartingNodes = func(network string) dht.StartingNodesGetter {
+ return func() ([]dht.Addr, error) { return dht.GlobalBootstrapAddrs(network) }
+ }
+ cc.PeriodicallyAnnounceTorrentsToDht = true
+ return cc