nex_socket/tcp/
config.rs

1use socket2::Type as SockType;
2use std::net::SocketAddr;
3use std::time::Duration;
4
5use crate::SocketFamily;
6
7/// TCP socket type, either STREAM or RAW.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TcpSocketType {
10    Stream,
11    Raw,
12}
13
14impl TcpSocketType {
15    /// Returns true if the socket type is STREAM.
16    pub fn is_stream(&self) -> bool {
17        matches!(self, TcpSocketType::Stream)
18    }
19
20    /// Returns true if the socket type is RAW.
21    pub fn is_raw(&self) -> bool {
22        matches!(self, TcpSocketType::Raw)
23    }
24
25    /// Converts the TCP socket type to a `socket2::Type`.
26    pub(crate) fn to_sock_type(&self) -> SockType {
27        match self {
28            TcpSocketType::Stream => SockType::STREAM,
29            TcpSocketType::Raw => SockType::RAW,
30        }
31    }
32}
33
34/// Configuration options for a TCP socket.
35#[derive(Debug, Clone)]
36pub struct TcpConfig {
37    /// The socket family, either IPv4 or IPv6.
38    pub socket_family: SocketFamily,
39    /// The type of TCP socket, either STREAM or RAW.
40    pub socket_type: TcpSocketType,
41    /// Optional address to bind the socket to.
42    pub bind_addr: Option<SocketAddr>,
43    /// Whether the socket should be non-blocking.
44    pub nonblocking: bool,
45    /// Whether to allow address reuse.
46    pub reuseaddr: Option<bool>,
47    /// Whether to disable Nagle's algorithm (TCP_NODELAY).
48    pub nodelay: Option<bool>,
49    /// Optional linger duration for the socket.
50    pub linger: Option<Duration>,
51    /// Optional Time-To-Live (TTL) for the socket.
52    pub ttl: Option<u32>,
53    /// Optional Hop Limit for the socket (IPv6).
54    pub hoplimit: Option<u32>,
55    /// Optional read timeout for the socket.
56    pub read_timeout: Option<Duration>,
57    /// Optional write timeout for the socket.
58    pub write_timeout: Option<Duration>,
59    /// Optional device to bind the socket to.
60    pub bind_device: Option<String>,
61    /// Whether to enable TCP keepalive.
62    pub keepalive: Option<bool>,
63}
64
65impl TcpConfig {
66    /// Create a STREAM socket for IPv4.
67    pub fn v4_stream() -> Self {
68        Self {
69            socket_family: SocketFamily::IPV4,
70            socket_type: TcpSocketType::Stream,
71            bind_addr: None,
72            nonblocking: false,
73            reuseaddr: None,
74            nodelay: None,
75            linger: None,
76            ttl: None,
77            hoplimit: None,
78            read_timeout: None,
79            write_timeout: None,
80            bind_device: None,
81            keepalive: None,
82        }
83    }
84
85    /// Create a RAW socket. Requires administrator privileges.
86    pub fn raw_v4() -> Self {
87        Self {
88            socket_family: SocketFamily::IPV4,
89            socket_type: TcpSocketType::Raw,
90            ..Self::v4_stream()
91        }
92    }
93
94    /// Create a STREAM socket for IPv6.
95    pub fn v6_stream() -> Self {
96        Self {
97            socket_family: SocketFamily::IPV6,
98            socket_type: TcpSocketType::Stream,
99            ..Self::v4_stream()
100        }
101    }
102
103    /// Create a RAW socket for IPv6. Requires administrator privileges.
104    pub fn raw_v6() -> Self {
105        Self {
106            socket_family: SocketFamily::IPV6,
107            socket_type: TcpSocketType::Raw,
108            ..Self::v4_stream()
109        }
110    }
111
112    // --- chainable modifiers ---
113
114    pub fn with_bind(mut self, addr: SocketAddr) -> Self {
115        self.bind_addr = Some(addr);
116        self
117    }
118
119    pub fn with_nonblocking(mut self, flag: bool) -> Self {
120        self.nonblocking = flag;
121        self
122    }
123
124    pub fn with_reuseaddr(mut self, flag: bool) -> Self {
125        self.reuseaddr = Some(flag);
126        self
127    }
128
129    pub fn with_nodelay(mut self, flag: bool) -> Self {
130        self.nodelay = Some(flag);
131        self
132    }
133
134    pub fn with_linger(mut self, dur: Duration) -> Self {
135        self.linger = Some(dur);
136        self
137    }
138
139    pub fn with_ttl(mut self, ttl: u32) -> Self {
140        self.ttl = Some(ttl);
141        self
142    }
143
144    pub fn with_hoplimit(mut self, hops: u32) -> Self {
145        self.hoplimit = Some(hops);
146        self
147    }
148
149    pub fn with_keepalive(mut self, on: bool) -> Self {
150        self.keepalive = Some(on);
151        self
152    }
153
154    pub fn with_read_timeout(mut self, timeout: Duration) -> Self {
155        self.read_timeout = Some(timeout);
156        self
157    }
158
159    pub fn with_write_timeout(mut self, timeout: Duration) -> Self {
160        self.write_timeout = Some(timeout);
161        self
162    }
163
164    pub fn with_bind_device(mut self, iface: impl Into<String>) -> Self {
165        self.bind_device = Some(iface.into());
166        self
167    }
168}
169
170#[cfg(test)]
171mod tests {
172    use super::*;
173
174    #[test]
175    fn tcp_config_builders() {
176        let addr: SocketAddr = "127.0.0.1:80".parse().unwrap();
177        let cfg = TcpConfig::v4_stream()
178            .with_bind(addr)
179            .with_nonblocking(true)
180            .with_reuseaddr(true)
181            .with_nodelay(true)
182            .with_ttl(10);
183
184        assert_eq!(cfg.socket_family, SocketFamily::IPV4);
185        assert_eq!(cfg.socket_type, TcpSocketType::Stream);
186        assert_eq!(cfg.bind_addr, Some(addr));
187        assert!(cfg.nonblocking);
188        assert_eq!(cfg.reuseaddr, Some(true));
189        assert_eq!(cfg.nodelay, Some(true));
190        assert_eq!(cfg.ttl, Some(10));
191    }
192}