Skip to main content

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}