Skip to main content

sipx_sdp/
lib.rs

1//! SDP session descriptions (RFC 8866) and offer/answer negotiation (RFC 3264).
2//!
3//! Two things shape this crate.
4//!
5//! **Unknown lines survive.** SDP is extended constantly, and an element that drops what it
6//! does not understand breaks features it has never heard of. Parsing keeps every line; the
7//! typed accessors are a view over them, not a replacement.
8//!
9//! **Negotiation is a pure function.** [`answer()`] takes an offer and a set of capabilities and
10//! returns an answer — no sockets, no clock, no shared mutable session object. The rules in
11//! RFC 3264 are full of cases that are awkward to reach through a live call (a stream with no
12//! common codec, a `sendonly` that must become `recvonly`, a dynamic payload type that means
13//! different things at each end) and they are all one function call away here.
14//!
15//! # Stability
16//!
17//! sipx is pre-1.0, so **neither word below means frozen**. `1.0.0` is what freezes an API, and its
18//! predicates are in `docs/roadmap.md`. Until then:
19//!
20//! - **Supported** — meant to be depended on. Breaking changes get a `CHANGELOG.md` entry saying what
21//!   to do instead. New enum variants and new struct fields may still appear in a minor release, so a
22//!   downstream `match` should carry a `_` arm.
23//! - **Experimental** — may change shape or be removed without a migration note. Depend on it only if
24//!   you are prepared to follow it.
25//!
26//!
27//! **Supported.** This includes `with_dtls_srtp` and the ICE attribute helpers: `sipx-call`
28//! consumes both for explicit media policy in dial and answer roles (`M-27`, `M-28`).
29
30pub mod answer;
31pub mod browser_audio;
32pub mod crypto;
33pub mod fingerprint;
34pub mod ice;
35pub mod parse;
36pub mod rtpmap;
37pub mod session;
38
39pub use answer::{Capabilities, answer, negotiate_direction};
40pub use ice::{
41    Candidate, CandidateType, ComponentId, Credentials, Foundation, Pacing, Priority,
42    RelatedAddress, RemoteCandidate, Transport,
43};
44pub use parse::parse;
45pub use session::{
46    Address, Attribute, Connection, Direction, MediaDescription, Origin, RtcpMode,
47    SessionDescription, Timing,
48};
49
50/// What can go wrong reading SDP.
51#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
52#[non_exhaustive]
53pub enum SdpError {
54    /// A line was not `x=value`.
55    #[error("malformed line: {0}")]
56    MalformedLine(String),
57    /// A required line was missing.
58    #[error("missing the {0} line")]
59    Missing(&'static str),
60    /// A field did not parse.
61    #[error("invalid {field}: {value}")]
62    Invalid {
63        /// Which field.
64        field: &'static str,
65        /// What it contained.
66        value: String,
67    },
68}
69
70/// An SDP result.
71pub type Result<T> = std::result::Result<T, SdpError>;