-package util
-
-import (
- "encoding"
- "encoding/binary"
- "errors"
- "fmt"
- "net"
-
- "github.com/bradfitz/iter"
-
- "github.com/anacrolix/torrent/bencode"
-)
-
-// Concatenated 6-byte peer addresses.
-type CompactIPv4Peers []CompactPeer
-
-var (
- // This allows bencode.Unmarshal to do better than a string or []byte.
- _ bencode.Unmarshaler = &CompactIPv4Peers{}
- _ encoding.BinaryMarshaler = CompactIPv4Peers{}
-)
-
-// This allows bencode.Unmarshal to do better than a string or []byte.
-func (cps *CompactIPv4Peers) UnmarshalBencode(b []byte) (err error) {
- var bb []byte
- err = bencode.Unmarshal(b, &bb)
- if err != nil {
- return
- }
- *cps, err = UnmarshalIPv4CompactPeers(bb)
- return
-}
-
-func (cps CompactIPv4Peers) MarshalBinary() (ret []byte, err error) {
- ret = make([]byte, len(cps)*6)
- for i, cp := range cps {
- copy(ret[6*i:], cp.IP.To4())
- binary.BigEndian.PutUint16(ret[6*i+4:], uint16(cp.Port))
- }
- return
-}
-
-// Represents peer address in either IPv6 or IPv4 form.
-type CompactPeer struct {
- IP net.IP
- Port int
-}
-
-var (
- _ bencode.Marshaler = &CompactPeer{}
- _ bencode.Unmarshaler = &CompactPeer{}
-)
-
-func (cp CompactPeer) MarshalBencode() (ret []byte, err error) {
- ip := cp.IP
- if ip4 := ip.To4(); ip4 != nil {
- ip = ip4
- }
- ret = make([]byte, len(ip)+2)
- copy(ret, ip)
- binary.BigEndian.PutUint16(ret[len(ip):], uint16(cp.Port))
- return bencode.Marshal(ret)
-}
-
-func (cp *CompactPeer) UnmarshalBinary(b []byte) error {
- switch len(b) {
- case 18:
- cp.IP = make([]byte, 16)
- case 6:
- cp.IP = make([]byte, 4)
- default:
- return fmt.Errorf("bad compact peer string: %q", b)
- }
- copy(cp.IP, b)
- b = b[len(cp.IP):]
- cp.Port = int(binary.BigEndian.Uint16(b))
- return nil
-}
-
-func (cp *CompactPeer) UnmarshalBencode(b []byte) (err error) {
- var _b []byte
- err = bencode.Unmarshal(b, &_b)
- if err != nil {
- return
- }
- return cp.UnmarshalBinary(_b)
-}
-
-func UnmarshalIPv4CompactPeers(b []byte) (ret []CompactPeer, err error) {
- if len(b)%6 != 0 {
- err = errors.New("bad length")
- return
- }
- num := len(b) / 6
- ret = make([]CompactPeer, num)
- for i := range iter.N(num) {
- off := i * 6
- err = ret[i].UnmarshalBinary(b[off : off+6])
- if err != nil {
- return
- }
- }
- return
-}