package tracker import ( "bytes" "encoding/binary" "fmt" "io/ioutil" "log" "net" "net/http" "dim13.org/btget/bencode" "dim13.org/btget/query" ) type Event string const ( NoEvent Event = "" Started Event = "started" Stopped Event = "stopped" Completed Event = "completed" ) type Request struct { InfoHash []byte `query:"info_hash"` // info_hash PeerID []byte `query:"peer_id"` // peer_id Port int `query:"port,optional"` Uploaded int `query:"uploaded,optional"` Downloaded int `query:"downloaded,optional"` Left int `query:"left,optional"` Compact bool `query:"compact,optional"` // always true NoPeerID bool `query:"no_peer_id,optional"` Event Event `query:"event,optional"` IP net.IPAddr `query:"ip,optional"` NumWant int `query:"numwant,optional"` Key []byte `query:"key,optional"` TrackerID []byte `query:"tracker_id,optional"` } // we support only compact mode type Response struct { Complete int `bencode:"complete"` FalureReason string `bencode:"failure reason"` Incomplete int `bencode:"incomplete"` Interval int `bencode:"interval"` MinInterval int `bencode:"min interval"` Peers []byte `bencode:"peers"` Peers6 []byte `bencode:"peers6"` TrackerId string `bencode:"tracker id"` WarningMessage string `bencode:"warning message"` } func (r Request) Get(announce string) (Response, error) { fail := func(err error) (Response, error) { return Response{}, err } q, err := query.Marshal(r) if err != nil { return fail(err) } log.Println(announce + q) resp, err := http.Get(announce + q) if err != nil { return fail(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return fail(err) } log.Println(string(body)) var res Response err = bencode.Unmarshal(body, &res) if err != nil { return fail(err) } return res, nil } func ParseAddr(b []byte) ([]string, error) { n := len(b) / 6 s := make([]string, n) var port uint16 for i := 0; i < n; i++ { off := i * 6 buf := bytes.NewReader(b[off+4 : off+6]) err := binary.Read(buf, binary.BigEndian, &port) if err != nil { return nil, err } s[i] = fmt.Sprintf("%s:%d", net.IP(b[off:off+4]), port) } return s, nil }