From 98d5a19d503894b1743b4be6f578a8c2e49f4561 Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Mon, 5 Dec 2022 17:53:36 +1100 Subject: [PATCH] Support marshalling http tracker response peers --- tracker/http/http.go | 4 ++-- tracker/http/http_test.go | 14 +++++++------- tracker/http/peer.go | 6 +++--- tracker/http/protocol.go | 33 +++++++++++++++++++++++++++++---- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/tracker/http/http.go b/tracker/http/http.go index 9aa53797..a7022a5f 100644 --- a/tracker/http/http.go +++ b/tracker/http/http.go @@ -133,10 +133,10 @@ func (cl Client) Announce(ctx context.Context, ar AnnounceRequest, opt AnnounceO 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 329aed72..7fd98a5d 100644 --- a/tracker/http/http_test.go +++ b/tracker/http/http_test.go @@ -22,12 +22,12 @@ func TestUnmarshalHTTPResponsePeerDicts(t *testing.T) { "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 @@ func TestUnmarshalHttpResponseNoPeers(t *testing.T) { []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 076a88c6..363ba6d3 100644 --- a/tracker/http/peer.go +++ b/tracker/http/peer.go @@ -8,9 +8,9 @@ import ( ) 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 5ce9fa90..11a90b2a 100644 --- a/tracker/http/protocol.go +++ b/tracker/http/protocol.go @@ -19,7 +19,30 @@ type HttpResponse struct { 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 @@ func (me *Peers) UnmarshalBencode(b []byte) (err error) { 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: -- 2.48.1