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 user_timeout: Option<Duration>,
82 pub ttl: Option<u8>,
84}
85
86impl TcpOptions {
87 pub fn new() -> TcpOptions {
89 TcpOptions::default()
90 }
91
92 pub fn nodelay(mut self, on: bool) -> TcpOptions {
94 self.nodelay = Some(on);
95 self
96 }
97
98 pub fn keepalive(mut self, k: Keepalive) -> TcpOptions {
100 self.keepalive = Some(k);
101 self
102 }
103
104 pub fn linger(mut self, l: Linger) -> TcpOptions {
106 self.linger = Some(l);
107 self
108 }
109
110 pub fn send_buffer(mut self, bytes: u32) -> TcpOptions {
112 self.send_buffer = Some(bytes);
113 self
114 }
115
116 pub fn receive_buffer(mut self, bytes: u32) -> TcpOptions {
118 self.receive_buffer = Some(bytes);
119 self
120 }
121
122 pub fn user_timeout(mut self, timeout: Duration) -> TcpOptions {
126 self.user_timeout = Some(timeout);
127 self
128 }
129
130 pub fn ttl(mut self, hops: u8) -> TcpOptions {
132 self.ttl = Some(hops);
133 self
134 }
135
136 pub(crate) fn apply<S: AsSock>(&self, socket: &S, v6: bool) -> Result<(), NetError> {
138 let sock = socket.sock();
139 let os = |op: &'static str| move |e| NetError::from_os(op, e);
140 if let Some(on) = self.nodelay {
141 sys::set_nodelay(sock, on).map_err(os("TCP_NODELAY"))?;
142 }
143 if let Some(k) = self.keepalive {
144 check_keepalive(&k)?;
145 sys::set_keepalive(sock, Some((k.idle, k.interval, k.count)))
146 .map_err(os("keepalive"))?;
147 }
148 if let Some(l) = self.linger {
149 sys::set_linger(sock, l.to_sys()).map_err(os("SO_LINGER"))?;
150 }
151 if let Some(n) = self.send_buffer {
152 sys::set_send_buffer(sock, n).map_err(os("SO_SNDBUF"))?;
153 }
154 if let Some(n) = self.receive_buffer {
155 sys::set_receive_buffer(sock, n).map_err(os("SO_RCVBUF"))?;
156 }
157 if let Some(t) = self.user_timeout {
158 sys::set_user_timeout(sock, t).map_err(|e| {
159 if e.kind() == std::io::ErrorKind::Unsupported {
160 NetError::Unsupported {
161 feature: "user_timeout",
162 platform: std::env::consts::OS,
163 }
164 } else {
165 NetError::from_os("TCP_USER_TIMEOUT", e)
166 }
167 })?;
168 }
169 if let Some(h) = self.ttl {
170 sys::set_ttl(sock, v6, h).map_err(os("IP_TTL"))?;
171 }
172 Ok(())
173 }
174
175 pub(crate) fn is_empty(&self) -> bool {
177 *self == TcpOptions::default()
178 }
179}
180
181fn check_keepalive(k: &Keepalive) -> Result<(), NetError> {
182 if cfg!(windows) && k.count > 255 {
183 return Err(NetError::InvalidConfig {
184 field: "keepalive",
185 reason: crate::error::ConfigReason::TooLarge { max: 255 },
186 });
187 }
188 if k.idle.is_zero() || k.interval.is_zero() || k.count == 0 {
189 return Err(NetError::InvalidConfig {
190 field: "keepalive",
191 reason: crate::error::ConfigReason::Zero,
192 });
193 }
194 Ok(())
195}
196
197#[must_use]
207#[derive(Clone, Copy, Debug, PartialEq, Eq)]
208pub struct ListenOptions {
209 pub(crate) backlog: u32,
210 pub(crate) reuse_address: bool,
211 pub(crate) reuse_port: bool,
212 pub(crate) ipv6_only: bool,
213 pub(crate) send_buffer: Option<u32>,
214 pub(crate) receive_buffer: Option<u32>,
215 pub(crate) defer_accept: Option<Duration>,
216 pub(crate) fast_open: Option<u32>,
217 pub(crate) incoming_cpu: Option<u32>,
218 pub(crate) per_worker: bool,
219 pub(crate) tcp: TcpOptions,
220}
221
222impl Default for ListenOptions {
223 fn default() -> ListenOptions {
224 ListenOptions {
225 backlog: 1024,
226 reuse_address: cfg!(unix),
227 reuse_port: false,
228 ipv6_only: true,
229 send_buffer: None,
230 receive_buffer: None,
231 defer_accept: None,
232 fast_open: None,
233 incoming_cpu: None,
234 per_worker: false,
235 tcp: TcpOptions::new().nodelay(true),
236 }
237 }
238}
239
240impl ListenOptions {
241 pub fn new() -> ListenOptions {
244 ListenOptions::default()
245 }
246
247 pub fn backlog(mut self, n: u32) -> ListenOptions {
249 self.backlog = n;
250 self
251 }
252
253 pub fn reuse_address(mut self, on: bool) -> ListenOptions {
255 self.reuse_address = on;
256 self
257 }
258
259 pub fn reuse_port(mut self, on: bool) -> ListenOptions {
261 self.reuse_port = on;
262 self
263 }
264
265 pub fn ipv6_only(mut self, on: bool) -> ListenOptions {
267 self.ipv6_only = on;
268 self
269 }
270
271 pub fn send_buffer(mut self, bytes: u32) -> ListenOptions {
273 self.send_buffer = Some(bytes);
274 self
275 }
276
277 pub fn receive_buffer(mut self, bytes: u32) -> ListenOptions {
279 self.receive_buffer = Some(bytes);
280 self
281 }
282
283 pub fn defer_accept(mut self, wait: Option<Duration>) -> ListenOptions {
288 self.defer_accept = wait;
289 self
290 }
291
292 pub fn fast_open(mut self, queue: Option<u32>) -> ListenOptions {
297 self.fast_open = queue;
298 self
299 }
300
301 pub fn incoming_cpu(mut self, cpu: Option<u32>) -> ListenOptions {
305 self.incoming_cpu = cpu;
306 self
307 }
308
309 pub fn per_worker(mut self, on: bool) -> ListenOptions {
317 self.per_worker = on;
318 self.reuse_port = self.reuse_port || on;
319 self
320 }
321
322 pub fn tcp_options(mut self, options: TcpOptions) -> ListenOptions {
324 self.tcp = options;
325 self
326 }
327
328 pub(crate) fn params(&self) -> sys::ListenParams {
329 sys::ListenParams {
330 reuse_address: self.reuse_address,
331 reuse_port: self.reuse_port,
332 ipv6_only: self.ipv6_only,
333 send_buffer: self.send_buffer,
334 receive_buffer: self.receive_buffer,
335 backlog: self.backlog,
336 defer_accept: self.defer_accept,
337 fast_open: self.fast_open,
338 incoming_cpu: self.incoming_cpu,
339 }
340 }
341}
342
343#[derive(Debug)]
355pub struct SocketOptions<'a> {
356 pub(crate) sock: sys::Sock<'a>,
357 pub(crate) v6: bool,
358}
359
360fn os(op: &'static str) -> impl Fn(std::io::Error) -> NetError {
361 move |e| NetError::from_os(op, e)
362}
363
364impl SocketOptions<'_> {
365 pub fn nodelay(&self) -> Result<bool, NetError> {
371 sys::nodelay(self.sock).map_err(os("TCP_NODELAY"))
372 }
373
374 pub fn set_nodelay(&self, on: bool) -> Result<(), NetError> {
380 sys::set_nodelay(self.sock, on).map_err(os("TCP_NODELAY"))
381 }
382
383 pub fn keepalive(&self) -> Result<Option<Keepalive>, NetError> {
389 Ok(sys::keepalive(self.sock)
390 .map_err(os("keepalive"))?
391 .map(|(idle, interval, count)| Keepalive {
392 idle,
393 interval,
394 count,
395 }))
396 }
397
398 pub fn set_keepalive(&self, k: Option<Keepalive>) -> Result<(), NetError> {
404 if let Some(k) = &k {
405 check_keepalive(k)?;
406 }
407 sys::set_keepalive(self.sock, k.map(|k| (k.idle, k.interval, k.count)))
408 .map_err(os("keepalive"))
409 }
410
411 pub fn linger(&self) -> Result<Linger, NetError> {
417 Ok(match sys::linger(self.sock).map_err(os("SO_LINGER"))? {
418 None => Linger::Off,
419 Some(d) if d.is_zero() => Linger::Abortive,
420 Some(d) => Linger::Timeout(d),
421 })
422 }
423
424 pub fn set_linger(&self, l: Linger) -> Result<(), NetError> {
430 sys::set_linger(self.sock, l.to_sys()).map_err(os("SO_LINGER"))
431 }
432
433 pub fn send_buffer(&self) -> Result<u32, NetError> {
439 sys::send_buffer(self.sock).map_err(os("SO_SNDBUF"))
440 }
441
442 pub fn set_send_buffer(&self, bytes: u32) -> Result<u32, NetError> {
448 sys::set_send_buffer(self.sock, bytes).map_err(os("SO_SNDBUF"))
449 }
450
451 pub fn receive_buffer(&self) -> Result<u32, NetError> {
457 sys::receive_buffer(self.sock).map_err(os("SO_RCVBUF"))
458 }
459
460 pub fn set_receive_buffer(&self, bytes: u32) -> Result<u32, NetError> {
466 sys::set_receive_buffer(self.sock, bytes).map_err(os("SO_RCVBUF"))
467 }
468
469 pub fn ttl(&self) -> Result<u8, NetError> {
475 sys::ttl(self.sock, self.v6).map_err(os("IP_TTL"))
476 }
477
478 pub fn set_ttl(&self, hops: u8) -> Result<(), NetError> {
484 sys::set_ttl(self.sock, self.v6, hops).map_err(os("IP_TTL"))
485 }
486}
487
488#[must_use]
496#[derive(Clone, Debug, PartialEq, Eq)]
497pub struct LocalOptions {
498 pub(crate) mode: u32,
499 pub(crate) owner: Option<u32>,
500 pub(crate) group: Option<u32>,
501 pub(crate) remove_stale: bool,
502 pub(crate) require_uid: Option<u32>,
503 pub(crate) backlog: u32,
504}
505
506impl Default for LocalOptions {
507 fn default() -> LocalOptions {
508 LocalOptions::new()
509 }
510}
511
512impl LocalOptions {
513 pub fn new() -> LocalOptions {
515 LocalOptions {
516 mode: 0o600,
517 owner: None,
518 group: None,
519 remove_stale: true,
520 require_uid: None,
521 backlog: 1024,
522 }
523 }
524
525 pub fn mode(mut self, mode: u32) -> LocalOptions {
527 self.mode = mode & 0o777;
528 self
529 }
530
531 pub fn owner(mut self, uid: u32) -> LocalOptions {
533 self.owner = Some(uid);
534 self
535 }
536
537 pub fn group(mut self, gid: u32) -> LocalOptions {
539 self.group = Some(gid);
540 self
541 }
542
543 pub fn group_access(mut self, gid: u32) -> LocalOptions {
545 self.group = Some(gid);
546 self.mode = 0o660;
547 self
548 }
549
550 pub fn remove_stale(mut self, on: bool) -> LocalOptions {
554 self.remove_stale = on;
555 self
556 }
557
558 pub fn require_uid(mut self, uid: u32) -> LocalOptions {
560 self.require_uid = Some(uid);
561 self
562 }
563
564 pub fn backlog(mut self, backlog: u32) -> LocalOptions {
566 self.backlog = backlog;
567 self
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574
575 #[test]
576 fn test_local_options_builders() {
577 let o = LocalOptions::new();
578 assert_eq!((o.mode, o.remove_stale, o.backlog), (0o600, true, 1024));
579 let o = o
580 .group_access(7)
581 .owner(3)
582 .require_uid(9)
583 .mode(0o1777)
584 .backlog(5);
585 assert_eq!(o.mode, 0o777);
586 assert_eq!(
587 (o.group, o.owner, o.require_uid),
588 (Some(7), Some(3), Some(9))
589 );
590 assert_eq!(LocalOptions::default(), LocalOptions::new());
591 }
592
593 #[test]
594 fn test_keepalive_zero_rejected() {
595 let k = Keepalive {
596 idle: Duration::ZERO,
597 interval: Duration::from_secs(1),
598 count: 1,
599 };
600 assert!(check_keepalive(&k).is_err());
601 assert!(check_keepalive(&Keepalive::DEFAULT).is_ok());
602 }
603
604 #[test]
605 fn test_listen_defaults() {
606 let o = ListenOptions::new();
607 assert_eq!(o.backlog, 1024);
608 assert!(o.ipv6_only);
609 assert_eq!(o.reuse_address, cfg!(unix));
610 assert_eq!(o.tcp.nodelay, Some(true));
611 }
612
613 #[test]
614 fn test_tcp_options_is_empty() {
615 assert!(TcpOptions::new().is_empty());
616 assert!(!TcpOptions::new().ttl(5).is_empty());
617 }
618}