update tracker interface

This commit is contained in:
xgfone
2020-06-12 21:03:02 +08:00
parent 11fe99eeeb
commit 2a8b6bd467
6 changed files with 149 additions and 116 deletions

View File

@ -20,6 +20,7 @@
package httptracker
import (
"context"
"io"
"net/http"
"net/url"
@ -115,7 +116,7 @@ func (r AnnounceRequest) ToQuery() (vs url.Values) {
if r.Port > 0 {
vs.Set("port", strconv.FormatUint(uint64(r.Port), 10))
}
if r.NumWant > 0 {
if r.NumWant != 0 {
vs.Set("numwant", strconv.FormatUint(uint64(r.NumWant), 10))
}
if r.Key != 0 {
@ -264,24 +265,28 @@ func (sr ScrapeResponse) EncodeTo(w io.Writer) (err error) {
return bencode.NewEncoder(w).Encode(sr)
}
// TrackerClient represents a tracker client based on HTTP/HTTPS.
type TrackerClient struct {
// Client represents a tracker client based on HTTP/HTTPS.
type Client struct {
AnnounceURL string
ScrapeURL string
}
// NewTrackerClient returns a new HTTPTrackerClient.
// NewClient returns a new HTTPClient.
//
// scrapeURL may be empty, which will replace the "announce" in announceURL
// with "scrape" to generate the scrapeURL.
func NewTrackerClient(announceURL, scrapeURL string) *TrackerClient {
func NewClient(announceURL, scrapeURL string) *Client {
if scrapeURL == "" {
scrapeURL = strings.Replace(announceURL, "announce", "scrape", -1)
}
return &TrackerClient{AnnounceURL: announceURL, ScrapeURL: scrapeURL}
return &Client{AnnounceURL: announceURL, ScrapeURL: scrapeURL}
}
func (t *TrackerClient) send(u string, vs url.Values, r interface{}) (err error) {
// Close closes the client, which does nothing at present.
func (t *Client) Close() error { return nil }
func (t *Client) String() string { return t.AnnounceURL }
func (t *Client) send(c context.Context, u string, vs url.Values, r interface{}) (err error) {
sym := "?"
if strings.IndexByte(u, '?') > 0 {
sym = "&"
@ -296,17 +301,19 @@ func (t *TrackerClient) send(u string, vs url.Values, r interface{}) (err error)
}
// Announce sends a Announce request to the tracker.
func (t *TrackerClient) Announce(req AnnounceRequest) (resp AnnounceResponse, err error) {
err = t.send(t.AnnounceURL, req.ToQuery(), &resp)
func (t *Client) Announce(c context.Context, req AnnounceRequest) (
resp AnnounceResponse, err error) {
err = t.send(c, t.AnnounceURL, req.ToQuery(), &resp)
return
}
// Scrape sends a Scrape request to the tracker.
func (t *TrackerClient) Scrape(infohashes []metainfo.Hash) (resp ScrapeResponse, err error) {
func (t *Client) Scrape(c context.Context, infohashes []metainfo.Hash) (
resp ScrapeResponse, err error) {
hs := make([]string, len(infohashes))
for i, h := range infohashes {
hs[i] = h.BytesString()
}
err = t.send(t.ScrapeURL, url.Values{"info_hash": hs}, &resp)
err = t.send(c, t.ScrapeURL, url.Values{"info_hash": hs}, &resp)
return
}

View File

@ -18,6 +18,7 @@ package tracker
import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
@ -43,18 +44,18 @@ const (
//
// BEP 3, 15
type AnnounceRequest struct {
InfoHash metainfo.Hash
PeerID metainfo.Hash
InfoHash metainfo.Hash // Required
PeerID metainfo.Hash // Required
Uploaded int64
Downloaded int64
Left int64
Event uint32
Uploaded int64 // Required, but default: 0, which should be only used for test or first.
Downloaded int64 // Required, but default: 0, which should be only used for test or first.
Left int64 // Required, but default: 0, which should be only used for test or last.
Event uint32 // Required, but default: 0
IP net.IP
Key int32
NumWant int32 // -1 for default
Port uint16
IP net.IP // Optional
Key int32 // Optional
NumWant int32 // Optional, BEP 15: -1 for default. But we use 0 as default.
Port uint16 // Optional
}
// ToHTTPAnnounceRequest creates a new httptracker.AnnounceRequest from itself.
@ -187,8 +188,10 @@ func (sr ScrapeResponse) FromUDPScrapeResponse(hs []metainfo.Hash,
// Client is the interface of BT tracker client.
type Client interface {
Announce(AnnounceRequest) (AnnounceResponse, error)
Scrape([]metainfo.Hash) (ScrapeResponse, error)
Announce(context.Context, AnnounceRequest) (AnnounceResponse, error)
Scrape(context.Context, []metainfo.Hash) (ScrapeResponse, error)
String() string
Close() error
}
// NewClient returns a new Client.
@ -197,16 +200,16 @@ func NewClient(connURL string) (c Client, err error) {
if err == nil {
switch u.Scheme {
case "http", "https":
c = &tclient{http: httptracker.NewTrackerClient(connURL, "")}
c = &tclient{url: connURL, http: httptracker.NewClient(connURL, "")}
case "udp", "udp4", "udp6":
var utc *udptracker.TrackerClient
utc, err = udptracker.NewTrackerClientByDial(u.Scheme, u.Host)
var utc *udptracker.Client
utc, err = udptracker.NewClientByDial(u.Scheme, u.Host)
if err == nil {
var e []udptracker.Extension
if p := u.RequestURI(); p != "" {
e = []udptracker.Extension{udptracker.NewURLData([]byte(p))}
}
c = &tclient{exts: e, udp: utc}
c = &tclient{url: connURL, exts: e, udp: utc}
}
default:
err = fmt.Errorf("unknown url scheme '%s'", u.Scheme)
@ -216,15 +219,25 @@ func NewClient(connURL string) (c Client, err error) {
}
type tclient struct {
http *httptracker.TrackerClient // BEP 3
udp *udptracker.TrackerClient // BEP 15
exts []udptracker.Extension // BEP 41
url string
http *httptracker.Client // BEP 3
udp *udptracker.Client // BEP 15
exts []udptracker.Extension // BEP 41
}
func (c *tclient) Announce(req AnnounceRequest) (resp AnnounceResponse, err error) {
func (c *tclient) String() string { return c.url }
func (c *tclient) Close() error {
if c.http != nil {
return c.http.Close()
}
return c.udp.Close()
}
func (c *tclient) Announce(ctx context.Context, req AnnounceRequest) (resp AnnounceResponse, err error) {
if c.http != nil {
var r httptracker.AnnounceResponse
if r, err = c.http.Announce(req.ToHTTPAnnounceRequest()); err != nil {
if r, err = c.http.Announce(ctx, req.ToHTTPAnnounceRequest()); err != nil {
return
} else if r.FailureReason != "" {
err = errors.New(r.FailureReason)
@ -236,17 +249,17 @@ func (c *tclient) Announce(req AnnounceRequest) (resp AnnounceResponse, err erro
r := req.ToUDPAnnounceRequest()
r.Exts = c.exts
rs, err := c.udp.Announce(r)
rs, err := c.udp.Announce(ctx, r)
if err == nil {
resp.FromUDPAnnounceResponse(rs)
}
return
}
func (c *tclient) Scrape(hs []metainfo.Hash) (resp ScrapeResponse, err error) {
func (c *tclient) Scrape(ctx context.Context, hs []metainfo.Hash) (resp ScrapeResponse, err error) {
if c.http != nil {
var r httptracker.ScrapeResponse
if r, err = c.http.Scrape(hs); err != nil {
if r, err = c.http.Scrape(ctx, hs); err != nil {
return
} else if r.FailureReason != "" {
err = errors.New(r.FailureReason)
@ -257,7 +270,7 @@ func (c *tclient) Scrape(hs []metainfo.Hash) (resp ScrapeResponse, err error) {
return
}
r, err := c.udp.Scrape(hs)
r, err := c.udp.Scrape(ctx, hs)
if err == nil {
resp = make(ScrapeResponse, len(r))
resp.FromUDPScrapeResponse(hs, r)

View File

@ -15,6 +15,7 @@
package tracker
import (
"context"
"errors"
"fmt"
"log"
@ -73,7 +74,7 @@ func ExampleClient() {
if err != nil {
log.Fatal(err)
}
server := udptracker.NewTrackerServer(sconn, testHandler{})
server := udptracker.NewServer(sconn, testHandler{})
defer server.Close()
go server.Run()
@ -89,7 +90,7 @@ func ExampleClient() {
// Send the ANNOUNCE request to the UDP tracker server,
// and get the ANNOUNCE response.
req := AnnounceRequest{IP: net.ParseIP("127.0.0.1"), Port: 80}
resp, err := client.Announce(req)
resp, err := client.Announce(context.Background(), req)
if err != nil {
log.Fatal(err)
}
@ -106,7 +107,7 @@ func ExampleClient() {
// and get the SCRAPE respsone.
h1 := metainfo.Hash{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
h2 := metainfo.Hash{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
rs, err := client.Scrape([]metainfo.Hash{h1, h2})
rs, err := client.Scrape(context.Background(), []metainfo.Hash{h1, h2})
if err != nil {
log.Fatal(err)
} else if len(rs) != 2 {

View File

@ -16,6 +16,7 @@ package udptracker
import (
"bytes"
"context"
"encoding/binary"
"errors"
"io"
@ -27,33 +28,30 @@ import (
"github.com/xgfone/bt/metainfo"
)
// NewTrackerClientByDial returns a new TrackerClient by dialing.
func NewTrackerClientByDial(network, address string, c ...TrackerClientConfig) (
*TrackerClient, error) {
// NewClientByDial returns a new Client by dialing.
func NewClientByDial(network, address string, c ...ClientConfig) (*Client, error) {
conn, err := net.Dial(network, address)
if err != nil {
return nil, err
}
return NewTrackerClient(conn.(*net.UDPConn), c...), nil
return NewClient(conn.(*net.UDPConn), c...), nil
}
// NewTrackerClient returns a new TrackerClient.
func NewTrackerClient(conn *net.UDPConn, c ...TrackerClientConfig) *TrackerClient {
var conf TrackerClientConfig
// NewClient returns a new Client.
func NewClient(conn *net.UDPConn, c ...ClientConfig) *Client {
var conf ClientConfig
conf.set(c...)
ipv4 := strings.Contains(conn.LocalAddr().String(), ".")
return &TrackerClient{conn: conn, conf: conf, ipv4: ipv4}
return &Client{conn: conn, conf: conf, ipv4: ipv4}
}
// TrackerClientConfig is used to configure the TrackerClient.
type TrackerClientConfig struct {
// ReadTimeout is used to receive the response.
ReadTimeout time.Duration // Default: 5s
MaxBufSize int // Default: 2048
// ClientConfig is used to configure the Client.
type ClientConfig struct {
MaxBufSize int // Default: 2048
}
func (c *TrackerClientConfig) set(conf ...TrackerClientConfig) {
func (c *ClientConfig) set(conf ...ClientConfig) {
if len(conf) > 0 {
*c = conf[0]
}
@ -61,20 +59,17 @@ func (c *TrackerClientConfig) set(conf ...TrackerClientConfig) {
if c.MaxBufSize <= 0 {
c.MaxBufSize = 2048
}
if c.ReadTimeout <= 0 {
c.ReadTimeout = time.Second * 5
}
}
// TrackerClient is a tracker client based on UDP.
// Client is a tracker client based on UDP.
//
// Notice: the request is synchronized, that's, the last request is not returned,
// the next request must not be sent.
//
// BEP 15
type TrackerClient struct {
type Client struct {
ipv4 bool
conf TrackerClientConfig
conf ClientConfig
conn *net.UDPConn
last time.Time
cid uint64
@ -82,24 +77,39 @@ type TrackerClient struct {
}
// Close closes the UDP tracker client.
func (utc *TrackerClient) Close() { utc.conn.Close() }
func (utc *Client) Close() error { return utc.conn.Close() }
func (utc *Client) String() string { return utc.conn.RemoteAddr().String() }
func (utc *TrackerClient) readResp(b []byte) (int, error) {
utc.conn.SetReadDeadline(time.Now().Add(utc.conf.ReadTimeout))
return utc.conn.Read(b)
func (utc *Client) readResp(ctx context.Context, b []byte) (int, error) {
done := make(chan struct{})
var n int
var err error
go func() {
n, err = utc.conn.Read(b)
close(done)
}()
select {
case <-ctx.Done():
utc.conn.SetReadDeadline(time.Now())
return n, ctx.Err()
case <-done:
return n, err
}
}
func (utc *TrackerClient) getTranID() uint32 {
func (utc *Client) getTranID() uint32 {
return atomic.AddUint32(&utc.tid, 1)
}
func (utc *TrackerClient) parseError(b []byte) (tid uint32, reason string) {
func (utc *Client) parseError(b []byte) (tid uint32, reason string) {
tid = binary.BigEndian.Uint32(b[:4])
reason = string(b[4:])
return
}
func (utc *TrackerClient) send(b []byte) (err error) {
func (utc *Client) send(b []byte) (err error) {
n, err := utc.conn.Write(b)
if err == nil && n < len(b) {
err = io.ErrShortWrite
@ -107,7 +117,7 @@ func (utc *TrackerClient) send(b []byte) (err error) {
return
}
func (utc *TrackerClient) connect() (err error) {
func (utc *Client) connect(ctx context.Context) (err error) {
tid := utc.getTranID()
buf := bytes.NewBuffer(make([]byte, 0, 16))
binary.Write(buf, binary.BigEndian, ProtocolID)
@ -118,7 +128,7 @@ func (utc *TrackerClient) connect() (err error) {
}
data := make([]byte, 32)
n, err := utc.readResp(data)
n, err := utc.readResp(ctx, data)
if err != nil {
return
} else if n < 8 {
@ -148,18 +158,19 @@ func (utc *TrackerClient) connect() (err error) {
return
}
func (utc *TrackerClient) getConnectionID() (cid uint64, err error) {
func (utc *Client) getConnectionID(ctx context.Context) (cid uint64, err error) {
cid = utc.cid
if time.Now().Sub(utc.last) > time.Minute {
if err = utc.connect(); err == nil {
if err = utc.connect(ctx); err == nil {
cid = utc.cid
}
}
return
}
func (utc *TrackerClient) announce(req AnnounceRequest) (r AnnounceResponse, err error) {
cid, err := utc.getConnectionID()
func (utc *Client) announce(ctx context.Context, req AnnounceRequest) (
r AnnounceResponse, err error) {
cid, err := utc.getConnectionID(ctx)
if err != nil {
return
}
@ -176,7 +187,7 @@ func (utc *TrackerClient) announce(req AnnounceRequest) (r AnnounceResponse, err
}
data := make([]byte, utc.conf.MaxBufSize)
n, err := utc.readResp(data)
n, err := utc.readResp(ctx, data)
if err != nil {
return
} else if n < 8 {
@ -217,22 +228,23 @@ func (utc *TrackerClient) announce(req AnnounceRequest) (r AnnounceResponse, err
// then send the ANNOUNCE request.
// 2. If returning an error, you should retry it.
// See http://www.bittorrent.org/beps/bep_0015.html#time-outs
func (utc *TrackerClient) Announce(r AnnounceRequest) (AnnounceResponse, error) {
return utc.announce(r)
func (utc *Client) Announce(c context.Context, r AnnounceRequest) (AnnounceResponse, error) {
return utc.announce(c, r)
}
func (utc *TrackerClient) scrape(infohashes []metainfo.Hash) (rs []ScrapeResponse, err error) {
cid, err := utc.getConnectionID()
func (utc *Client) scrape(c context.Context, ihs []metainfo.Hash) (
rs []ScrapeResponse, err error) {
cid, err := utc.getConnectionID(c)
if err != nil {
return
}
tid := utc.getTranID()
buf := bytes.NewBuffer(make([]byte, 0, 16+len(infohashes)*20))
buf := bytes.NewBuffer(make([]byte, 0, 16+len(ihs)*20))
binary.Write(buf, binary.BigEndian, cid)
binary.Write(buf, binary.BigEndian, ActionScrape)
binary.Write(buf, binary.BigEndian, tid)
for _, h := range infohashes {
for _, h := range ihs {
buf.Write(h[:])
}
if err = utc.send(buf.Bytes()); err != nil {
@ -240,7 +252,7 @@ func (utc *TrackerClient) scrape(infohashes []metainfo.Hash) (rs []ScrapeRespons
}
data := make([]byte, utc.conf.MaxBufSize)
n, err := utc.readResp(data)
n, err := utc.readResp(c, data)
if err != nil {
return
} else if n < 8 {
@ -284,6 +296,6 @@ func (utc *TrackerClient) scrape(infohashes []metainfo.Hash) (rs []ScrapeRespons
// then send the ANNOUNCE request.
// 2. If returning an error, you should retry it.
// See http://www.bittorrent.org/beps/bep_0015.html#time-outs
func (utc *TrackerClient) Scrape(hs []metainfo.Hash) ([]ScrapeResponse, error) {
return utc.scrape(hs)
func (utc *Client) Scrape(c context.Context, hs []metainfo.Hash) ([]ScrapeResponse, error) {
return utc.scrape(c, hs)
}

View File

@ -27,8 +27,8 @@ import (
"github.com/xgfone/bt/metainfo"
)
// TrackerServerHandler is used to handle the request from the client.
type TrackerServerHandler interface {
// ServerHandler is used to handle the request from the client.
type ServerHandler interface {
// OnConnect is used to check whether to make the connection or not.
OnConnect(raddr *net.UDPAddr) (err error)
OnAnnounce(raddr *net.UDPAddr, req AnnounceRequest) (AnnounceResponse, error)
@ -45,13 +45,13 @@ type wrappedPeerAddr struct {
Time time.Time
}
// TrackerServerConfig is used to configure the TrackerServer.
type TrackerServerConfig struct {
// ServerConfig is used to configure the Server.
type ServerConfig struct {
MaxBufSize int // Default: 2048
ErrorLog func(format string, args ...interface{}) // Default: log.Printf
}
func (c *TrackerServerConfig) setDefault() {
func (c *ServerConfig) setDefault() {
if c.MaxBufSize <= 0 {
c.MaxBufSize = 2048
}
@ -60,11 +60,11 @@ func (c *TrackerServerConfig) setDefault() {
}
}
// TrackerServer is a tracker server based on UDP.
type TrackerServer struct {
// Server is a tracker server based on UDP.
type Server struct {
conn net.PacketConn
conf TrackerServerConfig
handler TrackerServerHandler
conf ServerConfig
handler ServerHandler
bufpool sync.Pool
cid uint64
@ -73,16 +73,15 @@ type TrackerServer struct {
conns map[uint64]wrappedPeerAddr
}
// NewTrackerServer returns a new TrackerServer.
func NewTrackerServer(c net.PacketConn, h TrackerServerHandler,
config ...TrackerServerConfig) *TrackerServer {
var conf TrackerServerConfig
if len(config) > 0 {
conf = config[0]
// NewServer returns a new Server.
func NewServer(c net.PacketConn, h ServerHandler, sc ...ServerConfig) *Server {
var conf ServerConfig
if len(sc) > 0 {
conf = sc[0]
}
conf.setDefault()
s := &TrackerServer{
s := &Server{
conf: conf,
conn: c,
handler: h,
@ -95,7 +94,7 @@ func NewTrackerServer(c net.PacketConn, h TrackerServerHandler,
}
// Close closes the tracker server.
func (uts *TrackerServer) Close() {
func (uts *Server) Close() {
select {
case <-uts.exit:
default:
@ -104,7 +103,7 @@ func (uts *TrackerServer) Close() {
}
}
func (uts *TrackerServer) cleanConnectionID(interval time.Duration) {
func (uts *Server) cleanConnectionID(interval time.Duration) {
tick := time.NewTicker(interval)
defer tick.Stop()
for {
@ -124,7 +123,7 @@ func (uts *TrackerServer) cleanConnectionID(interval time.Duration) {
}
// Run starts the tracker server.
func (uts *TrackerServer) Run() {
func (uts *Server) Run() {
go uts.cleanConnectionID(time.Minute * 2)
for {
buf := uts.bufpool.Get().([]byte)
@ -141,12 +140,12 @@ func (uts *TrackerServer) Run() {
}
}
func (uts *TrackerServer) handleRequest(raddr *net.UDPAddr, buf []byte, n int) {
func (uts *Server) handleRequest(raddr *net.UDPAddr, buf []byte, n int) {
defer uts.bufpool.Put(buf)
uts.handlePacket(raddr, buf[:n])
}
func (uts *TrackerServer) send(raddr *net.UDPAddr, b []byte) {
func (uts *Server) send(raddr *net.UDPAddr, b []byte) {
n, err := uts.conn.WriteTo(b, raddr)
if err != nil {
uts.conf.ErrorLog("fail to send the udp tracker response to '%s': %s",
@ -156,18 +155,18 @@ func (uts *TrackerServer) send(raddr *net.UDPAddr, b []byte) {
}
}
func (uts *TrackerServer) getConnectionID() uint64 {
func (uts *Server) getConnectionID() uint64 {
return atomic.AddUint64(&uts.cid, 1)
}
func (uts *TrackerServer) addConnection(cid uint64, raddr *net.UDPAddr) {
func (uts *Server) addConnection(cid uint64, raddr *net.UDPAddr) {
now := time.Now()
uts.lock.Lock()
uts.conns[cid] = wrappedPeerAddr{Addr: raddr, Time: now}
uts.lock.Unlock()
}
func (uts *TrackerServer) checkConnection(cid uint64, raddr *net.UDPAddr) (ok bool) {
func (uts *Server) checkConnection(cid uint64, raddr *net.UDPAddr) (ok bool) {
uts.lock.RLock()
if w, _ok := uts.conns[cid]; _ok && w.Addr.Port == raddr.Port &&
bytes.Equal(w.Addr.IP, raddr.IP) {
@ -177,21 +176,21 @@ func (uts *TrackerServer) checkConnection(cid uint64, raddr *net.UDPAddr) (ok bo
return
}
func (uts *TrackerServer) sendError(raddr *net.UDPAddr, tid uint32, reason string) {
func (uts *Server) sendError(raddr *net.UDPAddr, tid uint32, reason string) {
buf := bytes.NewBuffer(make([]byte, 0, 8+len(reason)))
encodeResponseHeader(buf, ActionError, tid)
buf.WriteString(reason)
uts.send(raddr, buf.Bytes())
}
func (uts *TrackerServer) sendConnResp(raddr *net.UDPAddr, tid uint32, cid uint64) {
func (uts *Server) sendConnResp(raddr *net.UDPAddr, tid uint32, cid uint64) {
buf := bytes.NewBuffer(make([]byte, 0, 16))
encodeResponseHeader(buf, ActionConnect, tid)
binary.Write(buf, binary.BigEndian, cid)
uts.send(raddr, buf.Bytes())
}
func (uts *TrackerServer) sendAnnounceResp(raddr *net.UDPAddr, tid uint32,
func (uts *Server) sendAnnounceResp(raddr *net.UDPAddr, tid uint32,
resp AnnounceResponse) {
buf := bytes.NewBuffer(make([]byte, 0, 8+12+len(resp.Addresses)*18))
encodeResponseHeader(buf, ActionAnnounce, tid)
@ -199,7 +198,7 @@ func (uts *TrackerServer) sendAnnounceResp(raddr *net.UDPAddr, tid uint32,
uts.send(raddr, buf.Bytes())
}
func (uts *TrackerServer) sendScrapResp(raddr *net.UDPAddr, tid uint32,
func (uts *Server) sendScrapResp(raddr *net.UDPAddr, tid uint32,
rs []ScrapeResponse) {
buf := bytes.NewBuffer(make([]byte, 0, 8+len(rs)*12))
encodeResponseHeader(buf, ActionScrape, tid)
@ -209,7 +208,7 @@ func (uts *TrackerServer) sendScrapResp(raddr *net.UDPAddr, tid uint32,
uts.send(raddr, buf.Bytes())
}
func (uts *TrackerServer) handlePacket(raddr *net.UDPAddr, b []byte) {
func (uts *Server) handlePacket(raddr *net.UDPAddr, b []byte) {
cid := binary.BigEndian.Uint64(b[:8])
action := binary.BigEndian.Uint32(b[8:12])
tid := binary.BigEndian.Uint32(b[12:16])

View File

@ -15,6 +15,7 @@
package udptracker
import (
"context"
"errors"
"fmt"
"log"
@ -66,13 +67,13 @@ func (testHandler) OnScrap(raddr *net.UDPAddr, infohashes []metainfo.Hash) (
return
}
func ExampleTrackerClient() {
func ExampleClient() {
// Start the UDP tracker server
sconn, err := net.ListenPacket("udp4", "127.0.0.1:8001")
if err != nil {
log.Fatal(err)
}
server := NewTrackerServer(sconn, testHandler{})
server := NewServer(sconn, testHandler{})
defer server.Close()
go server.Run()
@ -80,7 +81,7 @@ func ExampleTrackerClient() {
time.Sleep(time.Second)
// Create a client and dial to the UDP tracker server.
client, err := NewTrackerClientByDial("udp4", "127.0.0.1:8001")
client, err := NewClientByDial("udp4", "127.0.0.1:8001")
if err != nil {
log.Fatal(err)
}
@ -89,7 +90,7 @@ func ExampleTrackerClient() {
// and get the ANNOUNCE response.
exts := []Extension{NewURLData([]byte("data")), NewNop()}
req := AnnounceRequest{IP: net.ParseIP("127.0.0.1"), Port: 80, Exts: exts}
resp, err := client.Announce(req)
resp, err := client.Announce(context.Background(), req)
if err != nil {
log.Fatal(err)
}
@ -105,7 +106,7 @@ func ExampleTrackerClient() {
// Send the SCRAPE request to the UDP tracker server,
// and get the SCRAPE respsone.
hs := []metainfo.Hash{metainfo.NewRandomHash(), metainfo.NewRandomHash()}
rs, err := client.Scrape(hs)
rs, err := client.Scrape(context.Background(), hs)
if err != nil {
log.Fatal(err)
} else if len(rs) != 2 {