/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 | } |