Thanks to visit codestin.com
Credit goes to docs.rs

Skip to main content

Crate wavekat_sip

Crate wavekat_sip 

Source
Expand description

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 owns the wire-level concerns — SIP registration, dialogs, SDP offer/answer, and RTP framing — on a from-scratch engine (no external SIP stack), while staying out of audio device I/O, codec work, and call orchestration so it remains light and embeddable.

The SIP transaction/dialog/transport engine is built in-house (see the stack plan in docs/08-own-sip-stack.md); only the rsip crate is used, for SIP message types. The engine is an internal detail — consumers depend on wavekat-sip alone.

§Scope

What this crate covers:

  • SIP signaling — REGISTER with digest auth and keepalive re-registration (Registrar), a bound endpoint with inbound-call routing (SipEndpoint), outbound calls (Caller), and inbound calls (IncomingCall).
  • SDP — offer/answer for Opus (RFC 7587, preferred) and G.711 (PCMU + PCMA) with round-trip parsing (build_sdp_offer, parse_sdp); answers and mid-call re-offers pin the negotiated codec (CodecMenu). Negotiation only — encode/decode stays with the consumer.
  • RTP — header parser (RtpHeader), a debug-friendly receive loop (receive_rtp), and a codec-agnostic send loop (send_loop).

Explicitly out of scope (push these to the consuming application): audio device I/O, codec encode/decode, jitter buffering, recording; account persistence; call orchestration / AI pipeline / business logic.

§Quick start: register against a SIP server

use tokio_util::sync::CancellationToken;
use wavekat_sip::{Registrar, SipAccount, SipEndpoint, Transport};

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 = SipEndpoint::new(&account, cancel.clone()).await?;

// Expires: 60s, re-register every 50s.
let registrar = Registrar::new(account, endpoint, cancel, 60, 50)?;
registrar.register().await?;
registrar.keepalive_loop().await;

§Placing an outbound call

use std::sync::Arc;
use wavekat_sip::{Caller, SipAccount, SipEndpoint};

let caller = Caller::new(account, endpoint);
let target: wavekat_sip::re_exports::Uri = "sip:[email protected]".try_into()?;
let mut call = caller.dial(target).await?;

// Wire RTP to your audio / AI pipeline using call.rtp_socket and
// call.remote_media. Hang up locally with:
call.hangup().await?;

§Answering inbound calls

use std::sync::Arc;
use wavekat_sip::SipEndpoint;

while let Some(incoming) = endpoint.next_incoming_call().await {
    // Inspect incoming.remote_media, then accept (or reject):
    let _call = incoming.accept().await?;
}

§Building SDP and parsing the answer

use std::net::{IpAddr, Ipv4Addr};
use wavekat_sip::{build_sdp_offer, parse_sdp, AudioCodec};

let local_ip: IpAddr = Ipv4Addr::new(192, 168, 1, 50).into();
let offer = build_sdp_offer(local_ip, 20000); // Opus preferred, G.711 fallback

let answer = offer.clone(); // simulate a loopback answer
let media = parse_sdp(&answer).expect("valid SDP");
assert_eq!(media.port, 20000);
assert_eq!(media.codec, Some(AudioCodec::Opus { payload_type: 111 }));

§Reading RTP headers off the wire

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

ModulePurpose
accountRuntime SipAccount + Transport enum.
endpointSipEndpoint — bound transport, engine, inbound-call routing.
registrarREGISTER + digest auth + keepalive re-registration.
resolveRFC 3263 (subset) server location: SRV + A/AAAA fallback.
calleeIncomingCall — inbound INVITE accept/reject.
callerCaller outbound dial + the Call handle.
sdpOpus + G.711 offer/answer build + parse (negotiation only).
rtpRTP header parser, debug receive loop, codec-agnostic send loop.

§Stability

Pre-1.0. The public API may still shift between minor versions.

§License

Licensed under Apache 2.0. Copyright 2026 WaveKat.

Re-exports§

