diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs index 47376970..87be8f3e 100644 --- a/src/bin/proxmox-backup-proxy.rs +++ b/src/bin/proxmox-backup-proxy.rs @@ -1,5 +1,6 @@ use std::sync::{Arc}; use std::path::{Path, PathBuf}; +use std::os::unix::io::AsRawFd; use anyhow::{bail, format_err, Error}; use futures::*; @@ -16,7 +17,16 @@ use proxmox_backup::server; use proxmox_backup::tools::daemon; use proxmox_backup::server::{ApiConfig, rest::*}; use proxmox_backup::auth_helpers::*; -use proxmox_backup::tools::disks::{ DiskManage, zfs_pool_stats }; +use proxmox_backup::tools::{ + disks::{ + DiskManage, + zfs_pool_stats, + }, + socket::{ + set_tcp_keepalive, + PROXMOX_BACKUP_TCP_KEEPALIVE_TIME, + }, +}; use proxmox_backup::api2::pull::do_sync_job; @@ -89,6 +99,9 @@ async fn run() -> Result<(), Error> { let acceptor = Arc::clone(&acceptor); async move { sock.set_nodelay(true).unwrap(); + + let _ = set_tcp_keepalive(sock.as_raw_fd(), PROXMOX_BACKUP_TCP_KEEPALIVE_TIME); + Ok(tokio_openssl::accept(&acceptor, sock) .await .ok() // handshake errors aren't be fatal, so return None to filter diff --git a/src/client/http_client.rs b/src/client/http_client.rs index e18b8fab..e3d18604 100644 --- a/src/client/http_client.rs +++ b/src/client/http_client.rs @@ -2,6 +2,7 @@ use std::io::Write; use std::task::{Context, Poll}; use std::sync::{Arc, Mutex, RwLock}; use std::time::Duration; +use std::os::unix::io::AsRawFd; use anyhow::{bail, format_err, Error}; use futures::*; @@ -26,7 +27,15 @@ use proxmox::{ use super::pipe_to_stream::PipeToSendStream; use crate::api2::types::Userid; use crate::tools::async_io::EitherStream; -use crate::tools::{self, BroadcastFuture, DEFAULT_ENCODE_SET}; +use crate::tools::{ + self, + BroadcastFuture, + DEFAULT_ENCODE_SET, + socket::{ + set_tcp_keepalive, + PROXMOX_BACKUP_TCP_KEEPALIVE_TIME, + }, +}; #[derive(Clone)] pub struct AuthInfo { @@ -608,7 +617,7 @@ impl HttpClient { .await?; let connection = connection - .map_err(|_| panic!("HTTP/2.0 connection failed")); + .map_err(|_| eprintln!("HTTP/2.0 connection failed")); let (connection, abort) = futures::future::abortable(connection); // A cancellable future returns an Option which is None when cancelled and @@ -969,6 +978,9 @@ impl hyper::service::Service for HttpsConnector { let config = this.ssl_connector.configure(); let conn = this.http.call(dst).await?; + + let _ = set_tcp_keepalive(conn.as_raw_fd(), PROXMOX_BACKUP_TCP_KEEPALIVE_TIME); + if is_https { let conn = tokio_openssl::connect(config?, &host, conn).await?; Ok(MaybeTlsStream::Right(conn)) diff --git a/src/tools.rs b/src/tools.rs index 5b244c02..1837c0e0 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -35,6 +35,7 @@ pub mod nom; pub mod logrotate; pub mod loopdev; pub mod fuse_loop; +pub mod socket; mod parallel_handler; pub use parallel_handler::*; diff --git a/src/tools/socket.rs b/src/tools/socket.rs new file mode 100644 index 00000000..bbb8af1d --- /dev/null +++ b/src/tools/socket.rs @@ -0,0 +1,23 @@ +use std::os::unix::io::RawFd; + +use nix::sys::socket::sockopt::{KeepAlive, TcpKeepIdle}; +use nix::sys::socket::setsockopt; + +pub const PROXMOX_BACKUP_TCP_KEEPALIVE_TIME: u32 = 120; + +/// Set TCP keepalive time on a socket +/// +/// See "man 7 tcp" for details. +/// +/// The default on Linix is 7200 (2 hours) which is much too long for +/// our backup tools. +pub fn set_tcp_keepalive( + socket_fd: RawFd, + tcp_keepalive_time: u32, +) -> nix::Result<()> { + + setsockopt(socket_fd, KeepAlive, &true)?; + setsockopt(socket_fd, TcpKeepIdle, &tcp_keepalive_time)?; + + Ok(()) +}