1use socket2::Type as SockType;
2use std::net::SocketAddr;
3use std::time::Duration;
4
5use crate::SocketFamily;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TcpSocketType {
10 Stream,
11 Raw,
12}
13
14impl TcpSocketType {
15 pub fn is_stream(&self) -> bool {
17 matches!(self, TcpSocketType::Stream)
18 }
19
20 pub fn is_raw(&self) -> bool {
22 matches!(self, TcpSocketType::Raw)
23 }
24
25 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#[derive(Debug, Clone)]
36pub struct TcpConfig {
37 pub socket_family: SocketFamily,
39 pub socket_type: TcpSocketType,
41 pub bind_addr: Option<SocketAddr>,
43 pub nonblocking: bool,
45 pub reuseaddr: Option<bool>,
47 pub nodelay: Option<bool>,
49 pub linger: Option<Duration>,
51 pub ttl: Option<u32>,
53 pub hoplimit: Option<u32>,
55 pub read_timeout: Option<Duration>,
57 pub write_timeout: Option<Duration>,
59 pub bind_device: Option<String>,
61 pub keepalive: Option<bool>,
63}
64
65impl TcpConfig {
66 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 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 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 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 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}