pub use account::SipAccount;
pub use account::Transport;
pub use callee::IncomingCall;
pub use caller::Call;
pub use caller::CallSession;
pub use caller::Caller;
pub use caller::InboundRequests;
pub use dtmf_info::build_info_body;
pub use dtmf_info::content_type_header;
pub use dtmf_info::InfoOutcome;
pub use endpoint::SipEndpoint;
pub use inbound::InboundRequest;
pub use refer::is_final_sipfrag;
pub use refer::parse_sipfrag_status;
pub use refer::refer_to_header;
pub use refer::refer_to_with_replaces;
pub use refer::DialogTriplet;
pub use registrar::Registrar;
pub use registrar::RegistrarDiagnostics;
pub use resolve::order_candidates;
pub use resolve::resolve_sip_server;
pub use resolve::SrvRecord;
pub use rtp::dtmf::build_event_payload;
pub use rtp::dtmf::build_rtp_dtmf_packet;
pub use rtp::dtmf::send_dtmf_burst;
pub use rtp::dtmf::DtmfBurstConfig;
pub use rtp::dtmf::DtmfDigit;
pub use rtp::dtmf::DEFAULT_VOLUME_DBM0;
pub use rtp::dtmf_recv::parse_event_payload;
pub use rtp::dtmf_recv::DtmfEvent;
pub use rtp::dtmf_recv::DtmfEventPayload;
pub use rtp::dtmf_recv::DtmfReceiver;
pub use rtp::receive_rtp;
pub use rtp::send_loop;
pub use rtp::RtpHeader;
pub use rtp::RtpSendConfig;
pub use sdp::build_sdp_offer;
pub use sdp::build_sdp_with;
pub use sdp::parse_sdp;
pub use sdp::select_codec;
pub use sdp::select_dtmf;
pub use sdp::AudioCodec;
pub use sdp::CodecMenu;
pub use sdp::DtmfSpec;
pub use sdp::MediaDirection;
pub use sdp::RemoteMedia;
pub use sdp::DTMF_DEFAULT_PT;
pub use sdp::DTMF_WIDEBAND_DEFAULT_PT;
pub use sdp::OPUS_DEFAULT_PT;
pub use sdp::OPUS_RTP_CLOCK_RATE;
pub use session_timer::min_se_in;
pub use session_timer::negotiate_uac;
pub use session_timer::negotiate_uas;
pub use session_timer::require_timer_header;
pub use session_timer::session_expires_in;
pub use session_timer::session_timer_loop;
pub use session_timer::supported_timer_header;
pub use session_timer::supports_timer;
pub use session_timer::Refresher;
pub use session_timer::SessionDialogOps;
pub use session_timer::SessionExpires;
pub use session_timer::SessionTimer;
pub use session_timer::SessionTimerOutcome;
pub use session_timer::UasSessionTimer;
pub use session_timer::DEFAULT_SESSION_EXPIRES_SECS;
pub use session_timer::MIN_SESSION_EXPIRES_SECS;

Modules§

account
Runtime SIP account configuration.
callee
Inbound calls: accept with an SDP answer, or reject.
caller
Outbound calls and the established-call handle.
dtmf_info
SIP INFO fallback transport for DTMF (application/dtmf-relay).
endpoint
Shared SIP endpoint: a bound UDP transport + the clean-room engine, with inbound requests routed to new calls or auto-answered in-dialog.
inbound
Inbound in-dialog requests surfaced to the consumer.
re_exports
Re-exports of the rsip message types that appear in our public API. Pinning them here lets consumers depend only on wavekat-sip.
refer
Call transfer primitives — REFER (RFC 3515) for blind and attended transfer, the latter with Replaces (RFC 3891).
registrar
REGISTER + digest auth + keepalive re-registration, over the engine.
resolve
SIP server location per a subset of RFC 3263: DNS SRV lookup with RFC 2782 ordering, falling back to plain A/AAAA.
rtp
RTP header parsing, a debug receive loop, a codec-agnostic send loop, and RFC 4733 DTMF (telephone-event) in both directions.
sdp
SDP offer/answer for telephony audio — Opus (RFC 7587) preferred, G.711 fallback — plus RFC 4733 telephone-event (DTMF) negotiation.
session_timer
RFC 4028 session timers — keep long calls from outliving a dead dialog.

Constants§

GIT_HASH
Short git hash this crate was built from, or "unknown" if unavailable.