Peers.go | 17 +++++++++++++++++ connection.go | 18 ++++-------------- pex.go | 12 +++++++++++- torrent.go | 13 +++++++++++++ diff --git a/Peers.go b/Peers.go new file mode 100644 index 0000000000000000000000000000000000000000..72f7e8e1b61abf1e4ef8c8df1cfc7becf4bdd711 --- /dev/null +++ b/Peers.go @@ -0,0 +1,17 @@ +package torrent + +import "github.com/anacrolix/dht/krpc" + +type Peers []Peer + +func (me *Peers) FromPex(nas []krpc.NodeAddr, fs []pexPeerFlags) { + for i, na := range nas { + var p Peer + var f pexPeerFlags + if i < len(fs) { + f = fs[i] + } + p.FromPex(na, f) + *me = append(*me, p) + } +} diff --git a/connection.go b/connection.go index 379b45f9668e84b74f176423294d01faf09de99b..4e919c5faecc468bbfe5c000bc0bfc2dedacc0d4 100644 --- a/connection.go +++ b/connection.go @@ -1142,6 +1142,8 @@ } return nil case pexExtendedId: if cl.config.DisablePEX { + // TODO: Maybe close the connection. Check that we're not + // advertising that we support PEX if it's disabled. return nil } var pexMsg peerExchangeMessage @@ -1150,21 +1152,9 @@ if err != nil { return fmt.Errorf("error unmarshalling PEX message: %s", err) } go func() { + ps := pexMsg.AddedPeers() cl.mu.Lock() - t.addPeers(func() (ret []Peer) { - for i, cp := range pexMsg.Added { - p := Peer{ - IP: append(make(net.IP, 0, 4), cp.IP...), - Port: cp.Port, - Source: peerSourcePEX, - } - if i < len(pexMsg.AddedFlags) && pexMsg.AddedFlags[i]&0x01 != 0 { - p.SupportsEncryption = true - } - ret = append(ret, p) - } - return - }()) + t.addPeers(ps) cl.mu.Unlock() }() return nil diff --git a/pex.go b/pex.go index b3e3e16660ea36d39c74c5e2e5aaf0ab0641cb60..7b28fe6f62950b35479c4156a561de2f01bf739b 100644 --- a/pex.go +++ b/pex.go @@ -6,12 +6,16 @@ type peerExchangeMessage struct { Added krpc.CompactIPv4NodeAddrs `bencode:"added"` AddedFlags []pexPeerFlags `bencode:"added.f"` Added6 krpc.CompactIPv6NodeAddrs `bencode:"added6"` - AddedFlags6 []pexPeerFlags `bencode:"added6.f"` + Added6Flags []pexPeerFlags `bencode:"added6.f"` Dropped krpc.CompactIPv4NodeAddrs `bencode:"dropped"` Dropped6 krpc.CompactIPv6NodeAddrs `bencode:"dropped6"` } type pexPeerFlags byte + +func (me pexPeerFlags) Get(f pexPeerFlags) bool { + return me&f == f +} const ( pexPrefersEncryption = 0x01 @@ -20,3 +24,9 @@ pexSupportsUtp = 0x04 pexHolepunchSupport = 0x08 pexOutgoingConn = 0x10 ) + +func (me *peerExchangeMessage) AddedPeers() (ret Peers) { + ret.FromPex(me.Added, me.AddedFlags) + ret.FromPex(me.Added6, me.Added6Flags) + return +} diff --git a/torrent.go b/torrent.go index f058a72f5d52510bc6e53e8ce6831ff2955f10bd..95e7aca1fe779b22deb258c432d6374b5d0c6186 100644 --- a/torrent.go +++ b/torrent.go @@ -16,6 +16,7 @@ "text/tabwriter" "time" "github.com/anacrolix/dht" + "github.com/anacrolix/dht/krpc" "github.com/anacrolix/log" "github.com/anacrolix/missinggo" "github.com/anacrolix/missinggo/bitmap" @@ -738,6 +739,18 @@ Port int Source peerSource // Peer is known to support encryption. SupportsEncryption bool + pexPeerFlags +} + +func (me *Peer) FromPex(na krpc.NodeAddr, fs pexPeerFlags) { + me.IP = append([]byte(nil), na.IP...) + me.Port = na.Port + me.Source = peerSourcePEX + // If they prefer encryption, they must support it. + if fs.Get(pexPrefersEncryption) { + me.SupportsEncryption = true + } + me.pexPeerFlags = fs } func (t *Torrent) pieceLength(piece int) pp.Integer {