redis/io/
tcp.rs

1use std::{io, net::TcpStream};
2
3#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
4use std::time::Duration;
5
6pub use socket2;
7
8/// Settings for a TCP stream.
9#[derive(Clone, Debug)]
10pub struct TcpSettings {
11    nodelay: bool,
12    keepalive: Option<socket2::TcpKeepalive>,
13    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
14    user_timeout: Option<Duration>,
15}
16
17impl TcpSettings {
18    /// Sets the value of the `TCP_NODELAY` option on this socket.
19    pub fn set_nodelay(self, nodelay: bool) -> Self {
20        Self { nodelay, ..self }
21    }
22
23    /// Set parameters configuring TCP keepalive probes for this socket.
24    ///
25    /// Default values are system-specific
26    pub fn set_keepalive(self, keepalive: socket2::TcpKeepalive) -> Self {
27        Self {
28            keepalive: Some(keepalive),
29            ..self
30        }
31    }
32
33    /// Set the value of the `TCP_USER_TIMEOUT` option on this socket.
34    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
35    pub fn set_user_timeout(self, user_timeout: Duration) -> Self {
36        Self {
37            user_timeout: Some(user_timeout),
38            ..self
39        }
40    }
41}
42
43#[allow(clippy::derivable_impls)]
44impl Default for TcpSettings {
45    fn default() -> Self {
46        Self {
47            #[cfg(feature = "tcp_nodelay")]
48            nodelay: true,
49            #[cfg(not(feature = "tcp_nodelay"))]
50            nodelay: false,
51            keepalive: None,
52            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
53            user_timeout: None,
54        }
55    }
56}
57
58pub(crate) fn stream_with_settings(
59    socket: TcpStream,
60    settings: &TcpSettings,
61) -> io::Result<TcpStream> {
62    socket.set_nodelay(settings.nodelay)?;
63    let socket2: socket2::Socket = socket.into();
64    if let Some(keepalive) = &settings.keepalive {
65        socket2.set_tcp_keepalive(keepalive)?;
66    }
67    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
68    socket2.set_tcp_user_timeout(settings.user_timeout)?;
69    Ok(socket2.into())
70}