From a85e7f7442117271c97ffbedc1671a7b1ea996a5 Mon Sep 17 00:00:00 2001 From: cloudhead Date: Wed, 22 May 2024 14:46:08 +0200 Subject: [PATCH] node: Set TCP_KEEPALIVE on sockets Ensures dead connections are not kept around longer than necessary. Note that the ping/pong mechanism is more expensive and checks that the session is active and healthy, while TCP_KEEPALIVE is lower level, cheaper, and checks that the connection is still alive. --- Cargo.lock | 1 + radicle-node/Cargo.toml | 1 + radicle-node/src/wire/protocol.rs | 11 ++++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 34d11e13..81bb55b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2683,6 +2683,7 @@ dependencies = [ "serde", "serde_json", "snapbox", + "socket2", "sqlite", "tempfile", "thiserror", diff --git a/radicle-node/Cargo.toml b/radicle-node/Cargo.toml index cda98b6d..96c76b94 100644 --- a/radicle-node/Cargo.toml +++ b/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" } diff --git a/radicle-node/src/wire/protocol.rs b/radicle-node/src/wire/protocol.rs index f6f8de35..0df48147 100644 --- a/radicle-node/src/wire/protocol.rs +++ b/radicle-node/src/wire/protocol.rs @@ -1181,8 +1181,17 @@ fn session>( 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,