Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
node: Add connection limits
Merged did:key:z6MktaNv...ZRZW opened 2 years ago

The limits are roughly modeled after the Bitcoin network.

3 files changed +48 -1 5bdc2ad1 786ce40f
modified radicle-cli/examples/rad-config.md
@@ -43,6 +43,10 @@ $ rad config
          "fillRate": 1.0,
          "capacity": 64
        }
+
      },
+
      "connection": {
+
        "inbound": 128,
+
        "outbound": 16
      }
    },
    "policy": "block",
modified radicle-node/src/service.rs
@@ -1059,10 +1059,15 @@ where

    /// Inbound connection attempt.
    pub fn accepted(&mut self, addr: Address) -> bool {
-
        // Always accept trusted connections.
+
        // Always accept trusted connections, even if we already reached
+
        // our inbound connection limit.
        if addr.is_trusted() {
            return true;
        }
+
        // Check for inbound connection limit.
+
        if self.sessions.inbound().count() >= self.config.limits.connection.inbound {
+
            return false;
+
        }
        let host: HostName = addr.into();

        if self
@@ -1912,6 +1917,10 @@ where
            error!(target: "service", "Attempted connection to self");
            return false;
        }
+
        if self.sessions.outbound().count() >= self.config.limits.connection.outbound {
+
            error!(target: "service", "Outbound connection limit reached when attempting {nid} ({addr})");
+
            return false;
+
        }
        let persistent = self.config.is_persistent(&nid);
        let time = self.time();

@@ -2345,6 +2354,16 @@ impl Sessions {
            })
    }

+
    /// Iterator over connected inbound peers.
+
    pub fn inbound(&self) -> impl Iterator<Item = (&NodeId, &Session)> + Clone {
+
        self.connected().filter(|(_, s)| s.link.is_inbound())
+
    }
+

+
    /// Iterator over outbound peers.
+
    pub fn outbound(&self) -> impl Iterator<Item = (&NodeId, &Session)> + Clone {
+
        self.connected().filter(|(_, s)| s.link.is_outbound())
+
    }
+

    /// Iterator over mutable fully connected peers.
    pub fn connected_mut(&mut self) -> impl Iterator<Item = (&NodeId, &mut Session)> {
        self.0.iter_mut().filter(move |(_, s)| s.is_connected())
modified radicle/src/node/config.rs
@@ -93,6 +93,9 @@ pub struct Limits {
    /// Rate limitter settings.
    #[serde(default)]
    pub rate: RateLimits,
+
    /// Connection limits.
+
    #[serde(default)]
+
    pub connection: ConnectionLimits,
}

impl Default for Limits {
@@ -104,6 +107,27 @@ impl Default for Limits {
            fetch_concurrency: 1,
            max_open_files: 4096,
            rate: RateLimits::default(),
+
            connection: ConnectionLimits::default(),
+
        }
+
    }
+
}
+

+
/// Connection limits.
+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+
#[serde(rename_all = "camelCase")]
+
pub struct ConnectionLimits {
+
    /// Max inbound connections.
+
    pub inbound: usize,
+
    /// Max outbound connections. Note that this is higher than the *target* number
+
    /// in [`TARGET_OUTBOUND_PEERS`].
+
    pub outbound: usize,
+
}
+

+
impl Default for ConnectionLimits {
+
    fn default() -> Self {
+
        Self {
+
            inbound: 128,
+
            outbound: 16,
        }
    }
}