tracker/http/http.go | 4 ++-- tracker/http/http_test.go | 14 +++++++------- tracker/http/peer.go | 6 +++--- tracker/http/protocol.go | 33 +++++++++++++++++++++++++++++---- diff --git a/tracker/http/http.go b/tracker/http/http.go index 9aa53797c390e9d96077e840278e9608e6b2c5bf..a7022a5f01737dbcbc54d595d753bedc1069e6ce 100644 --- a/tracker/http/http.go +++ b/tracker/http/http.go @@ -133,10 +133,10 @@ vars.Add("successful http announces", 1) ret.Interval = trackerResponse.Interval ret.Leechers = trackerResponse.Incomplete ret.Seeders = trackerResponse.Complete - if len(trackerResponse.Peers) != 0 { + if len(trackerResponse.Peers.List) != 0 { vars.Add("http responses with nonempty peers key", 1) } - ret.Peers = trackerResponse.Peers + ret.Peers = trackerResponse.Peers.List if len(trackerResponse.Peers6) != 0 { vars.Add("http responses with nonempty peers6 key", 1) } diff --git a/tracker/http/http_test.go b/tracker/http/http_test.go index 329aed72b1a939930e3e9fd2f25bf1d1ec997107..7fd98a5d1bda74666c2d4b44c2d5954f1da7fe6e 100644 --- a/tracker/http/http_test.go +++ b/tracker/http/http_test.go @@ -22,12 +22,12 @@ "6:peers618:123412341234123456"+ "e"), &hr)) - require.Len(t, hr.Peers, 2) - assert.Equal(t, []byte("thisisthe20bytepeeri"), hr.Peers[0].ID) - assert.EqualValues(t, 9999, hr.Peers[0].Port) - assert.EqualValues(t, 9998, hr.Peers[1].Port) - assert.NotNil(t, hr.Peers[0].IP) - assert.NotNil(t, hr.Peers[1].IP) + require.Len(t, hr.Peers.List, 2) + assert.Equal(t, []byte("thisisthe20bytepeeri"), hr.Peers.List[0].ID) + assert.EqualValues(t, 9999, hr.Peers.List[0].Port) + assert.EqualValues(t, 9998, hr.Peers.List[1].Port) + assert.NotNil(t, hr.Peers.List[0].IP) + assert.NotNil(t, hr.Peers.List[1].IP) assert.Len(t, hr.Peers6, 1) assert.EqualValues(t, "1234123412341234", hr.Peers6[0].IP) @@ -40,7 +40,7 @@ require.NoError(t, bencode.Unmarshal( []byte("d6:peers618:123412341234123456e"), &hr, )) - require.Len(t, hr.Peers, 0) + require.Len(t, hr.Peers.List, 0) assert.Len(t, hr.Peers6, 1) } diff --git a/tracker/http/peer.go b/tracker/http/peer.go index 076a88c6801939fee81475572ed9240c7e61b8b6..363ba6d3c7b9f7d317b0f2785a3e5338c16df49e 100644 --- a/tracker/http/peer.go +++ b/tracker/http/peer.go @@ -8,9 +8,9 @@ "github.com/anacrolix/dht/v2/krpc" ) type Peer struct { - IP net.IP - Port int - ID []byte + IP net.IP `bencode:"ip"` + Port int `bencode:"port"` + ID []byte `bencode:"peer id"` } func (p Peer) String() string { diff --git a/tracker/http/protocol.go b/tracker/http/protocol.go index 5ce9fa90cf2d32beea36ee1a18afca5ea1b75f29..11a90b2a315a150cddcb3340be48ee99d2883916 100644 --- a/tracker/http/protocol.go +++ b/tracker/http/protocol.go @@ -19,7 +19,30 @@ // BEP 7 Peers6 krpc.CompactIPv6NodeAddrs `bencode:"peers6"` } -type Peers []Peer +type Peers struct { + List []Peer + Compact bool +} + +func (me Peers) MarshalBencode() ([]byte, error) { + if me.Compact { + cnas := make([]krpc.NodeAddr, 0, len(me.List)) + for _, peer := range me.List { + cnas = append(cnas, krpc.NodeAddr{ + IP: peer.IP, + Port: peer.Port, + }) + } + return krpc.CompactIPv4NodeAddrs(cnas).MarshalBencode() + } else { + return bencode.Marshal(me.List) + } +} + +var ( + _ bencode.Unmarshaler = (*Peers)(nil) + _ bencode.Marshaler = Peers{} +) func (me *Peers) UnmarshalBencode(b []byte) (err error) { var _v interface{} @@ -35,19 +58,21 @@ err = cnas.UnmarshalBinary([]byte(v)) if err != nil { return } + me.Compact = true for _, cp := range cnas { - *me = append(*me, Peer{ + me.List = append(me.List, Peer{ IP: cp.IP[:], - Port: int(cp.Port), + Port: cp.Port, }) } return case []interface{}: vars.Add("http responses with list peers", 1) + me.Compact = false for _, i := range v { var p Peer p.FromDictInterface(i.(map[string]interface{})) - *me = append(*me, p) + me.List = append(me.List, p) } return default: