nex_socket/tcp/
config.rs

1use socket2::{Domain, Type as SockType};
2use std::net::SocketAddr;
3use std::time::Duration;
4
5/// Configuration options for a TCP socket.
6#[derive(Debug, Clone)]
7pub struct TcpConfig {
8    pub domain: Domain,
9    pub sock_type: SockType,
10    pub bind_addr: Option<SocketAddr>,
11    pub nonblocking: bool,
12    pub reuseaddr: Option<bool>,
13    pub nodelay: Option<bool>,
14    pub linger: Option<Duration>,
15    pub ttl: Option<u32>,
16    pub bind_device: Option<String>,
17}
18
19impl TcpConfig {
20    /// Create a STREAM socket for IPv4.
21    pub fn v4_stream() -> Self {
22        Self {
23            domain: Domain::IPV4,
24            sock_type: SockType::STREAM,
25            bind_addr: None,
26            nonblocking: false,
27            reuseaddr: None,
28            nodelay: None,
29            linger: None,
30            ttl: None,
31            bind_device: None,
32        }
33    }
34
35    /// Create a RAW socket. Requires administrator privileges.
36    pub fn raw_v4() -> Self {
37        Self {
38            domain: Domain::IPV4,
39            sock_type: SockType::RAW,
40            ..Self::v4_stream()
41        }
42    }
43
44    /// Create a STREAM socket for IPv6.
45    pub fn v6_stream() -> Self {
46        Self {
47            domain: Domain::IPV6,
48            sock_type: SockType::STREAM,
49            ..Self::v4_stream()
50        }
51    }
52
53    /// Create a RAW socket for IPv6. Requires administrator privileges.
54    pub fn raw_v6() -> Self {
55        Self {
56            domain: Domain::IPV6,
57            sock_type: SockType::RAW,
58            ..Self::v4_stream()
59        }
60    }
61
62    // --- chainable modifiers ---
63
64    pub fn with_bind(mut self, addr: SocketAddr) -> Self {
65        self.bind_addr = Some(addr);
66        self
67    }
68
69    pub fn with_nonblocking(mut self, flag: bool) -> Self {
70        self.nonblocking = flag;
71        self
72    }
73
74    pub fn with_reuseaddr(mut self, flag: bool) -> Self {
75        self.reuseaddr = Some(flag);
76        self
77    }
78
79    pub fn with_nodelay(mut self, flag: bool) -> Self {
80        self.nodelay = Some(flag);
81        self
82    }
83
84    pub fn with_linger(mut self, dur: Duration) -> Self {
85        self.linger = Some(dur);
86        self
87    }
88
89    pub fn with_ttl(mut self, ttl: u32) -> Self {
90        self.ttl = Some(ttl);
91        self
92    }
93
94    pub fn with_bind_device(mut self, iface: impl Into<String>) -> Self {
95        self.bind_device = Some(iface.into());
96        self
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn tcp_config_builders() {
106        let addr: SocketAddr = "127.0.0.1:80".parse().unwrap();
107        let cfg = TcpConfig::v4_stream()
108            .with_bind(addr)
109            .with_nonblocking(true)
110            .with_reuseaddr(true)
111            .with_nodelay(true)
112            .with_ttl(10);
113
114        assert_eq!(cfg.domain, Domain::IPV4);
115        assert_eq!(cfg.sock_type, SockType::STREAM);
116        assert_eq!(cfg.bind_addr, Some(addr));
117        assert!(cfg.nonblocking);
118        assert_eq!(cfg.reuseaddr, Some(true));
119        assert_eq!(cfg.nodelay, Some(true));
120        assert_eq!(cfg.ttl, Some(10));
121    }
122}