]> Sergey Matveev's repositories - btrtrc.git/blobdiff - tracker/tracker.go
Handle torrentfs failure in test.sh
[btrtrc.git] / tracker / tracker.go
index 576353b51cad1b9512994e2e213717180879efaf..e96a08a1175e63dc439b4865ae15288b7defbf03 100644 (file)
@@ -1,50 +1,89 @@
 package tracker
 
 import (
+       "context"
+       "errors"
+       "fmt"
        "net"
+       "net/http"
        "net/url"
-)
-
-type AnnounceRequest struct {
-       InfoHash   [20]byte
-       PeerId     [20]byte
-       Downloaded int64
-       Left       int64
-       Uploaded   int64
-       Event      AnnounceEvent
-       IPAddress  int32
-       Key        int32
-       NumWant    int32
-       Port       int16
-}
+       "time"
 
-type AnnounceResponse struct {
-       Interval int32
-       Leechers int32
-       Seeders  int32
-       Peers    []Peer
-}
-
-type AnnounceEvent int32
+       "github.com/anacrolix/dht/v2/krpc"
+       "github.com/anacrolix/log"
 
-type Peer struct {
-       IP   net.IP
-       Port int
-}
+       trHttp "github.com/anacrolix/torrent/tracker/http"
+       "github.com/anacrolix/torrent/tracker/shared"
+       "github.com/anacrolix/torrent/tracker/udp"
+)
 
 const (
-       None AnnounceEvent = iota
+       None      = shared.None
+       Started   = shared.Started
+       Stopped   = shared.Stopped
+       Completed = shared.Completed
 )
 
-type Client interface {
-       Announce(*AnnounceRequest) (AnnounceResponse, error)
-}
+type AnnounceRequest = udp.AnnounceRequest
+
+type AnnounceResponse = trHttp.AnnounceResponse
 
-var schemes = make(map[string]func(*url.URL) Client)
+type Peer = trHttp.Peer
 
-func RegisterClientScheme(scheme string, newFunc func(*url.URL) Client) {
+type AnnounceEvent = udp.AnnounceEvent
+
+var ErrBadScheme = errors.New("unknown scheme")
+
+type Announce struct {
+       TrackerUrl          string
+       Request             AnnounceRequest
+       HostHeader          string
+       HttpProxy           func(*http.Request) (*url.URL, error)
+       HttpRequestDirector func(*http.Request) error
+       DialContext         func(ctx context.Context, network, addr string) (net.Conn, error)
+       ListenPacket        func(network, addr string) (net.PacketConn, error)
+       ServerName          string
+       UserAgent           string
+       UdpNetwork          string
+       // If the port is zero, it's assumed to be the same as the Request.Port.
+       ClientIp4 krpc.NodeAddr
+       // If the port is zero, it's assumed to be the same as the Request.Port.
+       ClientIp6 krpc.NodeAddr
+       Context   context.Context
+       Logger    log.Logger
 }
 
-func New(url *url.URL) Client {
-       return schemes[url.Scheme](url)
+// The code *is* the documentation.
+const DefaultTrackerAnnounceTimeout = 15 * time.Second
+
+func (me Announce) Do() (res AnnounceResponse, err error) {
+       cl, err := NewClient(me.TrackerUrl, NewClientOpts{
+               Http: trHttp.NewClientOpts{
+                       Proxy:       me.HttpProxy,
+                       DialContext: me.DialContext,
+                       ServerName:  me.ServerName,
+               },
+               UdpNetwork:   me.UdpNetwork,
+               Logger:       me.Logger.WithContextValue(fmt.Sprintf("tracker client for %q", me.TrackerUrl)),
+               ListenPacket: me.ListenPacket,
+       })
+       if err != nil {
+               return
+       }
+       defer cl.Close()
+       if me.Context == nil {
+               // This is just to maintain the old behaviour that should be a timeout of 15s. Users can
+               // override it by providing their own Context. See comments elsewhere about longer timeouts
+               // acting as rate limiting overloaded trackers.
+               ctx, cancel := context.WithTimeout(context.Background(), DefaultTrackerAnnounceTimeout)
+               defer cancel()
+               me.Context = ctx
+       }
+       return cl.Announce(me.Context, me.Request, trHttp.AnnounceOpt{
+               UserAgent:           me.UserAgent,
+               HostHeader:          me.HostHeader,
+               ClientIp4:           me.ClientIp4.IP,
+               ClientIp6:           me.ClientIp6.IP,
+               HttpRequestDirector: me.HttpRequestDirector,
+       })
 }