]> Sergey Matveev's repositories - btrtrc.git/blob - tracker/http/protocol.go
Support marshalling http tracker response peers
[btrtrc.git] / tracker / http / protocol.go
1 package httpTracker
2
3 import (
4         "fmt"
5
6         "github.com/anacrolix/dht/v2/krpc"
7
8         "github.com/anacrolix/torrent/bencode"
9 )
10
11 type HttpResponse struct {
12         FailureReason string `bencode:"failure reason"`
13         Interval      int32  `bencode:"interval"`
14         TrackerId     string `bencode:"tracker id"`
15         Complete      int32  `bencode:"complete"`
16         Incomplete    int32  `bencode:"incomplete"`
17         Peers         Peers  `bencode:"peers"`
18         // BEP 7
19         Peers6 krpc.CompactIPv6NodeAddrs `bencode:"peers6"`
20 }
21
22 type Peers struct {
23         List    []Peer
24         Compact bool
25 }
26
27 func (me Peers) MarshalBencode() ([]byte, error) {
28         if me.Compact {
29                 cnas := make([]krpc.NodeAddr, 0, len(me.List))
30                 for _, peer := range me.List {
31                         cnas = append(cnas, krpc.NodeAddr{
32                                 IP:   peer.IP,
33                                 Port: peer.Port,
34                         })
35                 }
36                 return krpc.CompactIPv4NodeAddrs(cnas).MarshalBencode()
37         } else {
38                 return bencode.Marshal(me.List)
39         }
40 }
41
42 var (
43         _ bencode.Unmarshaler = (*Peers)(nil)
44         _ bencode.Marshaler   = Peers{}
45 )
46
47 func (me *Peers) UnmarshalBencode(b []byte) (err error) {
48         var _v interface{}
49         err = bencode.Unmarshal(b, &_v)
50         if err != nil {
51                 return
52         }
53         switch v := _v.(type) {
54         case string:
55                 vars.Add("http responses with string peers", 1)
56                 var cnas krpc.CompactIPv4NodeAddrs
57                 err = cnas.UnmarshalBinary([]byte(v))
58                 if err != nil {
59                         return
60                 }
61                 me.Compact = true
62                 for _, cp := range cnas {
63                         me.List = append(me.List, Peer{
64                                 IP:   cp.IP[:],
65                                 Port: cp.Port,
66                         })
67                 }
68                 return
69         case []interface{}:
70                 vars.Add("http responses with list peers", 1)
71                 me.Compact = false
72                 for _, i := range v {
73                         var p Peer
74                         p.FromDictInterface(i.(map[string]interface{}))
75                         me.List = append(me.List, p)
76                 }
77                 return
78         default:
79                 vars.Add("http responses with unhandled peers type", 1)
80                 err = fmt.Errorf("unsupported type: %T", _v)
81                 return
82         }
83 }