github.com/anacrolix/torrent@v1.61.0/tracker/http/protocol.go (about)

     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  }