tracker.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package tracker
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "net/url"
  9. "time"
  10. "github.com/anacrolix/dht/v2/krpc"
  11. "github.com/anacrolix/log"
  12. trHttp "github.com/anacrolix/torrent/tracker/http"
  13. "github.com/anacrolix/torrent/tracker/shared"
  14. "github.com/anacrolix/torrent/tracker/udp"
  15. )
  16. const (
  17. None = shared.None
  18. Started = shared.Started
  19. Stopped = shared.Stopped
  20. Completed = shared.Completed
  21. )
  22. type AnnounceRequest = udp.AnnounceRequest
  23. type AnnounceResponse = trHttp.AnnounceResponse
  24. type Peer = trHttp.Peer
  25. type AnnounceEvent = udp.AnnounceEvent
  26. var ErrBadScheme = errors.New("unknown scheme")
  27. type Announce struct {
  28. TrackerUrl string
  29. Request AnnounceRequest
  30. HostHeader string
  31. HttpProxy func(*http.Request) (*url.URL, error)
  32. HttpRequestDirector func(*http.Request) error
  33. DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
  34. ListenPacket func(network, addr string) (net.PacketConn, error)
  35. ServerName string
  36. UserAgent string
  37. UdpNetwork string
  38. // If the port is zero, it's assumed to be the same as the Request.Port.
  39. ClientIp4 krpc.NodeAddr
  40. // If the port is zero, it's assumed to be the same as the Request.Port.
  41. ClientIp6 krpc.NodeAddr
  42. Context context.Context
  43. Logger log.Logger
  44. }
  45. // The code *is* the documentation.
  46. const DefaultTrackerAnnounceTimeout = 15 * time.Second
  47. func (me Announce) Do() (res AnnounceResponse, err error) {
  48. cl, err := NewClient(me.TrackerUrl, NewClientOpts{
  49. Http: trHttp.NewClientOpts{
  50. Proxy: me.HttpProxy,
  51. DialContext: me.DialContext,
  52. ServerName: me.ServerName,
  53. },
  54. UdpNetwork: me.UdpNetwork,
  55. Logger: me.Logger.WithContextValue(fmt.Sprintf("tracker client for %q", me.TrackerUrl)),
  56. ListenPacket: me.ListenPacket,
  57. })
  58. if err != nil {
  59. return
  60. }
  61. defer cl.Close()
  62. if me.Context == nil {
  63. // This is just to maintain the old behaviour that should be a timeout of 15s. Users can
  64. // override it by providing their own Context. See comments elsewhere about longer timeouts
  65. // acting as rate limiting overloaded trackers.
  66. ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
  67. defer cancel()
  68. me.Context = ctx
  69. }
  70. return cl.Announce(me.Context, me.Request, trHttp.AnnounceOpt{
  71. UserAgent: me.UserAgent,
  72. HostHeader: me.HostHeader,
  73. ClientIp4: me.ClientIp4.IP,
  74. ClientIp6: me.ClientIp6.IP,
  75. HttpRequestDirector: me.HttpRequestDirector,
  76. })
  77. }