pub struct Engine<I: Instant, R> { /* private fields */ }Expand description
The runtime-agnostic mDNS engine.
Generic over the monotonic clock I (an mdns_proto::Instant) and the
RNG R; the storage pools are fixed to the alloc-tier slab backing.
Implementations§
Source§impl<I, R> Engine<I, R>
impl<I, R> Engine<I, R>
Sourcepub fn new(config: EndpointConfig, rng: R) -> Self
pub fn new(config: EndpointConfig, rng: R) -> Self
Create an engine from a proto-layer config and an RNG (used for probe tiebreak seeds and query transaction ids).
Sourcepub fn set_local_subnets(&mut self, subnets: Vec<IpCidr>)
pub fn set_local_subnets(&mut self, subnets: Vec<IpCidr>)
Set the device’s local subnets — the RFC 6762 §11 on-link heuristic used when
the transport cannot surface the received hop-limit (neither supplied transport
can; smoltcp’s UdpMetadata carries no RX TTL).
OPTIONAL. With no subnets configured the §11 gate accepts every inbound mDNS datagram (the groups are link-scoped multicast routers do not forward, so it is on-link by IP design) rather than dropping all of it and going deaf. Configure the device’s own subnets to additionally REJECT sources outside them — a best-effort defence against a same-link host spoofing on-link traffic.
Sourcepub fn register_service(
&mut self,
spec: ServiceSpec,
now: I,
) -> Result<ServiceHandle, RegisterServiceError>
pub fn register_service( &mut self, spec: ServiceSpec, now: I, ) -> Result<ServiceHandle, RegisterServiceError>
Register a service. The proto state machine is owned by the engine and
driven by Self::pump; updates are read via Self::poll_service_update.
Sourcepub fn unregister_service(&mut self, handle: ServiceHandle, now: I)
pub fn unregister_service(&mut self, handle: ServiceHandle, now: I)
Unregister a service, beginning its RFC 6762 §10.1 endpoint-owned
withdrawal. The endpoint KEEPS the route (holding the name against a
same-name re-registration) and drives the TTL=0 goodbye resend schedule;
Self::pump pumps each due goodbye datagram and, on completion, frees the
route and GCs the driver slot.
The withdrawal covers whatever the service must retract: the records it
confirmed-emitted under its current name (host A/AAAA filtered against
same-host siblings by the endpoint), AND — if a conflict rename left an
old-name withdrawal still pending — that old instance name too, in the SAME
goodbye (Service::withdrawal_snapshot captures both). A never-announced
service has an empty snapshot and completes on the next pump with no
datagram on the wire.
The driver slot is NOT removed here: it is kept (marked errored) so any
already-queued ServiceUpdate::Conflict still reaches the host, and is GC’d
when the endpoint reports the withdrawal complete.
Sourcepub fn start_query(
&mut self,
spec: QuerySpec,
now: I,
) -> Result<QueryHandle, StartQueryError>
pub fn start_query( &mut self, spec: QuerySpec, now: I, ) -> Result<QueryHandle, StartQueryError>
Start a query. Updates are read via Self::poll_query_update.
Sourcepub fn cancel_query(&mut self, handle: QueryHandle)
pub fn cancel_query(&mut self, handle: QueryHandle)
Cancel a query and free its pool slot.
Sourcepub fn collected_answers(
&self,
handle: QueryHandle,
) -> impl Iterator<Item = &CollectedAnswer> + '_
pub fn collected_answers( &self, handle: QueryHandle, ) -> impl Iterator<Item = &CollectedAnswer> + '_
Iterate the answers a query has collected so far — the browse / discovery
results. Empty if handle is not an active query. Read this after any
Self::pump (or a Self::poll_query_update); the proto keeps a bounded
snapshot, so compare its length against Self::query_accepted_count to
detect answers the max_answers cap evicted before you read them.
Sourcepub fn query_accepted_count(&self, handle: QueryHandle) -> Option<u64>
pub fn query_accepted_count(&self, handle: QueryHandle) -> Option<u64>
Total answers ever accepted by a query (including ones the max_answers cap
has since evicted from Self::collected_answers). None if handle is not
an active query.
Sourcepub fn pump<T: UdpIo>(
&mut self,
now: I,
io: &mut T,
scratch: &mut [u8],
) -> Option<I>
pub fn pump<T: UdpIo>( &mut self, now: I, io: &mut T, scratch: &mut [u8], ) -> Option<I>
Step the engine once: fire due timers, drain all ready RX through the
§11 gate into the proto, surface service updates, drain all pending TX via
io, pump any due endpoint-owned withdrawal goodbyes, and return the next
deadline to sleep until.
Graceful shutdown. There is no separate flush path: unregister_service
begins each service’s endpoint-owned §10.1 withdrawal, and pump drives the
goodbye sends + frees the route on completion. To flush all pending
withdrawals before exiting, drive pump until Self::poll_deadline returns
None (no service, query, cache, or withdrawal deadline remains) — at which
point every withdrawal has completed (sent its budget or hit its 2 s anti-pin
ceiling) and its route is freed.
Sourcepub fn poll_deadline(&self) -> Option<I>
pub fn poll_deadline(&self) -> Option<I>
The earliest deadline across the endpoint, services, and queries.
Endpoint-owned withdrawal deadlines (the next due goodbye round and the
anti-pin ceiling) are already folded into Endpoint::poll_timeout, so the
driver no longer tracks them here.
Sourcepub fn poll_service_update(
&mut self,
handle: ServiceHandle,
) -> Option<ServiceUpdate>
pub fn poll_service_update( &mut self, handle: ServiceHandle, ) -> Option<ServiceUpdate>
Pop one app-facing update for a registered service.
If this drains the LAST update of a slot whose endpoint-owned withdrawal has
already completed (route_freed), the slot is GC’d here — the deferred GC
that lets a retirement Conflict survive a withdrawal which completed in the
same pump that began it (see the ServiceSlot::route_freed field).
Sourcepub fn poll_query_update(&mut self, handle: QueryHandle) -> Option<QueryUpdate>
pub fn poll_query_update(&mut self, handle: QueryHandle) -> Option<QueryUpdate>
Pop one app-facing update for a query. A query the driver RETIRED (its
question is un-encodable, or permanently unsendable on every reachable
family) was forced to the proto’s TIMEOUT terminal when the driver retired it,
so it surfaces one QueryUpdate::Timeout here — the caller learns it died
(and can read Self::collected_answers, frozen, then cancel) instead of
waiting forever for a result it can never request.
Sourcepub fn poll_endpoint_event(&mut self) -> Option<EndpointEvent>
pub fn poll_endpoint_event(&mut self) -> Option<EndpointEvent>
Pop one endpoint-level event.