return netip.ParseAddrPort(pra.String())
}
}
+
+func krpcNodeAddrFromAddrPort(addrPort netip.AddrPort) krpc.NodeAddr {
+ return krpc.NodeAddr{
+ IP: addrPort.Addr().AsSlice(),
+ Port: int(addrPort.Port()),
+ }
+}
return netip.AddrPortFrom(addrPort.Addr(), uint16(c.PeerListenPort))
}
-func (c *PeerConn) pexEvent(t pexEventType) pexEvent {
+func (c *PeerConn) pexEvent(t pexEventType) (_ pexEvent, err error) {
f := c.pexPeerFlags()
- addr := c.dialAddr()
- return pexEvent{t, addr, f, nil}
+ dialAddr := c.dialAddr()
+ addr, err := addrPortFromPeerRemoteAddr(dialAddr)
+ if err != nil || !addr.IsValid() {
+ err = fmt.Errorf("parsing dial addr %q: %w", dialAddr, err)
+ return
+ }
+ return pexEvent{t, addr, f, nil}, nil
}
func (c *PeerConn) String() string {
}
func TestConnPexEvent(t *testing.T) {
+ c := qt.New(t)
var (
udpAddr = &net.UDPAddr{IP: net.IPv6loopback, Port: 4848}
tcpAddr = &net.TCPAddr{IP: net.IPv6loopback, Port: 4848}
{
pexAdd,
&PeerConn{Peer: Peer{RemoteAddr: udpAddr, Network: udpAddr.Network()}},
- pexEvent{pexAdd, udpAddr, pp.PexSupportsUtp, nil},
+ pexEvent{pexAdd, udpAddr.AddrPort(), pp.PexSupportsUtp, nil},
},
{
pexDrop,
- &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, Network: tcpAddr.Network(), outgoing: true}, PeerListenPort: dialTcpAddr.Port},
- pexEvent{pexDrop, tcpAddr, pp.PexOutgoingConn, nil},
+ &PeerConn{
+ Peer: Peer{RemoteAddr: tcpAddr, Network: tcpAddr.Network(), outgoing: true},
+ PeerListenPort: dialTcpAddr.Port,
+ },
+ pexEvent{pexDrop, tcpAddr.AddrPort(), pp.PexOutgoingConn, nil},
},
{
pexAdd,
- &PeerConn{Peer: Peer{RemoteAddr: tcpAddr, Network: tcpAddr.Network()}, PeerListenPort: dialTcpAddr.Port},
- pexEvent{pexAdd, dialTcpAddr, 0, nil},
+ &PeerConn{
+ Peer: Peer{RemoteAddr: tcpAddr, Network: tcpAddr.Network()},
+ PeerListenPort: dialTcpAddr.Port,
+ },
+ pexEvent{pexAdd, dialTcpAddr.AddrPort(), 0, nil},
},
{
pexDrop,
- &PeerConn{Peer: Peer{RemoteAddr: udpAddr, Network: udpAddr.Network()}, PeerListenPort: dialUdpAddr.Port},
- pexEvent{pexDrop, dialUdpAddr, pp.PexSupportsUtp, nil},
+ &PeerConn{
+ Peer: Peer{RemoteAddr: udpAddr, Network: udpAddr.Network()},
+ PeerListenPort: dialUdpAddr.Port,
+ },
+ pexEvent{pexDrop, dialUdpAddr.AddrPort(), pp.PexSupportsUtp, nil},
},
}
for i, tc := range testcases {
- e := tc.c.pexEvent(tc.t)
- require.EqualValues(t, tc.e, e, i)
+ c.Run(fmt.Sprintf("%v", i), func(c *qt.C) {
+ e, err := tc.c.pexEvent(tc.t)
+ c.Assert(err, qt.IsNil)
+ c.Check(e, qt.Equals, tc.e)
+ })
}
}
import (
"net"
+ "net/netip"
"sync"
- "github.com/anacrolix/dht/v2/krpc"
-
pp "github.com/anacrolix/torrent/peer_protocol"
)
// represents a single connection (t=pexAdd) or disconnection (t=pexDrop) event
type pexEvent struct {
t pexEventType
- addr PeerRemoteAddr
+ addr netip.AddrPort
f pp.PexPeerFlags
next *pexEvent // event feed list
}
// facilitates efficient de-duplication while generating PEX messages
type pexMsgFactory struct {
msg pp.PexMsg
- added map[addrKey]struct{}
- dropped map[addrKey]struct{}
+ added map[netip.AddrPort]struct{}
+ dropped map[netip.AddrPort]struct{}
}
func (me *pexMsgFactory) DeltaLen() int {
int64(len(me.dropped))))
}
-type addrKey string
+type addrKey = netip.AddrPort
// Returns the key to use to identify a given addr in the factory.
-func (me *pexMsgFactory) addrKey(addr PeerRemoteAddr) addrKey {
- return addrKey(addr.String())
+func (me *pexMsgFactory) addrKey(addr netip.AddrPort) addrKey {
+ return addr
}
// Returns whether the entry was added (we can check if we're cancelling out another entry and so
if me.added == nil {
me.added = make(map[addrKey]struct{}, pexMaxDelta)
}
- addr, ok := nodeAddr(e.addr)
- if !ok {
- return
- }
+ addr := krpcNodeAddrFromAddrPort(e.addr)
m := &me.msg
switch {
case addr.IP.To4() != nil:
// Returns whether the entry was added (we can check if we're cancelling out another entry and so
// won't hit the limit consuming this event).
func (me *pexMsgFactory) drop(e pexEvent) {
- addr, ok := nodeAddr(e.addr)
- if !ok {
- return
- }
+ addr := krpcNodeAddrFromAddrPort(e.addr)
key := me.addrKey(e.addr)
if me.dropped == nil {
me.dropped = make(map[addrKey]struct{}, pexMaxDelta)
return &me.msg
}
-// Convert an arbitrary torrent peer Addr into one that can be represented by the compact addr
-// format.
-func nodeAddr(addr PeerRemoteAddr) (krpc.NodeAddr, bool) {
- ipport, _ := tryIpPortFromNetAddr(addr)
- ok := ipport.IP != nil
- return krpc.NodeAddr{IP: ipport.IP, Port: ipport.Port}, ok
-}
-
// Per-torrent PEX state
type pexState struct {
sync.RWMutex
}
func (s *pexState) Add(c *PeerConn) {
+ e, err := c.pexEvent(pexAdd)
+ if err != nil {
+ return
+ }
s.Lock()
defer s.Unlock()
s.nc++
}
s.hold = s.hold[:0]
}
- e := c.pexEvent(pexAdd)
c.pex.Listed = true
s.append(&e)
}
// skip connections which were not previously Added
return
}
+ e, err := c.pexEvent(pexDrop)
+ if err != nil {
+ return
+ }
s.Lock()
defer s.Unlock()
- e := c.pexEvent(pexDrop)
s.nc--
if s.nc < pexTargAdded && len(s.hold) < pexMaxHold {
s.hold = append(s.hold, e)
require.EqualValues(t, targ, s)
}
-func mustNodeAddr(addr net.Addr) krpc.NodeAddr {
- ret, ok := nodeAddr(addr)
- if !ok {
- panic(addr)
+func krpcNodeAddrFromNetAddr(addr net.Addr) krpc.NodeAddr {
+ addrPort, err := addrPortFromPeerRemoteAddr(addr)
+ if err != nil {
+ panic(err)
}
- return ret
+ return krpcNodeAddrFromAddrPort(addrPort)
}
var testcases = []struct {
}(),
targ: pp.PexMsg{
Added: krpc.CompactIPv4NodeAddrs{
- mustNodeAddr(addrs[2]),
- mustNodeAddr(addrs[3]),
+ krpcNodeAddrFromNetAddr(addrs[2]),
+ krpcNodeAddrFromNetAddr(addrs[3]),
},
AddedFlags: []pp.PexPeerFlags{pp.PexOutgoingConn, 0},
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[0]),
- mustNodeAddr(addrs[1]),
+ krpcNodeAddrFromNetAddr(addrs[0]),
+ krpcNodeAddrFromNetAddr(addrs[1]),
},
Added6Flags: []pp.PexPeerFlags{0, pp.PexOutgoingConn},
},
}(),
targ: pp.PexMsg{
Dropped: krpc.CompactIPv4NodeAddrs{
- mustNodeAddr(addrs[2]),
+ krpcNodeAddrFromNetAddr(addrs[2]),
},
Dropped6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[0]),
+ krpcNodeAddrFromNetAddr(addrs[0]),
},
},
},
}(),
targ: pp.PexMsg{
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[1]),
+ krpcNodeAddrFromNetAddr(addrs[1]),
},
Added6Flags: []pp.PexPeerFlags{0},
},
}(),
targ: pp.PexMsg{
Added: krpc.CompactIPv4NodeAddrs{
- mustNodeAddr(addrs[2]),
+ krpcNodeAddrFromNetAddr(addrs[2]),
},
AddedFlags: []pp.PexPeerFlags{0},
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[0]),
- mustNodeAddr(addrs[1]),
+ krpcNodeAddrFromNetAddr(addrs[0]),
+ krpcNodeAddrFromNetAddr(addrs[1]),
},
Added6Flags: []pp.PexPeerFlags{0, 0},
},
}(),
targ: pp.PexMsg{
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[1]),
+ krpcNodeAddrFromNetAddr(addrs[1]),
},
Added6Flags: []pp.PexPeerFlags{0},
},
}(),
targ: pp.PexMsg{
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[0]),
+ krpcNodeAddrFromNetAddr(addrs[0]),
},
Added6Flags: []pp.PexPeerFlags{0},
},
},
targ1: pp.PexMsg{
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addrs[1]),
+ krpcNodeAddrFromNetAddr(addrs[1]),
},
Added6Flags: []pp.PexPeerFlags{0},
},
Added: krpc.CompactIPv4NodeAddrs(nil),
AddedFlags: []pp.PexPeerFlags{},
Added6: krpc.CompactIPv6NodeAddrs{
- mustNodeAddr(addr),
+ krpcNodeAddrFromNetAddr(addr),
},
Added6Flags: []pp.PexPeerFlags{0},
}