]> Sergey Matveev's repositories - btrtrc.git/blob - cmd/tracker-announce/main.go
e038d872b9ca09b661c9ff2fe1d85042cd9486fa
[btrtrc.git] / cmd / tracker-announce / main.go
1 package main
2
3 import (
4         "log"
5         "math"
6         "net/url"
7         "strings"
8         "sync"
9
10         "github.com/anacrolix/tagflag"
11         "github.com/davecgh/go-spew/spew"
12
13         "github.com/anacrolix/torrent"
14         "github.com/anacrolix/torrent/metainfo"
15         "github.com/anacrolix/torrent/tracker"
16 )
17
18 func argSpec(arg string) (ts *torrent.TorrentSpec, err error) {
19         if strings.HasPrefix(arg, "magnet:") {
20                 return torrent.TorrentSpecFromMagnetURI(arg)
21         }
22         mi, err := metainfo.LoadFromFile(arg)
23         if err != nil {
24                 return
25         }
26         ts = torrent.TorrentSpecFromMetaInfo(mi)
27         return
28 }
29
30 func main() {
31         flags := struct {
32                 Port uint16
33                 tagflag.StartPos
34                 Torrents []string `arity:"+"`
35         }{
36                 Port: 50007,
37         }
38         tagflag.Parse(&flags)
39         ar := tracker.AnnounceRequest{
40                 NumWant: -1,
41                 Left:    math.MaxUint64,
42                 Port:    flags.Port,
43         }
44         var wg sync.WaitGroup
45         for _, arg := range flags.Torrents {
46                 ts, err := argSpec(arg)
47                 if err != nil {
48                         log.Fatal(err)
49                 }
50                 ar.InfoHash = ts.InfoHash
51                 for _, tier := range ts.Trackers {
52                         for _, tURI := range tier {
53                                 wg.Add(1)
54                                 go doTracker(tURI, wg.Done, ar)
55                         }
56                 }
57         }
58         wg.Wait()
59 }
60
61 func doTracker(tURI string, done func(), ar tracker.AnnounceRequest) {
62         defer done()
63         for _, res := range announces(tURI, ar) {
64                 err := res.error
65                 resp := res.AnnounceResponse
66                 if err != nil {
67                         log.Printf("error announcing to %q: %s", tURI, err)
68                         continue
69                 }
70                 log.Printf("tracker response from %q: %s", tURI, spew.Sdump(resp))
71         }
72 }
73
74 type announceResult struct {
75         tracker.AnnounceResponse
76         error
77 }
78
79 func announces(uri string, ar tracker.AnnounceRequest) (ret []announceResult) {
80         u, err := url.Parse(uri)
81         if err != nil {
82                 return []announceResult{{error: err}}
83         }
84         a := tracker.Announce{
85                 Request:    ar,
86                 TrackerUrl: uri,
87         }
88         if u.Scheme == "udp" {
89                 a.UdpNetwork = "udp4"
90                 ret = append(ret, announce(a))
91                 a.UdpNetwork = "udp6"
92                 ret = append(ret, announce(a))
93                 return
94         }
95         return []announceResult{announce(a)}
96 }
97
98 func announce(a tracker.Announce) announceResult {
99         resp, err := a.Do()
100         return announceResult{resp, err}
101 }