1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! SIP signaling and RTP transport for voice pipelines.
//!
//! `wavekat-sip` is a small, focused toolkit for building softphones, voice
//! bots, and recording bridges in Rust. It wraps [`rsipstack`] and owns the
//! wire-level concerns — SIP registration, dialogs, SDP offer/answer, and
//! RTP framing — while staying out of audio device I/O, codec work, and
//! call orchestration so it remains light and embeddable.
//!
//! [`rsipstack`]: https://crates.io/crates/rsipstack
//!
//! # Scope
//!
//! What this crate covers:
//!
//! - **SIP signaling** — REGISTER with digest auth and keepalive
//! re-registration ([`Registrar`]), shared transport + dialog layer
//! ([`SipEndpoint`]).
//! - **SDP** — minimal G.711 (PCMU + PCMA) offer/answer with round-trip
//! parsing ([`build_sdp`], [`parse_sdp`]).
//! - **RTP** — header parser ([`RtpHeader`]) and a debug-friendly receive
//! loop ([`receive_rtp`]) suitable for transcription, recording, or
//! smoke-testing inbound media.
//!
//! Explicitly out of scope (push these to the consuming application):
//!
//! - Audio device I/O (e.g. `cpal`), codec encode/decode, jitter buffering,
//! recording, WAV writing.
//! - Account persistence (TOML files, system keychain).
//! - Call orchestration, AI pipeline, business logic.
//!
//! See the [roadmap](https://github.com/wavekat/wavekat-sip/blob/main/docs/01-port-plan.md)
//! for the planned `caller` / `callee` INVITE wrappers and RTP send helper.
//!
//! # Quick start: register against a SIP server
//!
//! ```no_run
//! use std::sync::Arc;
//! use tokio_util::sync::CancellationToken;
//! use wavekat_sip::{Registrar, SipAccount, SipEndpoint, Transport};
//!
//! # async fn run() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
//! let account = SipAccount {
//! display_name: "Office".into(),
//! username: "1001".into(),
//! password: "secret".into(),
//! domain: "sip.example.com".into(),
//! auth_username: None,
//! server: None,
//! port: None,
//! transport: Transport::Udp,
//! };
//!
//! let cancel = CancellationToken::new();
//! let (endpoint, _incoming) = SipEndpoint::new(&account, cancel.clone()).await?;
//! let endpoint = Arc::new(endpoint);
//!
//! // Expires: 60s, re-register every 50s.
//! let registrar = Registrar::new(account, endpoint, cancel, 60, 50)?;
//! registrar.register().await?;
//! registrar.keepalive_loop().await;
//! # Ok(())
//! # }
//! ```
//!
//! The `_incoming` stream returned by [`SipEndpoint::new`] yields inbound
//! transactions (INVITE, OPTIONS, …). Until the `callee` helper lands,
//! consume it by driving [`SipEndpoint::dialog_layer`] directly.
//!
//! # Building SDP and parsing the answer
//!
//! ```
//! use std::net::{IpAddr, Ipv4Addr};
//! use wavekat_sip::{build_sdp, parse_sdp};
//!
//! let local_ip: IpAddr = Ipv4Addr::new(192, 168, 1, 50).into();
//! let offer = build_sdp(local_ip, 20000);
//!
//! // ... send `offer` in an INVITE, receive an SDP answer ...
//! let answer = offer.clone(); // simulate a loopback answer
//! let media = parse_sdp(&answer).expect("valid SDP");
//! assert_eq!(media.port, 20000);
//! assert_eq!(media.payload_type, 0); // PCMU
//! ```
//!
//! # Reading RTP headers off the wire
//!
//! For real receive loops use [`receive_rtp`]; to inspect individual
//! packets, parse directly:
//!
//! ```
//! use wavekat_sip::RtpHeader;
//!
//! let packet = [
//! 0x80, 0x00, 0x04, 0xD2, // V=2, PT=0 (PCMU), seq=1234
//! 0x00, 0x00, 0x16, 0x2E, // timestamp
//! 0xDE, 0xAD, 0xBE, 0xEF, // SSRC
//! ];
//! let header = RtpHeader::parse(&packet).unwrap();
//! assert_eq!(header.payload_type, 0);
//! assert_eq!(header.sequence, 1234);
//! assert_eq!(header.header_len(), 12);
//! ```
//!
//! # Module map
//!
//! | Module | Purpose |
//! |-----------------|----------------------------------------------------------------|
//! | [`account`] | Runtime [`SipAccount`] + [`Transport`] enum. |
//! | [`endpoint`] | [`SipEndpoint`] — bound transport, dialog layer, RX stream. |
//! | [`registrar`] | REGISTER + digest auth + keepalive re-registration. |
//! | [`sdp`] | Minimal G.711 offer/answer build + parse. |
//! | [`rtp`] | RTP header parser and async receive loop. |
//!
//! # Stability
//!
//! Pre-1.0. The public API will shift between minor versions while the
//! `caller` / `callee` helpers land. Pin an exact version if you need
//! stability today.
//!
//! # License
//!
//! Licensed under Apache 2.0. Copyright 2026 WaveKat.
pub use ;
pub use SipEndpoint;
pub use Registrar;
pub use ;
pub use ;
/// Short git hash this crate was built from, or `"unknown"` if unavailable.
pub const GIT_HASH: &str = env!;