cotton_ssdp/
lib.rs

1//! Implementing SSDP, the Simple Service Discovery Protocol
2//!
3//! The cotton-ssdp crate encapsulates a client and server for the
4//! Simple Service Discovery Protocol (SSDP), a mechanism for
5//! discovering available _resources_ (services) on local networks. A
6//! _resource_ might be a streaming-media server, or a router, or a
7//! network printer, or anything else that someone might want to
8//! search for or enumerate on a network.
9//!
10//! What is advertised, or discovered, is, for each resource, a unique
11//! identifier for that particular resource (Unique Service Name,
12//! USN), an identifier for the _type_ of resource (Notification Type,
13//! NT), and the _location_ of the resource in the form of a URL.
14//!
15//! SSDP is mainly used by UPnP (Universal Plug-'n'-Play) systems,
16//! such as for media libraries and local streaming of music and video
17//! -- but the mechanism is quite generic, and could as easily be used
18//! for any type of device or resource that must be discoverable over
19//! a network, including in *ad hoc* settings which don't necessarily
20//! have expert network administrators close at hand.
21//!
22//! There is no Internet RFC as such for SSDP -- merely some expired
23//! drafts.  The protocol is, instead, documented in the [UPnP Device
24//! Architecture](https://openconnectivity.org/developer/specifications/upnp-resources/upnp/archive-of-previously-published-upnp-device-architectures/)
25//! documents.
26//!
27//! This crate provides two different high-level interfaces for
28//! working with SSDP, [`Service`] and [`AsyncService`]. Either one can
29//! be used both to discover other devices ([`Service::subscribe`])
30//! and to advertise resources itself ([`Service::advertise`]).
31//!
32//! Client code using the MIO crate should use plain [`Service`];
33//! client code using the Tokio crate might wish to use
34//! [`AsyncService`] instead, which integrates with that
35//! system. Client code with a _custom_ polling loop -- neither MIO
36//! nor Tokio -- should instead probably aim to build an equivalent to
37//! [`Service`] using the lower-level facilities in
38//! [`engine::Engine`].
39//!
40//! Example code is available both for asynchronous Tokio use:
41//! [ssdp-search](https://github.com/pdh11/cotton/blob/main/cotton-ssdp/examples/ssdp-search.rs)
42//! (on Github) and reactor-style MIO use:
43//! [ssdp-search-mio](https://github.com/pdh11/cotton/blob/main/cotton-ssdp/examples/ssdp-search-mio.rs)
44//! (on Github).
45//!
46//! Todo:
47//!  - [x] Make mio/tokio features
48//!  - [ ] Make advertise/subscribe features
49//!  - [ ] `Cow<'static>` for input strings?
50//!  - [ ] Hasher instead of `thread_rng`; hash over network interfaces sb unique
51//!  - [ ] Vary phase 1,2,3 timings but keep phase 0 timings on round numbers (needs _absolute_ wall time)
52//!  - [x] Monotonic time instead of `Instant::now` (lifetime?) *Solved differently*
53//!  - [x] `smoltcp`/`no_std`, see <https://github.com/rust-lang/rust/pull/104265>
54//!  - [ ] IPv6, see UPnP DA appendix A
55//!
56
57#![cfg_attr(not(feature = "std"), no_std)]
58#![warn(missing_docs)]
59#![warn(rustdoc::missing_crate_level_docs)]
60#![cfg_attr(docsrs, feature(doc_auto_cfg))]
61#![cfg_attr(docsrs, feature(doc_cfg_hide))]
62#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
63
64// NB "docsrs" here really means "nightly", but that isn't an available cfg
65
66extern crate alloc;
67
68#[cfg(feature = "async")]
69mod async_service;
70
71/// Low-level SSDP API used inside [`Service`] and [`AsyncService`]
72pub mod engine;
73
74/// Inbound and outbound SSDP events, high-level
75pub mod event;
76
77mod message;
78
79#[cfg(feature = "sync")]
80mod service;
81
82/// Traits used to abstract over various UDP socket implementations
83pub mod udp;
84
85/// Common code for triggering refreshes of [`Service`] and [`AsyncService`]
86pub mod refresh_timer;
87
88#[cfg(feature = "async")]
89pub use async_service::AsyncService;
90
91#[cfg(feature = "sync")]
92pub use service::Service;
93
94pub use event::Advertisement;
95pub use event::Notification;