redis/io/
tcp.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use std::{io, net::TcpStream};

#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
use std::time::Duration;

/// Settings for a TCP stream.
#[derive(Clone, Debug)]
pub struct TcpSettings {
    nodelay: bool,
    keepalive: Option<socket2::TcpKeepalive>,
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
    user_timeout: Option<Duration>,
}

impl TcpSettings {
    /// Sets the value of the `TCP_NODELAY` option on this socket.
    pub fn set_nodelay(self, nodelay: bool) -> Self {
        Self { nodelay, ..self }
    }

    /// Set parameters configuring TCP keepalive probes for this socket.
    ///
    /// Default values are system-specific
    pub fn set_keepalive(self, keepalive: socket2::TcpKeepalive) -> Self {
        Self {
            keepalive: Some(keepalive),
            ..self
        }
    }

    /// Set the value of the `TCP_USER_TIMEOUT` option on this socket.
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
    pub fn set_user_timeout(self, user_timeout: Duration) -> Self {
        Self {
            user_timeout: Some(user_timeout),
            ..self
        }
    }
}

impl Default for TcpSettings {
    fn default() -> Self {
        Self {
            #[cfg(feature = "tcp_nodelay")]
            nodelay: true,
            #[cfg(not(feature = "tcp_nodelay"))]
            nodelay: false,
            keepalive: None,
            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
            user_timeout: None,
        }
    }
}

pub(crate) fn stream_with_settings(
    socket: TcpStream,
    settings: &TcpSettings,
) -> io::Result<TcpStream> {
    socket.set_nodelay(settings.nodelay)?;
    let socket2: socket2::Socket = socket.into();
    if let Some(keepalive) = &settings.keepalive {
        socket2.set_tcp_keepalive(keepalive)?;
    }
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
    socket2.set_tcp_user_timeout(settings.user_timeout)?;
    Ok(socket2.into())
}