config.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package torrent
  2. import (
  3. "context"
  4. "net"
  5. "net/http"
  6. "net/url"
  7. "time"
  8. "github.com/anacrolix/dht/v2"
  9. "github.com/anacrolix/dht/v2/krpc"
  10. "github.com/anacrolix/log"
  11. "github.com/anacrolix/missinggo/v2"
  12. "github.com/pion/webrtc/v3"
  13. "golang.org/x/time/rate"
  14. "github.com/anacrolix/torrent/iplist"
  15. "github.com/anacrolix/torrent/mse"
  16. "github.com/anacrolix/torrent/storage"
  17. "github.com/anacrolix/torrent/version"
  18. )
  19. // Contains config elements that are exclusive to tracker handling. There may be other fields in
  20. // ClientConfig that are also relevant.
  21. type ClientTrackerConfig struct {
  22. // Don't announce to trackers. This only leaves DHT to discover peers.
  23. DisableTrackers bool `long:"disable-trackers"`
  24. // Defines DialContext func to use for HTTP tracker announcements
  25. TrackerDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
  26. // Defines ListenPacket func to use for UDP tracker announcements
  27. TrackerListenPacket func(network, addr string) (net.PacketConn, error)
  28. // Takes a tracker's hostname and requests DNS A and AAAA records.
  29. // Used in case DNS lookups require a special setup (i.e., dns-over-https)
  30. LookupTrackerIp func(*url.URL) ([]net.IP, error)
  31. }
  32. type ClientDhtConfig struct {
  33. // Don't create a DHT.
  34. NoDHT bool `long:"disable-dht"`
  35. DhtStartingNodes func(network string) dht.StartingNodesGetter
  36. // Called for each anacrolix/dht Server created for the Client.
  37. ConfigureAnacrolixDhtServer func(*dht.ServerConfig)
  38. PeriodicallyAnnounceTorrentsToDht bool
  39. // OnQuery hook func
  40. DHTOnQuery func(query *krpc.Msg, source net.Addr) (propagate bool)
  41. }
  42. // Probably not safe to modify this after it's given to a Client.
  43. type ClientConfig struct {
  44. ClientTrackerConfig
  45. ClientDhtConfig
  46. // Store torrent file data in this directory unless .DefaultStorage is
  47. // specified.
  48. DataDir string `long:"data-dir" description:"directory to store downloaded torrent data"`
  49. // The address to listen for new uTP and TCP BitTorrent protocol connections. DHT shares a UDP
  50. // socket with uTP unless configured otherwise.
  51. ListenHost func(network string) string
  52. ListenPort int
  53. NoDefaultPortForwarding bool
  54. UpnpID string
  55. DisablePEX bool `long:"disable-pex"`
  56. // Never send chunks to peers.
  57. NoUpload bool `long:"no-upload"`
  58. // Disable uploading even when it isn't fair.
  59. DisableAggressiveUpload bool `long:"disable-aggressive-upload"`
  60. // Upload even after there's nothing in it for us. By default uploading is
  61. // not altruistic, we'll only upload to encourage the peer to reciprocate.
  62. Seed bool `long:"seed"`
  63. // Only applies to chunks uploaded to peers, to maintain responsiveness
  64. // communicating local Client state to peers. Each limiter token
  65. // represents one byte. The Limiter's burst must be large enough to fit a
  66. // whole chunk, which is usually 16 KiB (see TorrentSpec.ChunkSize).
  67. UploadRateLimiter *rate.Limiter
  68. // Rate limits all reads from connections to peers. Each limiter token
  69. // represents one byte. The Limiter's burst must be bigger than the
  70. // largest Read performed on a the underlying rate-limiting io.Reader
  71. // minus one. This is likely to be the larger of the main read loop buffer
  72. // (~4096), and the requested chunk size (~16KiB, see
  73. // TorrentSpec.ChunkSize).
  74. DownloadRateLimiter *rate.Limiter
  75. // Maximum unverified bytes across all torrents. Not used if zero.
  76. MaxUnverifiedBytes int64
  77. // User-provided Client peer ID. If not present, one is generated automatically.
  78. PeerID string
  79. // For the bittorrent protocol.
  80. DisableUTP bool
  81. // For the bittorrent protocol.
  82. DisableTCP bool `long:"disable-tcp"`
  83. // Called to instantiate storage for each added torrent. Builtin backends
  84. // are in the storage package. If not set, the "file" implementation is
  85. // used (and Closed when the Client is Closed).
  86. DefaultStorage storage.ClientImpl
  87. HeaderObfuscationPolicy HeaderObfuscationPolicy
  88. // The crypto methods to offer when initiating connections with header obfuscation.
  89. CryptoProvides mse.CryptoMethod
  90. // Chooses the crypto method to use when receiving connections with header obfuscation.
  91. CryptoSelector mse.CryptoSelector
  92. IPBlocklist iplist.Ranger
  93. DisableIPv6 bool `long:"disable-ipv6"`
  94. DisableIPv4 bool
  95. DisableIPv4Peers bool
  96. // Perform logging and any other behaviour that will help debug.
  97. Debug bool `help:"enable debugging"`
  98. Logger log.Logger
  99. // Used for torrent sources and webseeding if set.
  100. WebTransport http.RoundTripper
  101. // Defines proxy for HTTP requests, such as for trackers. It's commonly set from the result of
  102. // "net/http".ProxyURL(HTTPProxy).
  103. HTTPProxy func(*http.Request) (*url.URL, error)
  104. // Defines DialContext func to use for HTTP requests, such as for fetching metainfo and webtorrent seeds
  105. HTTPDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
  106. // HTTPUserAgent changes default UserAgent for HTTP requests
  107. HTTPUserAgent string
  108. // HttpRequestDirector modifies the request before it's sent.
  109. // Useful for adding authentication headers, for example
  110. HttpRequestDirector func(*http.Request) error
  111. // WebsocketTrackerHttpHeader returns a custom header to be used when dialing a websocket connection
  112. // to the tracker. Useful for adding authentication headers
  113. WebsocketTrackerHttpHeader func() http.Header
  114. // Updated occasionally to when there's been some changes to client
  115. // behaviour in case other clients are assuming anything of us. See also
  116. // `bep20`.
  117. ExtendedHandshakeClientVersion string
  118. // Peer ID client identifier prefix. We'll update this occasionally to
  119. // reflect changes to client behaviour that other clients may depend on.
  120. // Also see `extendedHandshakeClientVersion`.
  121. Bep20 string
  122. // Peer dial timeout to use when there are limited peers.
  123. NominalDialTimeout time.Duration
  124. // Minimum peer dial timeout to use (even if we have lots of peers).
  125. MinDialTimeout time.Duration
  126. EstablishedConnsPerTorrent int
  127. HalfOpenConnsPerTorrent int
  128. TotalHalfOpenConns int
  129. // Maximum number of peer addresses in reserve.
  130. TorrentPeersHighWater int
  131. // Minumum number of peers before effort is made to obtain more peers.
  132. TorrentPeersLowWater int
  133. // Limit how long handshake can take. This is to reduce the lingering
  134. // impact of a few bad apples. 4s loses 1% of successful handshakes that
  135. // are obtained with 60s timeout, and 5% of unsuccessful handshakes.
  136. HandshakesTimeout time.Duration
  137. // How long between writes before sending a keep alive message on a peer connection that we want
  138. // to maintain.
  139. KeepAliveTimeout time.Duration
  140. // Maximum bytes to buffer per peer connection for peer request data before it is sent.
  141. MaxAllocPeerRequestDataPerConn int64
  142. // The IP addresses as our peers should see them. May differ from the
  143. // local interfaces due to NAT or other network configurations.
  144. PublicIp4 net.IP
  145. PublicIp6 net.IP
  146. // Accept rate limiting affects excessive connection attempts from IPs that fail during
  147. // handshakes or request torrents that we don't have.
  148. DisableAcceptRateLimiting bool
  149. // Don't add connections that have the same peer ID as an existing
  150. // connection for a given Torrent.
  151. DropDuplicatePeerIds bool
  152. // Drop peers that are complete if we are also complete and have no use for the peer. This is a
  153. // bit of a special case, since a peer could also be useless if they're just not interested, or
  154. // we don't intend to obtain all of a torrent's data.
  155. DropMutuallyCompletePeers bool
  156. // Whether to accept peer connections at all.
  157. AcceptPeerConnections bool
  158. // Whether a Client should want conns without delegating to any attached Torrents. This is
  159. // useful when torrents might be added dynamically in callbacks for example.
  160. AlwaysWantConns bool
  161. Extensions PeerExtensionBits
  162. // Bits that peers must have set to proceed past handshakes.
  163. MinPeerExtensions PeerExtensionBits
  164. DisableWebtorrent bool
  165. DisableWebseeds bool
  166. Callbacks Callbacks
  167. // ICEServerList defines a slice describing servers available to be used by
  168. // ICE, such as STUN and TURN servers.
  169. ICEServerList []webrtc.ICEServer
  170. // Deprecated. ICEServers does not support server authentication and therefore
  171. // it cannot be used with most TURN servers. Use ICEServerList instead.
  172. // ICEServers is kept for legacy support.
  173. ICEServers []string
  174. DialRateLimiter *rate.Limiter
  175. PieceHashersPerTorrent int // default: 2
  176. }
  177. func (cfg *ClientConfig) SetListenAddr(addr string) *ClientConfig {
  178. host, port, err := missinggo.ParseHostPort(addr)
  179. if err != nil {
  180. panic(err)
  181. }
  182. cfg.ListenHost = func(string) string { return host }
  183. cfg.ListenPort = port
  184. return cfg
  185. }
  186. func NewDefaultClientConfig() *ClientConfig {
  187. cc := &ClientConfig{
  188. HTTPUserAgent: version.DefaultHttpUserAgent,
  189. ExtendedHandshakeClientVersion: version.DefaultExtendedHandshakeClientVersion,
  190. Bep20: version.DefaultBep20Prefix,
  191. UpnpID: version.DefaultUpnpId,
  192. NominalDialTimeout: 20 * time.Second,
  193. MinDialTimeout: 3 * time.Second,
  194. EstablishedConnsPerTorrent: 50,
  195. HalfOpenConnsPerTorrent: 25,
  196. TotalHalfOpenConns: 100,
  197. TorrentPeersHighWater: 500,
  198. TorrentPeersLowWater: 50,
  199. HandshakesTimeout: 4 * time.Second,
  200. KeepAliveTimeout: time.Minute,
  201. MaxAllocPeerRequestDataPerConn: 1 << 20,
  202. ListenHost: func(string) string { return "" },
  203. UploadRateLimiter: unlimited,
  204. DownloadRateLimiter: unlimited,
  205. DisableAcceptRateLimiting: true,
  206. DropMutuallyCompletePeers: true,
  207. HeaderObfuscationPolicy: HeaderObfuscationPolicy{
  208. Preferred: true,
  209. RequirePreferred: false,
  210. },
  211. CryptoSelector: mse.DefaultCryptoSelector,
  212. CryptoProvides: mse.AllSupportedCrypto,
  213. ListenPort: 42069,
  214. Extensions: defaultPeerExtensionBytes(),
  215. AcceptPeerConnections: true,
  216. MaxUnverifiedBytes: 64 << 20,
  217. DialRateLimiter: rate.NewLimiter(10, 10),
  218. PieceHashersPerTorrent: 2,
  219. }
  220. cc.DhtStartingNodes = func(network string) dht.StartingNodesGetter {
  221. return func() ([]dht.Addr, error) { return dht.GlobalBootstrapAddrs(network) }
  222. }
  223. cc.PeriodicallyAnnounceTorrentsToDht = true
  224. return cc
  225. }
  226. type HeaderObfuscationPolicy struct {
  227. RequirePreferred bool // Whether the value of Preferred is a strict requirement.
  228. Preferred bool // Whether header obfuscation is preferred.
  229. }