Skip to main content

sipx_call/
lib.rs

1//! Calls: dialogs, INVITE with SDP offer/answer, and the media that results.
2//!
3//! This is the layer where the signalling and the media stacks meet. The join is narrower than
4//! it looks: SDP negotiation decides an address, a port and a codec, and everything else about
5//! media follows from those three.
6//!
7//! The ordering constraint worth knowing is that an SDP offer has to name the port audio will
8//! arrive on, and only a bound socket knows that port. So the media socket is bound *before*
9//! the INVITE is sent, not after the answer comes back.
10//!
11//! # Stability
12//!
13//! sipx is pre-1.0, so **neither word below means frozen**. `1.0.0` is what freezes an API, and its
14//! predicates are in `docs/roadmap.md`. Until then:
15//!
16//! - **Supported** — meant to be depended on. Breaking changes get a `CHANGELOG.md` entry saying what
17//!   to do instead. New enum variants and new struct fields may still appear in a minor release, so a
18//!   downstream `match` should carry a `_` arm.
19//! - **Experimental** — may change shape or be removed without a migration note. Depend on it only if
20//!   you are prepared to follow it.
21//!
22//!
23//! **Supported**: the call lifecycle — dial, answer, early dialogs, hold and resume, both transfer
24//! flavours, DTMF, playback, recording, session timers — plus the bounded generic load scheduler
25//! in [`load`]. Initial request/response extension fields are validated `sipx-sip` headers supplied
26//! by the owning application; stack-owned field policy remains the application's responsibility.
27//!
28//! **Experimental**: choosing what a call offers — [`CodecPreference`], [`Codecs`], [`IcePolicy`],
29//! [`Keying`], [`MediaPolicy`], [`MediaProfile`], [`MediaAddress`],
30//! [`OutboundIdentityPolicy`], [`InboundIdentityPolicy`],
31//! the bounded inbound event [`Notifier`], outbound [`EventSubscriptions`] and bidirectional
32//! publication [`Publications`] runtimes,
33//! the two-dialog ownership and relay surface in [`coupling`],
34//! [`DialOptions::with_codecs`], [`DialOptions::with_initial_direction`],
35//! [`DialOptions::with_media_policy`],
36//! [`DialOptions::with_identity`], [`Dispatcher::with_identity`], and the answering entry
37//! points that take a selection, policy, or independent media addresses ([`answer_at`],
38//! [`answer_with`], [`answer_with_policy`], [`answer_with_policy_at`],
39//! [`answer_ringing_with`], [`answer_ringing_with_policy`], [`answer_replacing_with`],
40//! [`Invitation::answer_with`], [`Invitation::answer_with_policy`], [`ring_early_with`],
41//! [`ring_early_with_policy`], [`ring_offer_early`], [`ring_offer_early_with_policy`] and
42//! [`dial_early_without_offer`]). These choices are pre-1.0 and their shape may still move.
43//! Confirmed-dialog persistence is Experimental too: [`Call::dialog_snapshot`],
44//! [`Call::restore_dialog`], [`DialogSnapshot`] and [`DialogRestoreContext`] expose a versioned
45//! boundary whose schema remains deliberately narrower than a serialized `Call`.
46//!
47//! The set is the G.711 pair unless a call says otherwise. An application may provide an exact
48//! non-empty order with [`Codecs::ordered`], including mono L16; selecting Opus is a typed error
49//! unless this crate is built with its `opus` feature, which links libopus.
50//! [`MediaProfile::BrowserAudio`] is the fail-closed composition of WSS, ICE, DTLS-SRTP,
51//! multiplexed RTCP, and that required audio vocabulary. It is one bounded audio endpoint profile,
52//! not a browser API or a general WebRTC compatibility claim.
53//!
54//! Absent rather than experimental, so that nobody looks for it: a signalling-only coupling that
55//! leaves media endpoint-owned (`C-7`), and **multi-party** call bridging or conferencing. A
56//! [`Coupling`] can own two calls and attach a bounded media bridge, but `Call` does not expose its
57//! `MediaSession` for arbitrary application-side mixing.
58//!
59//! [`Error`] is `#[non_exhaustive]`: additive diagnostics stay additive for downstream callers, so
60//! a `match` over it carries a `_` arm.
61
62pub mod call;
63pub mod counters;
64pub mod coupling;
65pub mod dialog;
66pub mod dispatch;
67pub mod error;
68pub mod event;
69pub mod extension;
70pub mod identity;
71pub mod load;
72mod media_policy;
73pub mod notifier;
74pub mod publication;
75pub mod rel;
76mod signalling;
77mod snapshot;
78pub mod subscriber;
79pub mod transfer;
80// Crate-private: every item in it is `pub(crate)`, and a `pub mod` whose contents are all
81// private renders as an empty page in the API reference — a promise of surface that is not there.
82mod update;
83
84pub use call::{
85    Call, Credentials, DialOptions, Dialing, MediaAddress, answer, answer_at, answer_early,
86    answer_replacing, answer_replacing_with, answer_ringing, answer_ringing_with,
87    answer_ringing_with_policy, answer_ringing_with_policy_at, answer_with, answer_with_policy,
88    answer_with_policy_and_headers, answer_with_policy_and_headers_at, answer_with_policy_at, dial,
89    dial_early, dial_early_until, dial_early_without_offer, dial_once, dial_until, serve,
90};
91pub use counters::SignallingCounts;
92pub use coupling::{
93    CancelAction, ConfirmedCoupling, Coupling, CouplingEnd, CouplingState, EarlyCoupling,
94    FailureAction, Leg, OfferAction, OfferAxis,
95};
96pub use dialog::{Dialog, DialogId, Role};
97pub use dispatch::{
98    Calls, DispatchCounts, Dispatched, Dispatcher, DrainProgress, DrainReport, Invitation,
99};
100pub use error::{Error, Result};
101pub use event::{CallEvent, CallEvents, EndCause};
102pub use extension::{ApplicationRequest, MAX_APPLICATION_BODY};
103pub use identity::{InboundIdentityPolicy, OutboundIdentityPolicy};
104pub use media_policy::{
105    CodecPreference, CodecSelectionError, Codecs, IcePolicy, Keying, MediaPolicy, MediaProfile,
106    NegotiatedKeying,
107};
108pub use notifier::{Notifier, NotifierCounts, NotifierHandle};
109pub use publication::{
110    AllowPublications, Publication, PublicationAuthorization, PublicationComposition,
111    PublicationConfig, PublicationCounts, PublicationError, Publications, PublicationsHandle,
112    ReplacePublicationState,
113};
114pub use rel::{
115    Ringing, ring, ring_early, ring_early_with, ring_early_with_policy, ring_early_with_policy_at,
116    ring_offer_early, ring_offer_early_with_policy, ring_offer_early_with_policy_at,
117};
118pub use signalling::{SignallingCall, SignallingEvent};
119pub use snapshot::{
120    DialogNotQuiescent, DialogPersistenceError, DialogRestoreContext, DialogSessionAction,
121    DialogSnapshot, MAX_FIELD_BYTES, MAX_ID_BYTES, MAX_ROUTES, MAX_SNAPSHOT_BYTES,
122    MAX_VARIABLE_BYTES,
123};
124pub use subscriber::{
125    EventNotification, EventSubscription, EventSubscriptionCounts, EventSubscriptionError,
126    EventSubscriptions, EventSubscriptionsHandle,
127};
128pub use transfer::{Referral, Replaces, Transfer, TransferState};