Skip to content

Commit

Permalink
Handle the case where we want to call OpenConnection without an IP ad…
Browse files Browse the repository at this point in the history
…dress
  • Loading branch information
MarcoPolo committed May 13, 2024
1 parent 67a4ab6 commit ccdf0e1
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 7 deletions.
27 changes: 21 additions & 6 deletions p2p/host/resource-manager/rcmgr.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ func (r *resourceManager) nextStreamId() int64 {
return r.streamId
}

// OpenConnectionNoIP is like OpenConnection, but does not use IP information.
// Used when we still want to limit the connection by other scopes, but don't
// have IP information like when we are relaying.
func (r *resourceManager) OpenConnectionNoIP(dir network.Direction, usefd bool, endpoint multiaddr.Multiaddr) (network.ConnManagementScope, error) {
return r.openConnection(dir, usefd, endpoint, netip.Addr{})
}

func (r *resourceManager) OpenConnection(dir network.Direction, usefd bool, endpoint multiaddr.Multiaddr) (network.ConnManagementScope, error) {
ip, err := manet.ToIP(endpoint)
if err != nil {
Expand All @@ -326,15 +333,21 @@ func (r *resourceManager) OpenConnection(dir network.Direction, usefd bool, endp
if !ok {
return nil, fmt.Errorf("failed to convert ip to netip.Addr")
}
if ok := r.connLimiter.addConn(ipAddr); !ok {
return nil, fmt.Errorf("connections per ip limit exceeded for %s", endpoint)
return r.openConnection(dir, usefd, endpoint, ipAddr)
}

func (r *resourceManager) openConnection(dir network.Direction, usefd bool, endpoint multiaddr.Multiaddr, ip netip.Addr) (network.ConnManagementScope, error) {
if ip.IsValid() {
if ok := r.connLimiter.addConn(ip); !ok {
return nil, fmt.Errorf("connections per ip limit exceeded for %s", endpoint)
}
}

var conn *connectionScope
conn = newConnectionScope(dir, usefd, r.limits.GetConnLimits(), r, endpoint, ipAddr)
conn = newConnectionScope(dir, usefd, r.limits.GetConnLimits(), r, endpoint, ip)

err = conn.AddConn(dir, usefd)
if err != nil {
err := conn.AddConn(dir, usefd)
if err != nil && ip.IsValid() {
// Try again if this is an allowlisted connection
// Failed to open connection, let's see if this was allowlisted and try again
allowed := r.allowlist.Allowed(endpoint)
Expand Down Expand Up @@ -664,7 +677,9 @@ func (s *connectionScope) PeerScope() network.PeerScope {
}

func (s *connectionScope) Done() {
s.rcmgr.connLimiter.rmConn(s.ip)
if s.ip.IsValid() {
s.rcmgr.connLimiter.rmConn(s.ip)
}
s.resourceScope.Done()
}

Expand Down
18 changes: 17 additions & 1 deletion p2p/protocol/circuitv2/client/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,24 @@ func AddTransport(h host.Host, upgrader transport.Upgrader) error {
var _ transport.Transport = (*Client)(nil)
var _ io.Closer = (*Client)(nil)

// If the resource manager supports OpenConnectionNoIP, we'll use it to open connections.
// That's because the swarm is already limiting by IP address at the swarm
// level, and here we want to limit by everything but the IP.
// Some ResourceManager implementations may not care about IP addresses, so we
// do our own interface check to see if they provide this option.
type rcmgrOpenConnectionNoIPer interface {
OpenConnectionNoIP(network.Direction, bool, ma.Multiaddr) (network.ConnManagementScope, error)
}

func (c *Client) Dial(ctx context.Context, a ma.Multiaddr, p peer.ID) (transport.CapableConn, error) {
connScope, err := c.host.Network().ResourceManager().OpenConnection(network.DirOutbound, false, a)
var connScope network.ConnManagementScope
var err error
if rcmgr, ok := c.host.Network().ResourceManager().(rcmgrOpenConnectionNoIPer); ok {
connScope, err = rcmgr.OpenConnectionNoIP(network.DirOutbound, false, a)
} else {
connScope, err = c.host.Network().ResourceManager().OpenConnection(network.DirOutbound, false, a)
}

if err != nil {
return nil, err
}
Expand Down

0 comments on commit ccdf0e1

Please sign in to comment.