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#[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 pub fn set_nodelay(self, nodelay: bool) -> Self {
20 Self { nodelay, ..self }
21 }
22
23 pub fn set_keepalive(self, keepalive: socket2::TcpKeepalive) -> Self {
27 Self {
28 keepalive: Some(keepalive),
29 ..self
30 }
31 }
32
33 #[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}