Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
node: TCP connection improvements
Merged did:key:z6MksFqX...wzpT opened 1 year ago
  • Set socket options for inbounds too
  • Set TCP_KEEPALIVE on sockets
3 files changed +32 -16 3403a66d a85e7f74
modified Cargo.lock
@@ -2683,6 +2683,7 @@ dependencies = [
 "serde",
 "serde_json",
 "snapbox",
+
 "socket2",
 "sqlite",
 "tempfile",
 "thiserror",
modified radicle-node/Cargo.toml
@@ -39,6 +39,7 @@ scrypt = { version = "0.11.0", default-features = false }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["preserve_order"] }
snapbox = { version = "0.4.3", optional = true }
+
socket2 = { version = "0.5.7" }
tempfile = { version = "3.3.0" }
thiserror = { version = "1" }

modified radicle-node/src/wire/protocol.rs
@@ -546,7 +546,14 @@ where
                    return;
                }

-
                let session = accept::<G>(remote.clone().into(), connection, self.signer.clone());
+
                let session =
+
                    match accept::<G>(remote.clone().into(), connection, self.signer.clone()) {
+
                        Ok(s) => s,
+
                        Err(e) => {
+
                            log::error!(target: "wire", "Error creating session for {ip}: {e}");
+
                            return;
+
                        }
+
                    };
                let transport = match NetTransport::with_session(session, Link::Inbound) {
                    Ok(transport) => transport,
                    Err(err) => {
@@ -1141,21 +1148,13 @@ pub fn dial<G: Signer + Ecdh<Pk = NodeId>>(
    // `socket2` library not supporting non-blocking connect with timeout.
    let connection = net::TcpStream::connect_nonblocking(inet_addr, DEFAULT_DIAL_TIMEOUT)?;

-
    connection.set_read_timeout(Some(DEFAULT_CONNECTION_TIMEOUT))?;
-
    connection.set_write_timeout(Some(DEFAULT_CONNECTION_TIMEOUT))?;
-

-
    // There are issues with setting TCP_NODELAY on WSL. Not a big deal.
-
    if let Err(e) = connection.set_nodelay(true) {
-
        log::warn!(target: "wire", "Unable to set TCP_NODELAY on fd {}: {e}", connection.as_raw_fd());
-
    }
-

-
    Ok(session::<G>(
+
    session::<G>(
        remote_addr,
        Some(remote_id),
        connection,
        force_proxy,
        signer,
-
    ))
+
    )
}

/// Accept a new connection.
@@ -1163,7 +1162,7 @@ pub fn accept<G: Signer + Ecdh<Pk = NodeId>>(
    remote_addr: NetAddr<HostName>,
    connection: net::TcpStream,
    signer: G,
-
) -> WireSession<G> {
+
) -> io::Result<WireSession<G>> {
    session::<G>(remote_addr, None, connection, false, signer)
}

@@ -1174,9 +1173,25 @@ fn session<G: Signer + Ecdh<Pk = NodeId>>(
    connection: net::TcpStream,
    force_proxy: bool,
    signer: G,
-
) -> WireSession<G> {
+
) -> io::Result<WireSession<G>> {
+
    // There are issues with setting TCP_NODELAY on WSL. Not a big deal.
+
    if let Err(e) = connection.set_nodelay(true) {
+
        log::warn!(target: "wire", "Unable to set TCP_NODELAY on fd {}: {e}", connection.as_raw_fd());
+
    }
+
    connection.set_read_timeout(Some(DEFAULT_CONNECTION_TIMEOUT))?;
+
    connection.set_write_timeout(Some(DEFAULT_CONNECTION_TIMEOUT))?;
+

+
    let sock = socket2::Socket::from(connection);
+
    let ka = socket2::TcpKeepalive::new()
+
        .with_time(time::Duration::from_secs(30))
+
        .with_interval(time::Duration::from_secs(10))
+
        .with_retries(3);
+
    if let Err(e) = sock.set_tcp_keepalive(&ka) {
+
        log::warn!(target: "wire", "Unable to set TCP_KEEPALIVE on fd {}: {e}", sock.as_raw_fd());
+
    }
+

    let socks5 = socks5::Socks5::with(remote_addr, force_proxy);
-
    let proxy = Socks5Session::with(connection, socks5);
+
    let proxy = Socks5Session::with(sock.into(), socks5);
    let pair = G::generate_keypair();
    let keyset = Keyset {
        e: pair.0,
@@ -1184,14 +1199,13 @@ fn session<G: Signer + Ecdh<Pk = NodeId>>(
        re: None,
        rs: remote_id,
    };
-

    let noise = NoiseState::initialize::<{ Sha256::OUTPUT_LEN }>(
        NOISE_XK,
        remote_id.is_some(),
        &[],
        keyset,
    );
-
    WireSession::with(proxy, noise)
+
    Ok(WireSession::with(proxy, noise))
}

#[cfg(test)]