1use std::{net::SocketAddr, time::Duration};
2
3use socket2::Type as SockType;
4
5use crate::SocketFamily;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum UdpSocketType {
10 Dgram,
11 Raw,
12}
13
14impl UdpSocketType {
15 pub fn is_dgram(&self) -> bool {
17 matches!(self, UdpSocketType::Dgram)
18 }
19
20 pub fn is_raw(&self) -> bool {
22 matches!(self, UdpSocketType::Raw)
23 }
24
25 pub(crate) fn to_sock_type(&self) -> SockType {
27 match self {
28 UdpSocketType::Dgram => SockType::DGRAM,
29 UdpSocketType::Raw => SockType::RAW,
30 }
31 }
32}
33
34#[derive(Debug, Clone)]
36pub struct UdpConfig {
37 pub socket_family: SocketFamily,
39 pub socket_type: UdpSocketType,
41 pub bind_addr: Option<SocketAddr>,
43 pub reuseaddr: Option<bool>,
45 pub broadcast: Option<bool>,
47 pub ttl: Option<u32>,
49 pub hoplimit: Option<u32>,
51 pub read_timeout: Option<Duration>,
53 pub write_timeout: Option<Duration>,
55 pub bind_device: Option<String>,
57}
58
59impl Default for UdpConfig {
60 fn default() -> Self {
61 Self {
62 socket_family: SocketFamily::IPV4,
63 socket_type: UdpSocketType::Dgram,
64 bind_addr: None,
65 reuseaddr: None,
66 broadcast: None,
67 ttl: None,
68 hoplimit: None,
69 read_timeout: None,
70 write_timeout: None,
71 bind_device: None,
72 }
73 }
74}
75
76impl UdpConfig {
77 pub fn new() -> Self {
79 Self::default()
80 }
81
82 pub fn with_bind_addr(mut self, addr: SocketAddr) -> Self {
84 self.bind_addr = Some(addr);
85 self
86 }
87
88 pub fn with_reuseaddr(mut self, on: bool) -> Self {
90 self.reuseaddr = Some(on);
91 self
92 }
93
94 pub fn with_broadcast(mut self, on: bool) -> Self {
96 self.broadcast = Some(on);
97 self
98 }
99
100 pub fn with_ttl(mut self, ttl: u32) -> Self {
102 self.ttl = Some(ttl);
103 self
104 }
105
106 pub fn with_hoplimit(mut self, hops: u32) -> Self {
108 self.hoplimit = Some(hops);
109 self
110 }
111
112 pub fn with_read_timeout(mut self, timeout: Duration) -> Self {
114 self.read_timeout = Some(timeout);
115 self
116 }
117
118 pub fn with_write_timeout(mut self, timeout: Duration) -> Self {
120 self.write_timeout = Some(timeout);
121 self
122 }
123
124 pub fn with_bind_device(mut self, iface: impl Into<String>) -> Self {
126 self.bind_device = Some(iface.into());
127 self
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn udp_config_default_values() {
137 let cfg = UdpConfig::default();
138 assert!(cfg.bind_addr.is_none());
139 assert!(cfg.reuseaddr.is_none());
140 assert!(cfg.broadcast.is_none());
141 assert!(cfg.ttl.is_none());
142 assert!(cfg.bind_device.is_none());
143 }
144}