p2p: change metered connection ip and node id

This commit is contained in:
Kurkó Mihály 2019-02-06 15:36:38 +02:00
parent 514a9472ad
commit 20a4756f73
3 changed files with 29 additions and 31 deletions

View file

@ -350,7 +350,7 @@ func (t *dialTask) dial(srv *Server, dest *enode.Node) error {
if err != nil { if err != nil {
return &dialError{err} return &dialError{err}
} }
mfd := newMeteredConn(fd, false, dest.IP()) mfd := newMeteredConn(fd, false, &net.TCPAddr{IP: dest.IP(), Port: dest.TCP()})
return srv.SetupConn(mfd, t.flags, dest) return srv.SetupConn(mfd, t.flags, dest)
} }

View file

@ -19,7 +19,6 @@
package p2p package p2p
import ( import (
"fmt"
"net" "net"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -73,8 +72,8 @@ const (
// MeteredPeerEvent is an event emitted when peers connect or disconnect. // MeteredPeerEvent is an event emitted when peers connect or disconnect.
type MeteredPeerEvent struct { type MeteredPeerEvent struct {
Type MeteredPeerEventType // Type of peer event Type MeteredPeerEventType // Type of peer event
IP net.IP // IP address of the peer Addr string // TCP address of the peer
ID enode.ID // NodeID of the peer Node string // Host
Elapsed time.Duration // Time elapsed between the connection and the handshake/disconnection Elapsed time.Duration // Time elapsed between the connection and the handshake/disconnection
Ingress uint64 // Ingress count at the moment of the event Ingress uint64 // Ingress count at the moment of the event
Egress uint64 // Egress count at the moment of the event Egress uint64 // Egress count at the moment of the event
@ -92,8 +91,8 @@ type meteredConn struct {
net.Conn // Network connection to wrap with metering net.Conn // Network connection to wrap with metering
connected time.Time // Connection time of the peer connected time.Time // Connection time of the peer
ip net.IP // IP address of the peer addr *net.TCPAddr // TCP address of the peer
id enode.ID // NodeID of the peer node *enode.Node // Host
// trafficMetered denotes if the peer is registered in the traffic registries. // trafficMetered denotes if the peer is registered in the traffic registries.
// Its value is true if the metered peer count doesn't reach the limit in the // Its value is true if the metered peer count doesn't reach the limit in the
@ -109,13 +108,13 @@ type meteredConn struct {
// connection meter and also increases the metered peer count. If the metrics // connection meter and also increases the metered peer count. If the metrics
// system is disabled or the IP address is unspecified, this function returns // system is disabled or the IP address is unspecified, this function returns
// the original object. // the original object.
func newMeteredConn(conn net.Conn, ingress bool, ip net.IP) net.Conn { func newMeteredConn(conn net.Conn, ingress bool, addr *net.TCPAddr) net.Conn {
// Short circuit if metrics are disabled // Short circuit if metrics are disabled
if !metrics.Enabled { if !metrics.Enabled {
return conn return conn
} }
if ip.IsUnspecified() { if addr == nil || addr.IP.IsUnspecified() {
log.Warn("Peer IP is unspecified") log.Warn("Peer address is unspecified")
return conn return conn
} }
// Bump the connection counters and wrap the connection // Bump the connection counters and wrap the connection
@ -126,7 +125,7 @@ func newMeteredConn(conn net.Conn, ingress bool, ip net.IP) net.Conn {
} }
return &meteredConn{ return &meteredConn{
Conn: conn, Conn: conn,
ip: ip, addr: addr,
connected: time.Now(), connected: time.Now(),
} }
} }
@ -160,26 +159,26 @@ func (c *meteredConn) Write(b []byte) (n int, err error) {
// handshakeDone is called when a peer handshake is done. Registers the peer to // handshakeDone is called when a peer handshake is done. Registers the peer to
// the ingress and the egress traffic registries using the peer's IP and node ID, // the ingress and the egress traffic registries using the peer's IP and node ID,
// also emits connect event. // also emits connect event.
func (c *meteredConn) handshakeDone(id enode.ID) { func (c *meteredConn) handshakeDone(node *enode.Node) {
if atomic.AddInt32(&meteredPeerCount, 1) >= MeteredPeerLimit { if atomic.AddInt32(&meteredPeerCount, 1) >= MeteredPeerLimit {
// Don't register the peer in the traffic registries. // Don't register the peer in the traffic registries.
atomic.AddInt32(&meteredPeerCount, -1) atomic.AddInt32(&meteredPeerCount, -1)
c.lock.Lock() c.lock.Lock()
c.id, c.trafficMetered = id, false c.node, c.trafficMetered = node, false
c.lock.Unlock() c.lock.Unlock()
log.Warn("Metered peer count reached the limit") log.Warn("Metered peer count reached the limit")
} else { } else {
key := fmt.Sprintf("%s/%s", c.ip, id.String()) key := node.String()
c.lock.Lock() c.lock.Lock()
c.id, c.trafficMetered = id, true c.node, c.trafficMetered = node, true
c.ingressMeter = metrics.NewRegisteredMeter(key, PeerIngressRegistry) c.ingressMeter = metrics.NewRegisteredMeter(key, PeerIngressRegistry)
c.egressMeter = metrics.NewRegisteredMeter(key, PeerEgressRegistry) c.egressMeter = metrics.NewRegisteredMeter(key, PeerEgressRegistry)
c.lock.Unlock() c.lock.Unlock()
} }
meteredPeerFeed.Send(MeteredPeerEvent{ meteredPeerFeed.Send(MeteredPeerEvent{
Type: PeerConnected, Type: PeerConnected,
IP: c.ip, Addr: c.addr.String(),
ID: id, Node: node.String(),
Elapsed: time.Since(c.connected), Elapsed: time.Since(c.connected),
}) })
} }
@ -189,24 +188,24 @@ func (c *meteredConn) handshakeDone(id enode.ID) {
func (c *meteredConn) Close() error { func (c *meteredConn) Close() error {
err := c.Conn.Close() err := c.Conn.Close()
c.lock.RLock() c.lock.RLock()
if c.id == (enode.ID{}) { if c.node == nil {
// If the peer disconnects before the handshake. // If the peer disconnects before the handshake.
c.lock.RUnlock() c.lock.RUnlock()
meteredPeerFeed.Send(MeteredPeerEvent{ meteredPeerFeed.Send(MeteredPeerEvent{
Type: PeerHandshakeFailed, Type: PeerHandshakeFailed,
IP: c.ip, Addr: c.addr.String(),
Elapsed: time.Since(c.connected), Elapsed: time.Since(c.connected),
}) })
return err return err
} }
id := c.id node := c.node.String()
if !c.trafficMetered { if !c.trafficMetered {
// If the peer isn't registered in the traffic registries. // If the peer isn't registered in the traffic registries.
c.lock.RUnlock() c.lock.RUnlock()
meteredPeerFeed.Send(MeteredPeerEvent{ meteredPeerFeed.Send(MeteredPeerEvent{
Type: PeerDisconnected, Type: PeerDisconnected,
IP: c.ip, Addr: c.addr.String(),
ID: id, Node: node,
}) })
return err return err
} }
@ -217,14 +216,13 @@ func (c *meteredConn) Close() error {
atomic.AddInt32(&meteredPeerCount, -1) atomic.AddInt32(&meteredPeerCount, -1)
// Unregister the peer from the traffic registries // Unregister the peer from the traffic registries
key := fmt.Sprintf("%s/%s", c.ip, id) PeerIngressRegistry.Unregister(node)
PeerIngressRegistry.Unregister(key) PeerEgressRegistry.Unregister(node)
PeerEgressRegistry.Unregister(key)
meteredPeerFeed.Send(MeteredPeerEvent{ meteredPeerFeed.Send(MeteredPeerEvent{
Type: PeerDisconnected, Type: PeerDisconnected,
IP: c.ip, Addr: c.addr.String(),
ID: id, Node: node,
Ingress: ingress, Ingress: ingress,
Egress: egress, Egress: egress,
}) })

View file

@ -863,11 +863,11 @@ func (srv *Server) listenLoop() {
} }
} }
var ip net.IP var addr *net.TCPAddr
if tcp, ok := fd.RemoteAddr().(*net.TCPAddr); ok { if tcp, ok := fd.RemoteAddr().(*net.TCPAddr); ok {
ip = tcp.IP addr = tcp
} }
fd = newMeteredConn(fd, true, ip) fd = newMeteredConn(fd, true, addr)
srv.log.Trace("Accepted connection", "addr", fd.RemoteAddr()) srv.log.Trace("Accepted connection", "addr", fd.RemoteAddr())
go func() { go func() {
srv.SetupConn(fd, inboundConn, nil) srv.SetupConn(fd, inboundConn, nil)
@ -921,7 +921,7 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro
c.node = nodeFromConn(remotePubkey, c.fd) c.node = nodeFromConn(remotePubkey, c.fd)
} }
if conn, ok := c.fd.(*meteredConn); ok { if conn, ok := c.fd.(*meteredConn); ok {
conn.handshakeDone(c.node.ID()) conn.handshakeDone(c.node)
} }
clog := srv.log.New("id", c.node.ID(), "addr", c.fd.RemoteAddr(), "conn", c.flags) clog := srv.log.New("id", c.node.ID(), "addr", c.fd.RemoteAddr(), "conn", c.flags)
err = srv.checkpoint(c, srv.posthandshake) err = srv.checkpoint(c, srv.posthandshake)