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