rtsp-runtime
Sans-IO RTSP 1.0 (RFC 2326) session engine — a driveable client and server, the piece the Rust ecosystem leaves out.
Message parse/serialize is delegated to the mature rtsp-types and
sdp-types codecs, and authentication (Basic/Digest/Bearer) to the shared
broadcast-auth crate (which itself wraps http-auth
for Basic/Digest) — extracted so RTSP and HTTP clients (e.g. multimux's
HTTP input adapters) share one auth implementation instead of duplicating
it. What lives here is the part nothing else provides:
- Session state machines —
ClientSessionandServerSession, per RFC 2326 Appendix A (Init → Ready → Playing/Recording), with illegal-method-in-state rejection (the client returnsErr; the server returns455 Method Not Valid In This State). - CSeq correlation — outbound requests carry an incrementing
CSeq; inbound responses are matched back to the pending request. Transportnegotiation — a typed, round-trippableTransportheader (§12.39): UDP unicast/multicast and TCP-interleaved.- Interleaved RTP/RTCP framing —
InterleavedFrameand a streaming demultiplexer for the$-channel muxing of §10.12 (complete frames + partial tail). - Auth — Basic + Digest (RFC 7617 / 7616), plus Bearer (RFC 6750),
wired into request signing via
broadcast-auth, including transparent401retry andstale=truenonce refresh, for the authenticated RTSP that IP cameras require.
All sans-IO: feed inbound bytes, get outbound bytes and typed events back —
no sockets in the core. Drive ClientSession with the request builders and
handle_data; drive ServerSession with handle_request.
- Async socket adapter (feature
tokio) —AsyncRtspClient/AsyncRtspServeraretokio_util::codec::Framedadapters over the sans-IO engine: the codec reassembles fragmented reads (one deadline per whole frame, 64 KiB header / 2 MiB message caps), and Digest401challenges are answered transparently. Every awaited IO is bounded byRtspTimeouts(connect / handshake / read_idle / write), andrecv_interleavedsends theGET_PARAMETERkeepalive at half theSessiontimeout. Both are generic over the stream type, so the same driver logic runs over plain TCP and TLS. rtsps://over TLS (featuretls) — the adapter wraps the stream in atokio-rustlssession before the RTSP exchange (AsyncRtspClient::connect_tls/AsyncRtspServer::accept_tls), forrtsps://on default port 322. The client trusts thewebpki-rootsbundle by default, or a customrustls::ClientConfigfor a self-signed camera cert.
[]
= "0.7" # sans-IO core
= { = "0.7", = ["tokio"] } # + real sockets
= { = "0.7", = ["tls"] } # + rtsps:// (TLS)
Status
The sans-IO core — client + server state machines, Transport negotiation,
interleaved framing, and Basic/Digest auth — is implemented and tested against
the RFC 2326 fixtures (see issue #521).
The tokio socket adapter (and tls for rtsps://) is implemented on top of
the same core, with real-loopback integration tests covering a full
OPTIONS→DESCRIBE→SETUP→PLAY→TEARDOWN session, fragmented interleaved media,
transparent Digest auth, and an end-to-end TLS handshake with a self-signed
cert.
License
MIT OR Apache-2.0.
Header parsing and rtsp-types gaps
Transport (RFC 2326 §12.39) and Session (§12.37) are parsed and serialized by this crate
(transport, session_header, one shared RFC 2326 §15.1 lexer), not by rtsp-types 0.1.3,
which is exact-case, does not trim whitespace, drops case-variant parameters and rejects a
quoted ssrc / malformed timeout. The probe table, for a future upstream issue, is in
docs/transport-header.md.