rtc_mdns/config.rs
1//! MdnsConfiguration for mDNS connections.
2//!
3//! This module provides the [`MdnsConfig`] struct for configuring mDNS client and server behavior.
4//!
5//! # Examples
6//!
7//! ## Client MdnsConfiguration
8//!
9//! For a client that only sends queries:
10//!
11//! ```rust
12//! use rtc_mdns::MdnsConfig;
13//! use std::time::Duration;
14//!
15//! let config = MdnsConfig::default()
16//! .with_query_interval(Duration::from_millis(500)); // Retry every 500ms
17//! ```
18//!
19//! ## Server MdnsConfiguration
20//!
21//! For a server that responds to queries:
22//!
23//! ```rust
24//! use rtc_mdns::MdnsConfig;
25//! use std::net::{IpAddr, Ipv4Addr};
26//!
27//! let config = MdnsConfig::default()
28//! .with_local_names(vec![
29//! "mydevice.local".to_string(),
30//! "mydevice._http._tcp.local".to_string(),
31//! ])
32//! .with_local_ip(
33//! IpAddr::V4(Ipv4Addr::new(192, 168, 1, 100)),
34//! );
35//! ```
36//!
37//! ## Combined Client/Server
38//!
39//! For a connection that both queries and responds:
40//!
41//! ```rust
42//! use rtc_mdns::MdnsConfig;
43//! use std::net::{IpAddr, Ipv4Addr};
44//! use std::time::Duration;
45//!
46//! let config = MdnsConfig::default()
47//! .with_query_interval(Duration::from_secs(1))
48//! .with_local_names(vec!["myhost.local".to_string()])
49//! .with_local_ip(
50//! IpAddr::V4(Ipv4Addr::new(192, 168, 1, 50)),
51//! );
52//! ```
53
54use std::net::IpAddr;
55use std::time::Duration;
56
57/// Default interval between query retries (1 second)
58pub(crate) const DEFAULT_QUERY_INTERVAL: Duration = Duration::from_secs(1);
59
60/// Default query timeout (None - queries never timeout automatically)
61///
62/// Set a timeout using [`MdnsConfig::with_query_timeout`] to have queries
63/// automatically emit [`MdnsEvent::QueryTimeout`](crate::MdnsEvent::QueryTimeout) events.
64pub(crate) const DEFAULT_QUERY_TIMEOUT: Option<Duration> = None;
65
66/// Maximum number of DNS records to process per message section
67///
68/// This limits processing to prevent excessive CPU usage on malformed packets.
69pub(crate) const MAX_MESSAGE_RECORDS: usize = 3;
70
71/// Default TTL (Time To Live) for mDNS response records (120 seconds)
72pub(crate) const RESPONSE_TTL: u32 = 120;
73
74/// MdnsConfiguration for an mDNS connection.
75///
76/// Use the builder pattern to construct a configuration:
77///
78/// ```rust
79/// use rtc_mdns::MdnsConfig;
80/// use std::time::Duration;
81///
82/// let config = MdnsConfig::new()
83/// .with_query_interval(Duration::from_millis(500))
84/// .with_local_names(vec!["myhost.local".to_string()]);
85/// ```
86///
87/// # Fields
88///
89/// - `query_interval`: How often to retry unanswered queries (default: 1 second)
90/// - `query_timeout`: Maximum time to wait for a query answer (default: None - no timeout)
91/// - `local_names`: Names this connection will respond to (empty by default)
92/// - `local_addr`: IP address to advertise in responses (required for server mode)
93#[derive(Clone, Debug)]
94pub struct MdnsConfig {
95 /// How often to retry unanswered queries.
96 ///
97 /// When a query is started, it will be retried at this interval until
98 /// either an answer is received or the query is cancelled.
99 ///
100 /// Default: 1 second
101 ///
102 /// # Example
103 ///
104 /// ```rust
105 /// use rtc_mdns::MdnsConfig;
106 /// use std::time::Duration;
107 ///
108 /// // Retry queries every 500ms for faster discovery
109 /// let config = MdnsConfig::default()
110 /// .with_query_interval(Duration::from_millis(500));
111 /// ```
112 pub query_interval: Duration,
113
114 /// Maximum time to wait for a query to be answered.
115 ///
116 /// When set, queries that haven't received an answer within this duration
117 /// will emit [`MdnsEvent::QueryTimeout`](crate::MdnsEvent::QueryTimeout) and
118 /// be automatically cancelled.
119 ///
120 /// When `None`, queries will retry indefinitely until answered or
121 /// manually cancelled.
122 ///
123 /// Default: None (no automatic timeout)
124 ///
125 /// # Example
126 ///
127 /// ```rust
128 /// use rtc_mdns::MdnsConfig;
129 /// use std::time::Duration;
130 ///
131 /// // Timeout queries after 5 seconds
132 /// let config = MdnsConfig::default()
133 /// .with_query_timeout(Duration::from_secs(5));
134 /// ```
135 pub query_timeout: Option<Duration>,
136
137 /// Local names that this connection will respond to.
138 ///
139 /// When an mDNS query arrives for any of these names, the connection
140 /// will automatically generate a response with the configured `local_addr`.
141 ///
142 /// Names should be in `.local` format (e.g., `"myhost.local"`).
143 /// Trailing dots are optional and will be normalized internally.
144 ///
145 /// Default: empty (no names to respond to)
146 ///
147 /// # Example
148 ///
149 /// ```rust
150 /// use rtc_mdns::MdnsConfig;
151 ///
152 /// let config = MdnsConfig::default()
153 /// .with_local_names(vec![
154 /// "mydevice.local".to_string(),
155 /// "printer.local".to_string(),
156 /// ]);
157 /// ```
158 pub local_names: Vec<String>,
159
160 /// Local address to advertise in mDNS responses.
161 ///
162 /// This IP address will be included in A record responses when
163 /// queries for `local_names` are received.
164 ///
165 /// **Required** if `local_names` is non-empty, otherwise responses
166 /// cannot be generated.
167 ///
168 /// Default: None
169 ///
170 /// # Example
171 ///
172 /// ```rust
173 /// use rtc_mdns::MdnsConfig;
174 /// use std::net::{IpAddr, Ipv4Addr};
175 ///
176 /// let config = MdnsConfig::default()
177 /// .with_local_names(vec!["myhost.local".to_string()])
178 /// .with_local_ip(
179 /// IpAddr::V4(Ipv4Addr::new(192, 168, 1, 42)),
180 /// );
181 /// ```
182 pub local_ip: Option<IpAddr>,
183}
184
185impl Default for MdnsConfig {
186 fn default() -> Self {
187 Self {
188 query_interval: DEFAULT_QUERY_INTERVAL,
189 query_timeout: DEFAULT_QUERY_TIMEOUT,
190 local_names: Vec::new(),
191 local_ip: None,
192 }
193 }
194}
195
196impl MdnsConfig {
197 /// Create a new configuration with default values.
198 ///
199 /// Equivalent to [`MdnsConfig::default()`].
200 ///
201 /// # Example
202 ///
203 /// ```rust
204 /// use rtc_mdns::MdnsConfig;
205 ///
206 /// let config = MdnsConfig::new();
207 /// ```
208 pub fn new() -> Self {
209 Self::default()
210 }
211
212 /// Set the query retry interval.
213 ///
214 /// Queries will be retried at this interval until answered or cancelled.
215 /// A value of zero will use the default interval (1 second).
216 ///
217 /// # Arguments
218 ///
219 /// * `interval` - Duration between query retries
220 ///
221 /// # Example
222 ///
223 /// ```rust
224 /// use rtc_mdns::MdnsConfig;
225 /// use std::time::Duration;
226 ///
227 /// let config = MdnsConfig::default()
228 /// .with_query_interval(Duration::from_millis(250));
229 /// ```
230 pub fn with_query_interval(mut self, interval: Duration) -> Self {
231 self.query_interval = interval;
232 self
233 }
234
235 /// Set the query timeout.
236 ///
237 /// When set, queries that don't receive an answer within this duration
238 /// will emit [`MdnsEvent::QueryTimeout`](crate::MdnsEvent::QueryTimeout)
239 /// and be automatically removed from the pending list.
240 ///
241 /// # Arguments
242 ///
243 /// * `timeout` - Maximum duration to wait for a query answer
244 ///
245 /// # Example
246 ///
247 /// ```rust
248 /// use rtc_mdns::MdnsConfig;
249 /// use std::time::Duration;
250 ///
251 /// // Queries will timeout after 5 seconds
252 /// let config = MdnsConfig::default()
253 /// .with_query_timeout(Duration::from_secs(5));
254 ///
255 /// // Combined with retry interval: retry every 500ms, give up after 3s
256 /// let config = MdnsConfig::default()
257 /// .with_query_interval(Duration::from_millis(500))
258 /// .with_query_timeout(Duration::from_secs(3));
259 /// ```
260 pub fn with_query_timeout(mut self, timeout: Duration) -> Self {
261 self.query_timeout = Some(timeout);
262 self
263 }
264
265 /// Set the local names to respond to.
266 ///
267 /// When mDNS queries for these names are received, the connection
268 /// will automatically generate responses with the configured `local_addr`.
269 ///
270 /// # Arguments
271 ///
272 /// * `names` - List of hostnames (e.g., `["myhost.local"]`)
273 ///
274 /// # Example
275 ///
276 /// ```rust
277 /// use rtc_mdns::MdnsConfig;
278 ///
279 /// let config = MdnsConfig::default()
280 /// .with_local_names(vec!["server.local".to_string()]);
281 /// ```
282 pub fn with_local_names(mut self, names: Vec<String>) -> Self {
283 self.local_names = names;
284 self
285 }
286
287 /// Set the local address to advertise in responses.
288 ///
289 /// This address will be included in A record responses. The port
290 /// is typically 5353 for mDNS.
291 ///
292 /// # Arguments
293 ///
294 /// * `addr` - Socket address containing the IP to advertise
295 ///
296 /// # Example
297 ///
298 /// ```rust
299 /// use rtc_mdns::MdnsConfig;
300 /// use std::net::{IpAddr, Ipv4Addr};
301 ///
302 /// let config = MdnsConfig::default()
303 /// .with_local_ip(
304 /// IpAddr::V4(Ipv4Addr::new(10, 0, 0, 5)),
305 /// );
306 /// ```
307 pub fn with_local_ip(mut self, local_ip: IpAddr) -> Self {
308 self.local_ip = Some(local_ip);
309 self
310 }
311}