]> Sergey Matveev's repositories - btrtrc.git/blob - tracker/tracker.go
tracker: Shoehorn old client implementations into new tracker Announce interface
[btrtrc.git] / tracker / tracker.go
1 package tracker
2
3 import (
4         "errors"
5         "net"
6         "net/url"
7 )
8
9 // Marshalled as binary by the UDP client, so be careful making changes.
10 type AnnounceRequest struct {
11         InfoHash   [20]byte
12         PeerId     [20]byte
13         Downloaded int64
14         Left       uint64
15         Uploaded   int64
16         Event      AnnounceEvent
17         IPAddress  int32
18         Key        int32
19         NumWant    int32 // How many peer addresses are desired. -1 for default.
20         Port       uint16
21 } // 82 bytes
22
23 type AnnounceResponse struct {
24         Interval int32 // Minimum seconds the local peer should wait before next announce.
25         Leechers int32
26         Seeders  int32
27         Peers    []Peer
28 }
29
30 type AnnounceEvent int32
31
32 func (me AnnounceEvent) String() string {
33         // See BEP 3, "event".
34         return []string{"empty", "completed", "started", "stopped"}[me]
35 }
36
37 type Peer struct {
38         IP   net.IP
39         Port int
40 }
41
42 const (
43         None      AnnounceEvent = iota
44         Completed               // The local peer just completed the torrent.
45         Started                 // The local peer has just resumed this torrent.
46         Stopped                 // The local peer is leaving the swarm.
47 )
48
49 type client interface {
50         // Returns ErrNotConnected if Connect needs to be called.
51         Announce(*AnnounceRequest) (AnnounceResponse, error)
52         Connect() error
53         String() string
54         URL() string
55         Close() error
56 }
57
58 var (
59         ErrNotConnected = errors.New("not connected")
60         ErrBadScheme    = errors.New("unknown scheme")
61
62         schemes = make(map[string]func(*url.URL) client)
63 )
64
65 func registerClientScheme(scheme string, newFunc func(*url.URL) client) {
66         schemes[scheme] = newFunc
67 }
68
69 // Returns ErrBadScheme if the tracker scheme isn't recognised.
70 func new(rawurl string) (cl client, err error) {
71         url_s, err := url.Parse(rawurl)
72         if err != nil {
73                 return
74         }
75         newFunc, ok := schemes[url_s.Scheme]
76         if !ok {
77                 err = ErrBadScheme
78                 return
79         }
80         cl = newFunc(url_s)
81         return
82 }
83
84 func Announce(urlStr string, req *AnnounceRequest) (res AnnounceResponse, err error) {
85         cl, err := new(urlStr)
86         if err != nil {
87                 return
88         }
89         defer cl.Close()
90         err = cl.Connect()
91         if err != nil {
92                 return
93         }
94         return cl.Announce(req)
95
96 }