1use std::time::Duration;
4
5use crate::error::NetError;
6use crate::sys::{self, AsSock};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
15pub struct Keepalive {
16 pub idle: Duration,
18 pub interval: Duration,
20 pub count: u32,
22}
23
24impl Keepalive {
25 pub const DEFAULT: Keepalive = Keepalive {
27 idle: Duration::from_secs(60),
28 interval: Duration::from_secs(10),
29 count: 6,
30 };
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub enum Linger {
40 Off,
42 Abortive,
44 Timeout(Duration),
46}
47
48impl Linger {
49 fn to_sys(self) -> Option<Duration> {
50 match self {
51 Linger::Off => None,
52 Linger::Abortive => Some(Duration::ZERO),
53 Linger::Timeout(d) => Some(d),
54 }
55 }
56}
57
58#[must_use]
66#[non_exhaustive]
67#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
68pub struct TcpOptions {
69 pub nodelay: Option<bool>,
71 pub keepalive: Option<Keepalive>,
73 pub linger: Option<Linger>,
75 pub send_buffer: Option<u32>,
77 pub receive_buffer: Option<u32>,
79 pub ttl: Option<u8>,
81}
82
83impl TcpOptions {
84 pub fn new() -> TcpOptions {
86 TcpOptions::default()
87 }
88
89 pub fn nodelay(mut self, on: bool) -> TcpOptions {
91 self.nodelay = Some(on);
92 self
93 }
94
95 pub fn keepalive(mut self, k: Keepalive) -> TcpOptions {
97 self.keepalive = Some(k);
98 self
99 }
100
101 pub fn linger(mut self, l: Linger) -> TcpOptions {
103 self.linger = Some(l);
104 self
105 }
106
107 pub fn send_buffer(mut self, bytes: u32) -> TcpOptions {
109 self.send_buffer = Some(bytes);
110 self
111 }
112
113 pub fn receive_buffer(mut self, bytes: u32) -> TcpOptions {
115 self.receive_buffer = Some(bytes);
116 self
117 }
118
119 pub fn ttl(mut self, hops: u8) -> TcpOptions {
121 self.ttl = Some(hops);
122 self
123 }
124
125 pub(crate) fn apply<S: AsSock>(&self, socket: &S, v6: bool) -> Result<(), NetError> {
127 let sock = socket.sock();
128 let os = |op: &'static str| move |e| NetError::from_os(op, e);
129 if let Some(on) = self.nodelay {
130 sys::set_nodelay(sock, on).map_err(os("TCP_NODELAY"))?;
131 }
132 if let Some(k) = self.keepalive {
133 check_keepalive(&k)?;
134 sys::set_keepalive(sock, Some((k.idle, k.interval, k.count)))
135 .map_err(os("keepalive"))?;
136 }
137 if let Some(l) = self.linger {
138 sys::set_linger(sock, l.to_sys()).map_err(os("SO_LINGER"))?;
139 }
140 if let Some(n) = self.send_buffer {
141 sys::set_send_buffer(sock, n).map_err(os("SO_SNDBUF"))?;
142 }
143 if let Some(n) = self.receive_buffer {
144 sys::set_receive_buffer(sock, n).map_err(os("SO_RCVBUF"))?;
145 }
146 if let Some(h) = self.ttl {
147 sys::set_ttl(sock, v6, h).map_err(os("IP_TTL"))?;
148 }
149 Ok(())
150 }
151
152 pub(crate) fn is_empty(&self) -> bool {
154 *self == TcpOptions::default()
155 }
156}
157
158fn check_keepalive(k: &Keepalive) -> Result<(), NetError> {
159 if cfg!(windows) && k.count > 255 {
160 return Err(NetError::InvalidConfig {
161 field: "keepalive",
162 reason: crate::error::ConfigReason::TooLarge { max: 255 },
163 });
164 }
165 if k.idle.is_zero() || k.interval.is_zero() || k.count == 0 {
166 return Err(NetError::InvalidConfig {
167 field: "keepalive",
168 reason: crate::error::ConfigReason::Zero,
169 });
170 }
171 Ok(())
172}
173
174#[must_use]
184#[derive(Clone, Copy, Debug, PartialEq, Eq)]
185pub struct ListenOptions {
186 pub(crate) backlog: u32,
187 pub(crate) reuse_address: bool,
188 pub(crate) reuse_port: bool,
189 pub(crate) ipv6_only: bool,
190 pub(crate) send_buffer: Option<u32>,
191 pub(crate) receive_buffer: Option<u32>,
192 pub(crate) tcp: TcpOptions,
193}
194
195impl Default for ListenOptions {
196 fn default() -> ListenOptions {
197 ListenOptions {
198 backlog: 1024,
199 reuse_address: cfg!(unix),
200 reuse_port: false,
201 ipv6_only: true,
202 send_buffer: None,
203 receive_buffer: None,
204 tcp: TcpOptions::new().nodelay(true),
205 }
206 }
207}
208
209impl ListenOptions {
210 pub fn new() -> ListenOptions {
213 ListenOptions::default()
214 }
215
216 pub fn backlog(mut self, n: u32) -> ListenOptions {
218 self.backlog = n;
219 self
220 }
221
222 pub fn reuse_address(mut self, on: bool) -> ListenOptions {
224 self.reuse_address = on;
225 self
226 }
227
228 pub fn reuse_port(mut self, on: bool) -> ListenOptions {
230 self.reuse_port = on;
231 self
232 }
233
234 pub fn ipv6_only(mut self, on: bool) -> ListenOptions {
236 self.ipv6_only = on;
237 self
238 }
239
240 pub fn send_buffer(mut self, bytes: u32) -> ListenOptions {
242 self.send_buffer = Some(bytes);
243 self
244 }
245
246 pub fn receive_buffer(mut self, bytes: u32) -> ListenOptions {
248 self.receive_buffer = Some(bytes);
249 self
250 }
251
252 pub fn tcp_options(mut self, options: TcpOptions) -> ListenOptions {
254 self.tcp = options;
255 self
256 }
257
258 pub(crate) fn params(&self) -> sys::ListenParams {
259 sys::ListenParams {
260 reuse_address: self.reuse_address,
261 reuse_port: self.reuse_port,
262 ipv6_only: self.ipv6_only,
263 send_buffer: self.send_buffer,
264 receive_buffer: self.receive_buffer,
265 backlog: self.backlog,
266 }
267 }
268}
269
270#[derive(Debug)]
282pub struct SocketOptions<'a> {
283 pub(crate) sock: sys::Sock<'a>,
284 pub(crate) v6: bool,
285}
286
287fn os(op: &'static str) -> impl Fn(std::io::Error) -> NetError {
288 move |e| NetError::from_os(op, e)
289}
290
291impl SocketOptions<'_> {
292 pub fn nodelay(&self) -> Result<bool, NetError> {
298 sys::nodelay(self.sock).map_err(os("TCP_NODELAY"))
299 }
300
301 pub fn set_nodelay(&self, on: bool) -> Result<(), NetError> {
307 sys::set_nodelay(self.sock, on).map_err(os("TCP_NODELAY"))
308 }
309
310 pub fn keepalive(&self) -> Result<Option<Keepalive>, NetError> {
316 Ok(sys::keepalive(self.sock)
317 .map_err(os("keepalive"))?
318 .map(|(idle, interval, count)| Keepalive {
319 idle,
320 interval,
321 count,
322 }))
323 }
324
325 pub fn set_keepalive(&self, k: Option<Keepalive>) -> Result<(), NetError> {
331 if let Some(k) = &k {
332 check_keepalive(k)?;
333 }
334 sys::set_keepalive(self.sock, k.map(|k| (k.idle, k.interval, k.count)))
335 .map_err(os("keepalive"))
336 }
337
338 pub fn linger(&self) -> Result<Linger, NetError> {
344 Ok(match sys::linger(self.sock).map_err(os("SO_LINGER"))? {
345 None => Linger::Off,
346 Some(d) if d.is_zero() => Linger::Abortive,
347 Some(d) => Linger::Timeout(d),
348 })
349 }
350
351 pub fn set_linger(&self, l: Linger) -> Result<(), NetError> {
357 sys::set_linger(self.sock, l.to_sys()).map_err(os("SO_LINGER"))
358 }
359
360 pub fn send_buffer(&self) -> Result<u32, NetError> {
366 sys::send_buffer(self.sock).map_err(os("SO_SNDBUF"))
367 }
368
369 pub fn set_send_buffer(&self, bytes: u32) -> Result<u32, NetError> {
375 sys::set_send_buffer(self.sock, bytes).map_err(os("SO_SNDBUF"))
376 }
377
378 pub fn receive_buffer(&self) -> Result<u32, NetError> {
384 sys::receive_buffer(self.sock).map_err(os("SO_RCVBUF"))
385 }
386
387 pub fn set_receive_buffer(&self, bytes: u32) -> Result<u32, NetError> {
393 sys::set_receive_buffer(self.sock, bytes).map_err(os("SO_RCVBUF"))
394 }
395
396 pub fn ttl(&self) -> Result<u8, NetError> {
402 sys::ttl(self.sock, self.v6).map_err(os("IP_TTL"))
403 }
404
405 pub fn set_ttl(&self, hops: u8) -> Result<(), NetError> {
411 sys::set_ttl(self.sock, self.v6, hops).map_err(os("IP_TTL"))
412 }
413}
414
415#[must_use]
423#[derive(Clone, Debug, PartialEq, Eq)]
424pub struct LocalOptions {
425 pub(crate) mode: u32,
426 pub(crate) owner: Option<u32>,
427 pub(crate) group: Option<u32>,
428 pub(crate) remove_stale: bool,
429 pub(crate) require_uid: Option<u32>,
430 pub(crate) backlog: u32,
431}
432
433impl Default for LocalOptions {
434 fn default() -> LocalOptions {
435 LocalOptions::new()
436 }
437}
438
439impl LocalOptions {
440 pub fn new() -> LocalOptions {
442 LocalOptions {
443 mode: 0o600,
444 owner: None,
445 group: None,
446 remove_stale: true,
447 require_uid: None,
448 backlog: 1024,
449 }
450 }
451
452 pub fn mode(mut self, mode: u32) -> LocalOptions {
454 self.mode = mode & 0o777;
455 self
456 }
457
458 pub fn owner(mut self, uid: u32) -> LocalOptions {
460 self.owner = Some(uid);
461 self
462 }
463
464 pub fn group(mut self, gid: u32) -> LocalOptions {
466 self.group = Some(gid);
467 self
468 }
469
470 pub fn group_access(mut self, gid: u32) -> LocalOptions {
472 self.group = Some(gid);
473 self.mode = 0o660;
474 self
475 }
476
477 pub fn remove_stale(mut self, on: bool) -> LocalOptions {
481 self.remove_stale = on;
482 self
483 }
484
485 pub fn require_uid(mut self, uid: u32) -> LocalOptions {
487 self.require_uid = Some(uid);
488 self
489 }
490
491 pub fn backlog(mut self, backlog: u32) -> LocalOptions {
493 self.backlog = backlog;
494 self
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501
502 #[test]
503 fn test_local_options_builders() {
504 let o = LocalOptions::new();
505 assert_eq!((o.mode, o.remove_stale, o.backlog), (0o600, true, 1024));
506 let o = o
507 .group_access(7)
508 .owner(3)
509 .require_uid(9)
510 .mode(0o1777)
511 .backlog(5);
512 assert_eq!(o.mode, 0o777);
513 assert_eq!(
514 (o.group, o.owner, o.require_uid),
515 (Some(7), Some(3), Some(9))
516 );
517 assert_eq!(LocalOptions::default(), LocalOptions::new());
518 }
519
520 #[test]
521 fn test_keepalive_zero_rejected() {
522 let k = Keepalive {
523 idle: Duration::ZERO,
524 interval: Duration::from_secs(1),
525 count: 1,
526 };
527 assert!(check_keepalive(&k).is_err());
528 assert!(check_keepalive(&Keepalive::DEFAULT).is_ok());
529 }
530
531 #[test]
532 fn test_listen_defaults() {
533 let o = ListenOptions::new();
534 assert_eq!(o.backlog, 1024);
535 assert!(o.ipv6_only);
536 assert_eq!(o.reuse_address, cfg!(unix));
537 assert_eq!(o.tcp.nodelay, Some(true));
538 }
539
540 #[test]
541 fn test_tcp_options_is_empty() {
542 assert!(TcpOptions::new().is_empty());
543 assert!(!TcpOptions::new().ttl(5).is_empty());
544 }
545}