]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Extract HTTP tracker client into separate package
authorMatt Joiner <anacrolix@gmail.com>
Tue, 22 Jun 2021 13:28:26 +0000 (23:28 +1000)
committerMatt Joiner <anacrolix@gmail.com>
Tue, 22 Jun 2021 13:28:26 +0000 (23:28 +1000)
tracker/expvar.go
tracker/http/http.go [moved from tracker/http.go with 75% similarity]
tracker/http/http_test.go [moved from tracker/http_test.go with 98% similarity]
tracker/http/peer.go [new file with mode: 0644]
tracker/peer.go
tracker/shared/shared.go [new file with mode: 0644]
tracker/tracker.go
tracker/udp.go

index de5a49858bf8661cf2fab167691822a3b3bc8323..bf0317392f4909c58d38e2bdc4fb9c5be51fd635 100644 (file)
@@ -1,7 +1 @@
 package tracker
-
-import (
-       "expvar"
-)
-
-var vars = expvar.NewMap("tracker")
similarity index 75%
rename from tracker/http.go
rename to tracker/http/http.go
index eb2650454eb3a28bbc0e30c48e814e31272f5308..c74243cdaee2a7de457ea708db4f2cc86dc0726f 100644 (file)
@@ -1,8 +1,10 @@
-package tracker
+package http
 
 import (
        "bytes"
+       "context"
        "crypto/tls"
+       "expvar"
        "fmt"
        "io"
        "math"
@@ -13,10 +15,38 @@ import (
 
        "github.com/anacrolix/dht/v2/krpc"
        "github.com/anacrolix/missinggo/httptoo"
-
        "github.com/anacrolix/torrent/bencode"
+       "github.com/anacrolix/torrent/tracker/shared"
+       "github.com/anacrolix/torrent/tracker/udp"
 )
 
+var vars = expvar.NewMap("tracker/http")
+
+type Client struct {
+       hc *http.Client
+}
+
+type NewClientOpts struct {
+       Proxy      func(*http.Request) (*url.URL, error)
+       ServerName string
+}
+
+func NewClient(opts NewClientOpts) Client {
+       return Client{
+               hc: &http.Client{
+                       Transport: &http.Transport{
+                               Proxy: opts.Proxy,
+                               TLSClientConfig: &tls.Config{
+                                       InsecureSkipVerify: true,
+                                       ServerName:         opts.ServerName,
+                               },
+                               // This is for S3 trackers that hold connections open.
+                               DisableKeepAlives: true,
+                       },
+               },
+       }
+}
+
 type HttpResponse struct {
        FailureReason string `bencode:"failure reason"`
        Interval      int32  `bencode:"interval"`
@@ -66,7 +96,7 @@ func (me *Peers) UnmarshalBencode(b []byte) (err error) {
        }
 }
 
-func setAnnounceParams(_url *url.URL, ar *AnnounceRequest, opts Announce) {
+func setAnnounceParams(_url *url.URL, ar *AnnounceRequest, opts AnnounceOpt) {
        q := _url.Query()
 
        q.Set("key", strconv.FormatInt(int64(ar.Key), 10))
@@ -86,7 +116,7 @@ func setAnnounceParams(_url *url.URL, ar *AnnounceRequest, opts Announce) {
        }
        q.Set("left", strconv.FormatInt(left, 10))
 
-       if ar.Event != None {
+       if ar.Event != shared.None {
                q.Set("event", ar.Event.String())
        }
        // http://stackoverflow.com/questions/17418004/why-does-tracker-server-not-understand-my-request-bittorrent-protocol
@@ -104,36 +134,27 @@ func setAnnounceParams(_url *url.URL, ar *AnnounceRequest, opts Announce) {
                // addresses for other address-families, although it's not encouraged.
                q.Add("ip", ipString)
        }
-       doIp("ipv4", opts.ClientIp4.IP)
-       doIp("ipv6", opts.ClientIp6.IP)
+       doIp("ipv4", opts.ClientIp4)
+       doIp("ipv6", opts.ClientIp6)
        _url.RawQuery = q.Encode()
 }
 
-func announceHTTP(opt Announce, _url *url.URL) (ret AnnounceResponse, err error) {
+type AnnounceOpt struct {
+       UserAgent  string
+       HostHeader string
+       ClientIp4  net.IP
+       ClientIp6  net.IP
+}
+
+type AnnounceRequest = udp.AnnounceRequest
+
+func (cl Client) Announce(ctx context.Context, ar AnnounceRequest, opt AnnounceOpt, _url *url.URL) (ret AnnounceResponse, err error) {
        _url = httptoo.CopyURL(_url)
-       setAnnounceParams(_url, &opt.Request, opt)
-       req, err := http.NewRequest("GET", _url.String(), nil)
+       setAnnounceParams(_url, &ar, opt)
+       req, err := http.NewRequestWithContext(ctx, http.MethodGet, _url.String(), nil)
        req.Header.Set("User-Agent", opt.UserAgent)
        req.Host = opt.HostHeader
-       if opt.Context != nil {
-               req = req.WithContext(opt.Context)
-       }
-       resp, err := (&http.Client{
-               //Timeout: time.Second * 15,
-               Transport: &http.Transport{
-                       //Dial: (&net.Dialer{
-                       //      Timeout: 15 * time.Second,
-                       //}).Dial,
-                       Proxy: opt.HTTPProxy,
-                       //TLSHandshakeTimeout: 15 * time.Second,
-                       TLSClientConfig: &tls.Config{
-                               InsecureSkipVerify: true,
-                               ServerName:         opt.ServerName,
-                       },
-                       // This is for S3 trackers that hold connections open.
-                       DisableKeepAlives: true,
-               },
-       }).Do(req)
+       resp, err := cl.hc.Do(req)
        if err != nil {
                return
        }
@@ -175,3 +196,10 @@ func announceHTTP(opt Announce, _url *url.URL) (ret AnnounceResponse, err error)
        }
        return
 }
+
+type AnnounceResponse struct {
+       Interval int32 // Minimum seconds the local peer should wait before next announce.
+       Leechers int32
+       Seeders  int32
+       Peers    []Peer
+}
similarity index 98%
rename from tracker/http_test.go
rename to tracker/http/http_test.go
index 474c4aa4ec5572eb97d694260010134e99c129b8..f0066de75b17e4933d5105e34436be1955e502cb 100644 (file)
@@ -1,12 +1,11 @@
-package tracker
+package http
 
 import (
        "testing"
 
+       "github.com/anacrolix/torrent/bencode"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
-
-       "github.com/anacrolix/torrent/bencode"
 )
 
 func TestUnmarshalHTTPResponsePeerDicts(t *testing.T) {
diff --git a/tracker/http/peer.go b/tracker/http/peer.go
new file mode 100644 (file)
index 0000000..f715e20
--- /dev/null
@@ -0,0 +1,38 @@
+package http
+
+import (
+       "fmt"
+       "net"
+
+       "github.com/anacrolix/dht/v2/krpc"
+)
+
+type Peer struct {
+       IP   net.IP
+       Port int
+       ID   []byte
+}
+
+func (p Peer) String() string {
+       loc := net.JoinHostPort(p.IP.String(), fmt.Sprintf("%d", p.Port))
+       if len(p.ID) != 0 {
+               return fmt.Sprintf("%x at %s", p.ID, loc)
+       } else {
+               return loc
+       }
+}
+
+// Set from the non-compact form in BEP 3.
+func (p *Peer) FromDictInterface(d map[string]interface{}) {
+       p.IP = net.ParseIP(d["ip"].(string))
+       if _, ok := d["peer id"]; ok {
+               p.ID = []byte(d["peer id"].(string))
+       }
+       p.Port = int(d["port"].(int64))
+}
+
+func (p Peer) FromNodeAddr(na krpc.NodeAddr) Peer {
+       p.IP = na.IP
+       p.Port = na.Port
+       return p
+}
index 3cda3dc3a520525116ff3d7bc6538e8391f67cea..bf0317392f4909c58d38e2bdc4fb9c5be51fd635 100644 (file)
@@ -1,38 +1 @@
 package tracker
-
-import (
-       "fmt"
-       "net"
-
-       "github.com/anacrolix/dht/v2/krpc"
-)
-
-type Peer struct {
-       IP   net.IP
-       Port int
-       ID   []byte
-}
-
-func (p Peer) String() string {
-       loc := net.JoinHostPort(p.IP.String(), fmt.Sprintf("%d", p.Port))
-       if len(p.ID) != 0 {
-               return fmt.Sprintf("%x at %s", p.ID, loc)
-       } else {
-               return loc
-       }
-}
-
-// Set from the non-compact form in BEP 3.
-func (p *Peer) FromDictInterface(d map[string]interface{}) {
-       p.IP = net.ParseIP(d["ip"].(string))
-       if _, ok := d["peer id"]; ok {
-               p.ID = []byte(d["peer id"].(string))
-       }
-       p.Port = int(d["port"].(int64))
-}
-
-func (p Peer) FromNodeAddr(na krpc.NodeAddr) Peer {
-       p.IP = na.IP
-       p.Port = na.Port
-       return p
-}
diff --git a/tracker/shared/shared.go b/tracker/shared/shared.go
new file mode 100644 (file)
index 0000000..7859ea9
--- /dev/null
@@ -0,0 +1,10 @@
+package shared
+
+import "github.com/anacrolix/torrent/tracker/udp"
+
+const (
+       None      udp.AnnounceEvent = iota
+       Completed                   // The local peer just completed the torrent.
+       Started                     // The local peer has just resumed this torrent.
+       Stopped                     // The local peer is leaving the swarm.
+)
index 0a187574476beab4e70590c55fb7ddad26797bf1..66344fe2475f046db44ae21d0a29f817f4b6077a 100644 (file)
@@ -8,26 +8,25 @@ import (
        "time"
 
        "github.com/anacrolix/dht/v2/krpc"
+       trHttp "github.com/anacrolix/torrent/tracker/http"
+       "github.com/anacrolix/torrent/tracker/shared"
        "github.com/anacrolix/torrent/tracker/udp"
 )
 
+const (
+       None      = shared.None
+       Started   = shared.Started
+       Stopped   = shared.Stopped
+       Completed = shared.Completed
+)
+
 type AnnounceRequest = udp.AnnounceRequest
 
-type AnnounceResponse struct {
-       Interval int32 // Minimum seconds the local peer should wait before next announce.
-       Leechers int32
-       Seeders  int32
-       Peers    []Peer
-}
+type AnnounceResponse = trHttp.AnnounceResponse
 
-type AnnounceEvent = udp.AnnounceEvent
+type Peer = trHttp.Peer
 
-const (
-       None      AnnounceEvent = iota
-       Completed               // The local peer just completed the torrent.
-       Started                 // The local peer has just resumed this torrent.
-       Stopped                 // The local peer is leaving the swarm.
-)
+type AnnounceEvent = udp.AnnounceEvent
 
 var (
        ErrBadScheme = errors.New("unknown scheme")
@@ -66,7 +65,16 @@ func (me Announce) Do() (res AnnounceResponse, err error) {
        }
        switch _url.Scheme {
        case "http", "https":
-               return announceHTTP(me, _url)
+               cl := trHttp.NewClient(trHttp.NewClientOpts{
+                       Proxy:      me.HTTPProxy,
+                       ServerName: me.ServerName,
+               })
+               return cl.Announce(me.Context, me.Request, trHttp.AnnounceOpt{
+                       UserAgent:  me.UserAgent,
+                       HostHeader: me.HostHeader,
+                       ClientIp4:  me.ClientIp4.IP,
+                       ClientIp6:  me.ClientIp6.IP,
+               }, _url)
        case "udp", "udp4", "udp6":
                return announceUDP(me, _url)
        default:
index 4fb00b117381834d33a54526281cbd4e356ff0ca..ac9f3e1c9416fcab59705857a11b3f313c608054 100644 (file)
@@ -8,6 +8,7 @@ import (
 
        "github.com/anacrolix/dht/v2/krpc"
        "github.com/anacrolix/missinggo"
+       trHttp "github.com/anacrolix/torrent/tracker/http"
        "github.com/anacrolix/torrent/tracker/udp"
 )
 
@@ -73,7 +74,7 @@ func (c *udpAnnounce) Do(req AnnounceRequest) (res AnnounceResponse, err error)
        res.Leechers = h.Leechers
        res.Seeders = h.Seeders
        for _, cp := range nas.NodeAddrs() {
-               res.Peers = append(res.Peers, Peer{}.FromNodeAddr(cp))
+               res.Peers = append(res.Peers, trHttp.Peer{}.FromNodeAddr(cp))
        }
        return
 }