Skip to main content

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}