1use std::net::TcpStream;
4use std::time::Duration;
5
6use crate::error::NetError;
7use crate::sys::{self, AsSock};
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub struct Keepalive {
17 pub idle: Duration,
19 pub interval: Duration,
21 pub count: u32,
23}
24
25impl Keepalive {
26 pub const DEFAULT: Keepalive = Keepalive {
28 idle: Duration::from_secs(60),
29 interval: Duration::from_secs(10),
30 count: 6,
31 };
32}
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum Linger {
41 Off,
43 Abortive,
45 Timeout(Duration),
47}
48
49impl Linger {
50 fn to_sys(self) -> Option<Duration> {
51 match self {
52 Linger::Off => None,
53 Linger::Abortive => Some(Duration::ZERO),
54 Linger::Timeout(d) => Some(d),
55 }
56 }
57}
58
59#[must_use]
67#[non_exhaustive]
68#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
69pub struct TcpOptions {
70 pub nodelay: Option<bool>,
72 pub keepalive: Option<Keepalive>,
74 pub linger: Option<Linger>,
76 pub send_buffer: Option<u32>,
78 pub receive_buffer: Option<u32>,
80 pub ttl: Option<u8>,
82}
83
84impl TcpOptions {
85 pub fn new() -> TcpOptions {
87 TcpOptions::default()
88 }
89
90 pub fn nodelay(mut self, on: bool) -> TcpOptions {
92 self.nodelay = Some(on);
93 self
94 }
95
96 pub fn keepalive(mut self, k: Keepalive) -> TcpOptions {
98 self.keepalive = Some(k);
99 self
100 }
101
102 pub fn linger(mut self, l: Linger) -> TcpOptions {
104 self.linger = Some(l);
105 self
106 }
107
108 pub fn send_buffer(mut self, bytes: u32) -> TcpOptions {
110 self.send_buffer = Some(bytes);
111 self
112 }
113
114 pub fn receive_buffer(mut self, bytes: u32) -> TcpOptions {
116 self.receive_buffer = Some(bytes);
117 self
118 }
119
120 pub fn ttl(mut self, hops: u8) -> TcpOptions {
122 self.ttl = Some(hops);
123 self
124 }
125
126 pub(crate) fn apply<S: AsSock>(&self, socket: &S, v6: bool) -> Result<(), NetError> {
128 let sock = socket.sock();
129 let os = |op: &'static str| move |e| NetError::from_os(op, e);
130 if let Some(on) = self.nodelay {
131 sys::set_nodelay(sock, on).map_err(os("TCP_NODELAY"))?;
132 }
133 if let Some(k) = self.keepalive {
134 check_keepalive(&k)?;
135 sys::set_keepalive(sock, Some((k.idle, k.interval, k.count)))
136 .map_err(os("keepalive"))?;
137 }
138 if let Some(l) = self.linger {
139 sys::set_linger(sock, l.to_sys()).map_err(os("SO_LINGER"))?;
140 }
141 if let Some(n) = self.send_buffer {
142 sys::set_send_buffer(sock, n).map_err(os("SO_SNDBUF"))?;
143 }
144 if let Some(n) = self.receive_buffer {
145 sys::set_receive_buffer(sock, n).map_err(os("SO_RCVBUF"))?;
146 }
147 if let Some(h) = self.ttl {
148 sys::set_ttl(sock, v6, h).map_err(os("IP_TTL"))?;
149 }
150 Ok(())
151 }
152
153 pub(crate) fn is_empty(&self) -> bool {
155 *self == TcpOptions::default()
156 }
157}
158
159fn check_keepalive(k: &Keepalive) -> Result<(), NetError> {
160 if cfg!(windows) && k.count > 255 {
161 return Err(NetError::InvalidConfig {
162 field: "keepalive",
163 reason: crate::error::ConfigReason::TooLarge { max: 255 },
164 });
165 }
166 if k.idle.is_zero() || k.interval.is_zero() || k.count == 0 {
167 return Err(NetError::InvalidConfig {
168 field: "keepalive",
169 reason: crate::error::ConfigReason::Zero,
170 });
171 }
172 Ok(())
173}
174
175#[must_use]
185#[derive(Clone, Copy, Debug, PartialEq, Eq)]
186pub struct ListenOptions {
187 pub(crate) backlog: u32,
188 pub(crate) reuse_address: bool,
189 pub(crate) reuse_port: bool,
190 pub(crate) ipv6_only: bool,
191 pub(crate) send_buffer: Option<u32>,
192 pub(crate) receive_buffer: Option<u32>,
193 pub(crate) tcp: TcpOptions,
194}
195
196impl Default for ListenOptions {
197 fn default() -> ListenOptions {
198 ListenOptions {
199 backlog: 1024,
200 reuse_address: cfg!(unix),
201 reuse_port: false,
202 ipv6_only: true,
203 send_buffer: None,
204 receive_buffer: None,
205 tcp: TcpOptions::new().nodelay(true),
206 }
207 }
208}
209
210impl ListenOptions {
211 pub fn new() -> ListenOptions {
214 ListenOptions::default()
215 }
216
217 pub fn backlog(mut self, n: u32) -> ListenOptions {
219 self.backlog = n;
220 self
221 }
222
223 pub fn reuse_address(mut self, on: bool) -> ListenOptions {
225 self.reuse_address = on;
226 self
227 }
228
229 pub fn reuse_port(mut self, on: bool) -> ListenOptions {
231 self.reuse_port = on;
232 self
233 }
234
235 pub fn ipv6_only(mut self, on: bool) -> ListenOptions {
237 self.ipv6_only = on;
238 self
239 }
240
241 pub fn send_buffer(mut self, bytes: u32) -> ListenOptions {
243 self.send_buffer = Some(bytes);
244 self
245 }
246
247 pub fn receive_buffer(mut self, bytes: u32) -> ListenOptions {
249 self.receive_buffer = Some(bytes);
250 self
251 }
252
253 pub fn tcp_options(mut self, options: TcpOptions) -> ListenOptions {
255 self.tcp = options;
256 self
257 }
258
259 pub(crate) fn params(&self) -> sys::ListenParams {
260 sys::ListenParams {
261 reuse_address: self.reuse_address,
262 reuse_port: self.reuse_port,
263 ipv6_only: self.ipv6_only,
264 send_buffer: self.send_buffer,
265 receive_buffer: self.receive_buffer,
266 backlog: self.backlog,
267 }
268 }
269}
270
271#[derive(Debug)]
283pub struct SocketOptions<'a> {
284 pub(crate) stream: &'a TcpStream,
285 pub(crate) v6: bool,
286}
287
288fn os(op: &'static str) -> impl Fn(std::io::Error) -> NetError {
289 move |e| NetError::from_os(op, e)
290}
291
292impl SocketOptions<'_> {
293 pub fn nodelay(&self) -> Result<bool, NetError> {
299 sys::nodelay(self.stream.sock()).map_err(os("TCP_NODELAY"))
300 }
301
302 pub fn set_nodelay(&self, on: bool) -> Result<(), NetError> {
308 sys::set_nodelay(self.stream.sock(), on).map_err(os("TCP_NODELAY"))
309 }
310
311 pub fn keepalive(&self) -> Result<Option<Keepalive>, NetError> {
317 Ok(sys::keepalive(self.stream.sock())
318 .map_err(os("keepalive"))?
319 .map(|(idle, interval, count)| Keepalive {
320 idle,
321 interval,
322 count,
323 }))
324 }
325
326 pub fn set_keepalive(&self, k: Option<Keepalive>) -> Result<(), NetError> {
332 if let Some(k) = &k {
333 check_keepalive(k)?;
334 }
335 sys::set_keepalive(self.stream.sock(), k.map(|k| (k.idle, k.interval, k.count)))
336 .map_err(os("keepalive"))
337 }
338
339 pub fn linger(&self) -> Result<Linger, NetError> {
345 Ok(
346 match sys::linger(self.stream.sock()).map_err(os("SO_LINGER"))? {
347 None => Linger::Off,
348 Some(d) if d.is_zero() => Linger::Abortive,
349 Some(d) => Linger::Timeout(d),
350 },
351 )
352 }
353
354 pub fn set_linger(&self, l: Linger) -> Result<(), NetError> {
360 sys::set_linger(self.stream.sock(), l.to_sys()).map_err(os("SO_LINGER"))
361 }
362
363 pub fn send_buffer(&self) -> Result<u32, NetError> {
369 sys::send_buffer(self.stream.sock()).map_err(os("SO_SNDBUF"))
370 }
371
372 pub fn set_send_buffer(&self, bytes: u32) -> Result<u32, NetError> {
378 sys::set_send_buffer(self.stream.sock(), bytes).map_err(os("SO_SNDBUF"))
379 }
380
381 pub fn receive_buffer(&self) -> Result<u32, NetError> {
387 sys::receive_buffer(self.stream.sock()).map_err(os("SO_RCVBUF"))
388 }
389
390 pub fn set_receive_buffer(&self, bytes: u32) -> Result<u32, NetError> {
396 sys::set_receive_buffer(self.stream.sock(), bytes).map_err(os("SO_RCVBUF"))
397 }
398
399 pub fn ttl(&self) -> Result<u8, NetError> {
405 sys::ttl(self.stream.sock(), self.v6).map_err(os("IP_TTL"))
406 }
407
408 pub fn set_ttl(&self, hops: u8) -> Result<(), NetError> {
414 sys::set_ttl(self.stream.sock(), self.v6, hops).map_err(os("IP_TTL"))
415 }
416}
417
418#[cfg(test)]
419mod tests {
420 use super::*;
421
422 #[test]
423 fn test_keepalive_zero_rejected() {
424 let k = Keepalive {
425 idle: Duration::ZERO,
426 interval: Duration::from_secs(1),
427 count: 1,
428 };
429 assert!(check_keepalive(&k).is_err());
430 assert!(check_keepalive(&Keepalive::DEFAULT).is_ok());
431 }
432
433 #[test]
434 fn test_listen_defaults() {
435 let o = ListenOptions::new();
436 assert_eq!(o.backlog, 1024);
437 assert!(o.ipv6_only);
438 assert_eq!(o.reuse_address, cfg!(unix));
439 assert_eq!(o.tcp.nodelay, Some(true));
440 }
441
442 #[test]
443 fn test_tcp_options_is_empty() {
444 assert!(TcpOptions::new().is_empty());
445 assert!(!TcpOptions::new().ttl(5).is_empty());
446 }
447}