Expand description
§rtsp-runtime
Sans-IO RTSP 1.0 (RFC 2326) session engine: a driveable client and a server state machine, Transport negotiation, interleaved RTP/RTCP framing and authenticated requests. An optional tokio adapter (and tls for rtsps://) puts it on real sockets.
[dependencies]
rtsp-runtime = "0.8" # sans-IO core
rtsp-runtime = { version = "0.8", features = ["tokio"] } # + real sockets
rtsp-runtime = { version = "0.8", features = ["tls"] } # + rtsps:// (TLS)§What it does / what it does not
Does: run the RFC 2326 Appendix A session state machines (Init, Ready, Playing, Recording) on both sides; build outbound requests (OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN, ANNOUNCE, RECORD, GET_PARAMETER) with an incrementing CSeq and match responses back to them; parse and serialize the Transport (§12.39) and Session (§12.37) headers; frame and de-frame $-channel interleaved RTP/RTCP (§10.12); answer 401 challenges with Basic, Digest or Bearer credentials, including stale=true nonce refresh; and manage the keepalive timeout. The server rejects a method that is illegal in the current state with 455, allocates a Session id on SETUP (from a caller-supplied CSPRNG), and echoes the first offered transport.
Does not: open sockets in the core (feed bytes in, get bytes and events out), parse RTP or RTCP payloads (use rtp-packet and rtcp-packet), parse SDP (use sdp-types), generate DESCRIBE SDP or challenge clients on the server side (the server session has no authentication; put a broadcast-auth Verifier in your own layer), or speak RTSP 2.0 (RFC 7826 is vendored but not implemented). The client has no SET_PARAMETER builder, and server-initiated REDIRECT is not modelled.
Typical users: IP-camera ingest (multimux’s RTSP input), RTSP push to a media server, test servers, and tools that need to drive a camera session deterministically.
§Standards supported
| Standard | Edition | Scope | Status | Notes |
|---|---|---|---|---|
| IETF RFC 2326 “Real Time Streaming Protocol” | RFC 2326 (vendored specs/rfc2326_rtsp.txt, transcribed in docs/rfc2326.md) | Appendix A state machines, §10 methods listed above, §10.12 interleaved framing, §12.37 Session, §12.39 Transport, §14 authentication, CSeq (§12.17) | Partial | See the methods table below |
| IETF RFC 7826 “RTSP 2.0” | RFC 7826 (vendored, not implemented) | n/a | Not implemented | |
| IETF RFC 7617 / RFC 7616 / RFC 6750 (Basic, Digest, Bearer) | not vendored, unverified here | Client side via broadcast-auth | Full | Server side has no authentication |
| IETF RFC 8866 (SDP) | RFC 8866 (vendored) | Bodies carried opaque | Typed-opaque | Parse with sdp-types |
| IETF RFC 3550 (RTP/RTCP) | RFC 3550 | Interleaved payload is carried as bytes | Typed-opaque | Decode with rtp-packet / rtcp-packet |
rtsps:// (RTSP over TLS, default port 322) | n/a | Client connect_tls, server accept_tls | Full, behind tls | webpki-roots trust by default or a custom rustls::ClientConfig |
| Method | Client builds | Server session handles | State effect |
|---|---|---|---|
| OPTIONS, DESCRIBE, GET_PARAMETER, ANNOUNCE | yes | accepted, empty 200 | none |
| SET_PARAMETER | no builder | accepted as state-neutral, empty 200 | none |
| SETUP | yes | allocates Session, echoes transport | Init to Ready |
| PLAY, PAUSE, RECORD, TEARDOWN | yes | accepted, requires Session | Ready/Playing/Recording per Appendix A |
| REDIRECT | no | not modelled (a client resets to Init on a 3xx) | n/a |
§Features
| Feature | Default | Description |
|---|---|---|
serde | no | Serialize on the public wire and event types. |
tokio | no | AsyncRtspClient / AsyncRtspServer (tokio_util Framed adapters; 64 KiB header and 2 MiB message caps; RtspTimeouts; keepalive at half the session timeout). |
tls | no | Implies tokio; adds rtsps:// via tokio-rustls. |
The core is std and uses no async runtime. The crate has #![forbid(unsafe_code)].
§Quick start
A client talking to a server entirely in memory (no socket):
use rtsp_runtime::{
ClientEvent, ClientSession, InterleavedFrame, ServerSession, SessionState, Transport,
TransportSpec,
};
let url = "rtsp://127.0.0.1/stream";
let track = "rtsp://127.0.0.1/stream/trackID=0";
// A fixed id is fine here; a real server must draw ids from a CSPRNG.
let mut server = ServerSession::new(|| 0x0123_4567_89ab_cdef);
let mut client = ClientSession::new();
let req = client.options(url).unwrap();
let (resp, _) = server.handle_request(&req).unwrap();
client.handle_data_strict(&resp).unwrap();
let transport = Transport::single(TransportSpec::rtp_avp_tcp_interleaved(0, 1));
let req = client.setup(track, &transport).unwrap();
let (resp, _) = server.handle_request(&req).unwrap();
client.handle_data_strict(&resp).unwrap();
assert_eq!(client.state(), SessionState::Ready);
assert!(client.session_id().is_some());
let req = client.play(url).unwrap();
let (resp, _) = server.handle_request(&req).unwrap();
client.handle_data_strict(&resp).unwrap();
assert_eq!(client.state(), SessionState::Playing);
// While playing, RTP is tunnelled on interleaved channel 0 over the same connection.
let rtp = [0x80, 0x60, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0, 1, 0xde, 0xad];
let wire = InterleavedFrame::slice_to_bytes(0, &rtp).unwrap();
let events = client.handle_data_strict(&wire).unwrap();
assert!(matches!(&events[0], ClientEvent::MediaData { channel: 0, data } if data == &rtp));
let req = client.teardown(url).unwrap();
let (resp, _) = server.handle_request(&req).unwrap();
client.handle_data_strict(&resp).unwrap();
assert_eq!(client.state(), SessionState::Init);Runnable programs: client_server_loopback and transport_and_framing (cargo run -p rtsp-runtime --example <name>).
§What is implemented
ClientSession: request builders,handle_data(returnsHandleOutcome { events, error }so frames decoded before a terminal error are never lost) andhandle_data_strict;with_credentials;AuthRetryevents for401;poll_timeout/handle_timeoutkeepalive.ServerSession:handle_requestreturning response bytes plusServerEvents (RequestAccepted,MethodNotValid,SessionSetup,MediaData),with_session_timeout.Transport,TransportSpec,LowerTransport,Delivery,TransportMode: UDP unicast and multicast, TCP interleaved.SessionHeader:Sessionid andtimeout. Both are parsed by this crate over one RFC 2326 §15.1 lexer, becausertsp-types0.1 is exact-case and drops case-variant parameters (a documented, owner-approved exception to the no-hand-roll rule; probe table indocs/transport-header.md).InterleavedFrameand a streaming demultiplexer (complete frames plus a partial tail).CredentialsandAuthenticator, re-exported frombroadcast-auth.io(featuretokio):AsyncRtspClient,AsyncRtspServer,RtspTimeouts,RTSP_DEFAULT_PORT(554),RTSPS_DEFAULT_PORT(322).
§Design notes
Sans-IO: the core never reads a clock or a socket (the caller passes Instant for timeouts and supplies the session-id source). Error is #[non_exhaustive]. The Session id comparison is constant time. Message framing is bounded (header and message size caps). Tests include golden wire transcripts and real-loopback integration tests (OPTIONS to TEARDOWN, fragmented interleaved media, Digest, a TLS handshake with a self-signed certificate). A lexical no_handroll_guard test enforces the allowlist.
§Related crates
Builds on rtsp-types and sdp-types (codecs) and broadcast-auth. Pair with rtp-packet and rtcp-packet for the interleaved payloads. multimux uses it for RTSP input and push, and transmux for RTP depacketising.
§MSRV and licence
MSRV 1.95.0. Licensed under MIT OR Apache-2.0.
Re-exports§
pub use client::ClientEvent;pub use client::ClientSession;pub use client::HandleOutcome;pub use error::Error;pub use error::Result;pub use interleaved::InterleavedFrame;pub use io::AsyncRtspClient;tokiopub use io::AsyncRtspServer;tokiopub use io::RTSP_DEFAULT_PORT;tokiopub use io::RTSPS_DEFAULT_PORT;tokiopub use io::RtspTimeouts;tokiopub use server::ServerEvent;pub use server::ServerSession;pub use session_header::SessionHeader;pub use state::SessionState;pub use transport::Delivery;pub use transport::LowerTransport;pub use transport::Transport;pub use transport::TransportMode;pub use transport::TransportSpec;
Modules§
- auth
- Authentication wiring — RFC 2326 §14 (RTSP reuses HTTP auth).
- client
- Client-side RTSP session engine — RFC 2326 Appendix A.1.
- error
- Error types for the RTSP session engine.
- interleaved
- Interleaved (
$-framed) binary data — RFC 2326 §10.12. - io
tokio - Async real-socket IO adapter over the sans-IO engine — RFC 2326 transport.
- server
- Server-side RTSP session engine — RFC 2326 Appendix A.2.
- session_
header - Typed
Sessionheader — RFC 2326 §12.37 (docs/rfc2326.md,docs/session-header.md). - state
- RTSP session state machine — RFC 2326 Appendix A.
- transport
- Typed
Transportheader — RFC 2326 §12.39 (docs/rfc2326.md,docs/transport-header.md).
Structs§
- Authenticator
- Negotiates a challenge once, then answers every subsequent request in the
session (RFC 7235
WWW-Authenticate/Authorization; RFC 2326 §14 for RTSP; RFC 6750 for Bearer).
Enums§
- Credentials
- Credentials for one of the supported auth schemes.
- Method
- RTSP method.
- Status
Code - RTSP response status codes.
Constants§
- RFC
- The RFC this engine implements.