Coverage Report

Created: 2026-08-31 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/redis-rs/redis/src/io/tcp.rs
Line
Count
Source
1
use std::{io, net::TcpStream};
2
3
use std::time::Duration;
4
5
#[cfg(not(target_family = "wasm"))]
6
pub use socket2;
7
8
/// Settings for a TCP stream.
9
#[derive(Clone, Debug)]
10
pub struct TcpSettings {
11
    nodelay: bool,
12
    #[cfg(not(target_family = "wasm"))]
13
    keepalive: Option<socket2::TcpKeepalive>,
14
    linger_time: Option<Duration>,
15
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
16
    user_timeout: Option<Duration>,
17
}
18
19
impl TcpSettings {
20
    /// Returns the value of the `TCP_NODELAY` option on this socket.
21
0
    pub fn nodelay(&self) -> bool {
22
0
        self.nodelay
23
0
    }
24
25
    /// Returns parameters configuring TCP keepalive probes for this socket.
26
    #[cfg(not(target_family = "wasm"))]
27
0
    pub fn keepalive(&self) -> Option<&socket2::TcpKeepalive> {
28
0
        self.keepalive.as_ref()
29
0
    }
30
31
    /// Returns the value of the `TCP_USER_TIMEOUT` option on this socket.
32
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
33
0
    pub fn user_timeout(&self) -> Option<Duration> {
34
0
        self.user_timeout
35
0
    }
36
37
    /// Sets the value of the `TCP_NODELAY` option on this socket.
38
0
    pub fn set_nodelay(self, nodelay: bool) -> Self {
39
0
        Self { nodelay, ..self }
40
0
    }
41
42
    /// Set parameters configuring TCP keepalive probes for this socket.
43
    ///
44
    /// Default values are system-specific
45
    #[cfg(not(target_family = "wasm"))]
46
0
    pub fn set_keepalive(self, keepalive: socket2::TcpKeepalive) -> Self {
47
0
        Self {
48
0
            keepalive: Some(keepalive),
49
0
            ..self
50
0
        }
51
0
    }
52
53
    /// Set the SO_LINGER time on this socket.
54
    ///
55
    /// By default, lingering is disabled and sockets will remain in the background
56
    /// after being closed. Setting linger to `Duration::ZERO` will disable lingering
57
    /// and cause sockets to no longer wait in the TIME-WAIT state (at the cost of causing
58
    /// unusual behavior if connecting to non-local-hosts where packets may be ordered).
59
    /// Setting linger to a non-zero value will cause close/shutdown to wait for
60
    /// reordered packets. This option may not do anything depending on your operating
61
    /// system and its configuration; please consult your friendly neighborhood netadmin.
62
    /// For more information, see the socket(7) man page.
63
0
    pub fn set_linger_time(self, linger: Duration) -> Self {
64
0
        Self {
65
0
            linger_time: Some(linger),
66
0
            ..self
67
0
        }
68
0
    }
69
70
    /// Set the value of the `TCP_USER_TIMEOUT` option on this socket.
71
    #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
72
0
    pub fn set_user_timeout(self, user_timeout: Duration) -> Self {
73
0
        Self {
74
0
            user_timeout: Some(user_timeout),
75
0
            ..self
76
0
        }
77
0
    }
78
}
79
80
#[allow(clippy::derivable_impls)]
81
impl Default for TcpSettings {
82
0
    fn default() -> Self {
83
0
        Self {
84
0
            nodelay: false,
85
0
            #[cfg(not(target_family = "wasm"))]
86
0
            keepalive: None,
87
0
            linger_time: None,
88
0
            #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
89
0
            user_timeout: None,
90
0
        }
91
0
    }
92
}
93
94
0
pub(crate) fn stream_with_settings(
95
0
    socket: TcpStream,
96
0
    settings: &TcpSettings,
97
0
) -> io::Result<TcpStream> {
98
0
    socket.set_nodelay(settings.nodelay)?;
99
    #[cfg(not(target_family = "wasm"))]
100
    {
101
0
        let socket2: socket2::Socket = socket.into();
102
0
        if let Some(keepalive) = &settings.keepalive {
103
0
            socket2.set_tcp_keepalive(keepalive)?;
104
0
        }
105
0
        if let Some(linger) = &settings.linger_time {
106
0
            socket2.set_linger(Some(*linger))?;
107
0
        }
108
        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
109
0
        socket2.set_tcp_user_timeout(settings.user_timeout)?;
110
0
        Ok(socket2.into())
111
    }
112
    #[cfg(target_family = "wasm")]
113
    {
114
        Ok(socket)
115
    }
116
0
}