Skip to content

Commit

Permalink
Extract HTTP tracker client into separate package
Browse files Browse the repository at this point in the history
  • Loading branch information
anacrolix committed Jun 22, 2021
1 parent 8df885c commit af8c41e
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 89 deletions.
6 changes: 0 additions & 6 deletions tracker/expvar.go
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
package tracker

import (
"expvar"
)

var vars = expvar.NewMap("tracker")
84 changes: 56 additions & 28 deletions tracker/http.go → tracker/http/http.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package tracker
package http

import (
"bytes"
"context"
"crypto/tls"
"expvar"
"fmt"
"io"
"math"
Expand All @@ -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"`
Expand Down Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
5 changes: 2 additions & 3 deletions tracker/http_test.go → tracker/http/http_test.go
Original file line number Diff line number Diff line change
@@ -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) {
Expand Down
38 changes: 38 additions & 0 deletions tracker/http/peer.go
Original file line number Diff line number Diff line change
@@ -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
}
37 changes: 0 additions & 37 deletions tracker/peer.go
Original file line number Diff line number Diff line change
@@ -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
}
10 changes: 10 additions & 0 deletions tracker/shared/shared.go
Original file line number Diff line number Diff line change
@@ -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.
)
36 changes: 22 additions & 14 deletions tracker/tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion tracker/udp.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit af8c41e

Please sign in to comment.