Skip to content

Features

Germán Luis Aracil Boned edited this page Jun 25, 2026 · 6 revisions

chan_sofia Feature Catalogue

This page lists every chan_sofia capability one by one. Each entry names what it does and where it lives in the tree, so the source stays authoritative. The companion deep dive is Chan-Sofia; WebRTC has its own page (WebRTC); the security posture is Security.

chan_sofia registers the SIP channel type and the sippeers realtime family, so it is mutually exclusive with chan_sip — load one or the other.

SIP signaling

Inbound REGISTER / SIP registrar

Phones and softphones register their location so the PBX knows where to send their calls, with credential checks, per-peer source ACLs, and unknown-peer rejection. sofia_process_register() at channels/chan_sofia.c:7747; per-peer ACL and unknown-peer challenge in the same path.

REGISTER expiry bounds (423 / Min-Expires)

Minimum and maximum registration lifetimes are enforced; a too-short refresh gets a 423 Interval Too Brief with Min-Expires, which blunts registration-flood abuse. sofia_check_register_expiry() at channels/chan_sofia.c:2325.

Contact binding registry + binding query

Each phone's reachable Contact is stored under peer->lock, and a Contact-less REGISTER is answered as a pure "where am I registered?" query without changing state. sofia_update_peer_contacts() and sofia_respond_register_query() in channels/chan_sofia.c.

Outbound REGISTER (trunk registration)

register => lines register the PBX to upstream providers so inbound carrier calls reach you, with scheduled re-registration. sofia_do_register() issuing nua_register at channels/chan_sofia.c:13985.

Outbound-REGISTER response handling

A provider's answer (success, expiry, learned GRUU / Service-Route / Path / outbound state) is consumed and surfaced as an AMI Registry event. nua_r_register case at channels/chan_sofia.c:10809.

Qualify / OPTIONS keepalive

The PBX periodically pings registered phones with SIP OPTIONS to confirm reachability and measure round-trip time, marking dead peers unreachable. sofia_qualify_peer() at channels/chan_sofia.c:10495; periodic driver and on-demand async probe in the same area.

RTP keepalive

Optional tiny periodic media packets keep NAT/firewall pinholes open during a call or on hold. ast_rtp_instance_set_keepalive() driven by peer->rtpkeepalive at channels/chan_sofia.c:1483.

INVITE handling (inbound + outbound)

The call-setup engine: incoming calls into the dialplan, outgoing calls to peers and trunks. sofia_process_invite() and sofia_process_reinvite(), dispatched from nua_i_invite at channels/chan_sofia.c:10750.

INVITE digest authentication

Incoming calls can be challenged for a password so only authenticated users place calls, with toll-fraud guards for unknown and guest callers. sofia_verify_digest_auth() at channels/chan_sofia.c:5464; alwaysauthreject challenge and allowguest=no 403 in the same path.

Digest algorithms — MD5 + SHA-256 (RFC 7616)

Passwords are verified with classic MD5 or the stronger SHA-256, selectable per deployment, with anti-downgrade so the server accepts only an algorithm it offered. SOFIA_DIGEST_MD5/SHA256 and auth_algorithms enum in channels/chan_sofia.c:6713-6796 and channels/sofia/include/chan_sofia_internal.h:91-93.

Cryptographic nonce + TTL/stale handling

Each challenge uses a fresh 128-bit nonce from /dev/urandom with a configurable lifetime; an expired-nonce client is re-challenged (stale) rather than rejected. sofia_secure_nonce_gen() at channels/chan_sofia.c:6681.

WWW-Authenticate challenge per policy

The PBX advertises exactly the algorithms the operator enabled (MD5 first for legacy phones, SHA-256, or both). sofia_emit_auth_challenge() at channels/chan_sofia.c:6811.

100rel / PRACK (RFC 3262)

Reliable provisional responses, so "ringing" and other early call-progress messages are acknowledged and never lost on a lossy link. Outbound gating and inbound sofia_process_prack() at channels/chan_sofia.c:5411 and :10441; per-peer rel100.

UPDATE (RFC 3311)

In-dialog media renegotiation — hold, codec swap, session-timer refresh — without disrupting the dialog. sofia_process_update() at channels/chan_sofia.c:10768.

Session timers (RFC 4028)

Long calls are periodically refreshed so a crashed phone or dropped network cannot leave a zombie call billing forever; per-trunk originate/accept/refuse. sofia_session_timer_values() at channels/chan_sofia.c:3205.

Q.850 cause / Reason header (RFC 3326)

Internal hangup reasons map to standardized telephony cause codes on outbound BYE/CANCEL and parse back inbound. sofia_reason_build() / sofia_reason_parse_cause() in channels/sofia/sofia_reason.c; gated by use_q850_reason.

REFER transfer — outbound (blind + attended)

The PBX transfers a connected call to a third party, blind or attended (with Replaces), via the .transfer tech callback and a SofiaTransfer() application. channels/sofia/sofia_transfer.c:13.

REFER transfer — inbound

When a phone asks the PBX to transfer (REFER), the PBX honors it, including attended transfers via Replaces and the RFC 5589 transferer-leg BYE deferral. sofia_process_refer() at channels/chan_sofia.c:10156.

Out-of-dialog MESSAGE / SIP SIMPLE

Sends and receives SIP instant messages independent of a call; inbound routes to a message_context, outbound from the dialplan or AMI. channels/sofia/sofia_message.c.

Inbound SUBSCRIBE/NOTIFY routing

Accepts event-package subscriptions and routes each to the right handler — message-summary to MWI, dialog/dialog-info/presence to presence — rejecting unsupported packages with 489 Bad Event. sofia_process_subscribe() at channels/chan_sofia.c:9655.

Presence + BLF / dialog-info

Drives speed-dial lamps showing whether a monitored colleague is idle, ringing or on a call, in dialog-info+xml, pidf+xml or xpidf+xml. channels/sofia/sofia_presence.c.

MWI — inbound subscription + NOTIFY (RFC 3842)

Lights the message-waiting indicator, delivering the voicemail count solicited or unsolicited. Body builder and transmit_mwi_notify_for_peer() around channels/chan_sofia.c:8989.

MWI — outbound SUBSCRIBE watcher

The PBX subscribes to a provider's voicemail-status notifications and re-lights local phones, with retry/backoff on a failed initial subscribe. channels/sofia/sofia_subscribe.c; per-peer mwi_subscribe=.

Generic outbound SUBSCRIBE watcher (RFC 6665)

Subscribes a trunk to any event package and surfaces each notification as a SofiaEventNotify AMI event, without interpreting the body. channels/sofia/sofia_eventsub.c; per-peer subscribe_event=.

Outbound PUBLISH / EPA (RFC 3903)

Publishes a local extension's presence/state to an upstream server, refreshing with SIP-If-Match/ETag. channels/sofia/sofia_publish.c.

INFO — DTMF relay (application/dtmf-relay)

Carries key-press digits inside SIP signaling both ways, separate from inband or RFC 2833. sofia_process_info() at channels/chan_sofia.c:10350.

OPTIONS — capability responder

Answers SIP OPTIONS pings with a 200 OK advertising every supported method plus Accept: application/sdp. sofia_process_options() at channels/chan_sofia.c:5706.

GRUU (RFC 5627/5626)

Advertises a stable per-device instance ID on registration and learns the routable address the registrar mints. channels/sofia/sofia_gruu.c; per-peer gruu=.

Path (RFC 3327)

As a registrar, records and honors the route a phone registered through (edge proxy), rejecting forged Path with 420 Bad Extension. channels/sofia/sofia_route.c; per-peer path=.

Service-Route (RFC 3608)

On outbound registration, remembers the route the provider mandates and pre-loads it on outgoing calls. sofia_service_route_store() at channels/sofia/sofia_route.c:83; per-peer service_route=.

SIP Outbound / reg-id + Flow-Timer (RFC 5626)

Advertises outbound support and a registration ID and honors the provider's flow-keepalive timer, for reliable connectivity behind firewalls. Require: outbound / Flow-Timer learned from the 2xx at channels/chan_sofia.c:10876; per-peer sip_outbound=.

Diversion (RFC 5806)

Carries forwarding/redirection history outbound and parses it inbound into the channel's redirecting info, with a per-trunk forced-Diversion override. sofia_add_diversion() / sofia_change_redirecting_info() at channels/chan_sofia.c:1766.

SIP history / call-event recording

A per-call timeline of every SIP request and response for diagnostics, viewable while a call is being traced. Central hook around channels/chan_sofia.c:10740; implementation channels/sofia/sofia_history.c.

Local anti-abuse SIP blacklist

Counts and bans abusive source IPs (failed-auth probes, malformed requests, unknown-peer REGISTERs) to blunt brute-force and scanning. channels/sofia/sofia_blacklist.c; checked on every inbound request at channels/chan_sofia.c:10701.

Media (RTP / SRTP / DTLS-SRTP / codecs / T.38 / DTMF)

RTP/RTCP media stack (forked engine)

RFC 3550 RTP/RTCP with symmetric-RTP NAT traversal, jitter handling, RED and sender/receiver reports. One forked engine — gabpbx_rtp_engine, .name="gabpbx" at res/res_rtp_gabpbx.c:1408 — handles plain calls and WebRTC alike, so non-WebRTC RTP is unchanged. There is no separate res_rtp_asterisk in the tree.

SRTP with SDES (RFC 4568)

Encrypted media via SDP a=crypto — AES-CM 128/192/256 with HMAC-SHA1 80/32 and two GCM suites. Offers/answers are validated in full and staged, then committed only past every reject gate, so a bad a=crypto never silently downgrades a live call to plaintext. channels/sofia/sdp_crypto.c:37; process/stage/commit in channels/sofia/sofia_sdp.c.

DTLS-SRTP keying (RFC 5763/5764)

WebRTC-grade keying: keys derive from a DTLS handshake over the media path (not the SDP), with SHA-256 fingerprints, ephemeral self-signed certs and a=setup role negotiation so the two sides never both try to be the DTLS client. A dedicated scheduler honors DTLS backoff; a fingerprint mismatch fails the call closed. gabpbx_dtls engine at res/res_rtp_gabpbx.c:1001. Detail in WebRTC.

WebRTC ICE-lite STUN responder (RFC 8445)

A dependency-free ICE-lite agent — no pjproject, no libnice. GABPBX is permanently the controlled lite agent: it answers STUN binding checks, learns the peer from the authenticated check, and latches the nominated pair on USE-CANDIDATE. The responder is armed before the offer leaves the wire so a browser's first checks are never dropped. ICE-lite block at res/res_rtp_gabpbx.c:1265. Detail in WebRTC.

RTCP multiplexing (RFC 5761)

rtcp-mux: RTP and RTCP share one socket on WebRTC legs (browsers require it), with exactly one DTLS association per media stream. Emit at channels/sofia/sofia_sdp.c:268 (audio) and :443 (video).

BUNDLE negotiation (RFC 8843)

Session-level a=group:BUNDLE and per-m-line a=mid are emitted so browsers accept the SDP; audio is the tagged transport. Unsupported offered m-lines are reflected back as port-0 rejections in order, rather than refusing the whole session with a 488. channels/sofia/sofia_sdp.c:359-362.

WebRTC DataChannel relay (RFC 8831/8832/8841)

GABPBX bridges WebRTC DataChannels back-to-back between two WebRTC legs: an m=application UDP/DTLS/SCTP webrtc-datachannel is negotiated on the audio BUNDLE's DTLS, the SCTP association is carried by an optional usrsctp build, and the DCEP OPEN/ACK plus every message (PPID-preserving) are proxied to the far leg. GABPBX both accepts an offered DataChannel and offers one to the bridged leg, so a createDataChannel between two browsers crosses end to end. Opt-in per peer with datachannel=yes (needs webrtc=yes and a usrsctp build). channels/sofia/sofia_datachannel.c. Detail in WebRTC.

SIP over secure WebSocket (WSS / RFC 7118)

Browsers register and call over SIP-over-WSS (and plain WS). GABPBX listens on dedicated WS/WSS URLs, auto-aliases the WSS cert/ca-bundle files, and routes in-dialog ACK/BYE back over the exact accepted WebSocket connection (a browser's Contact host is a placeholder), so calls set up, tear down and survive NAT. channels/chan_sofia.c:11568-11660; transport append and placeholder-Contact routing at :501-589.

WebRTC audio (browser-to-browser)

A real two-way audio call between two WSS browsers, with DTLS-SRTP + ICE-lite + rtcp-mux + BUNDLE wired into the SDP. Opt-in per peer with webrtc=yes (inherited from [general]); a webrtc=yes peer fails the call rather than ever falling back to insecure media. Direct media is force-disabled on any DTLS/SRTP leg. Peer flag at channels/chan_sofia.c:2591/:13173; outbound offer sofia_webrtc_provision_offer() at channels/sofia/sofia_sdp.c:822.

Two-way WebRTC video (VP8/H.264)

Real two-way browser-to-browser video on top of audio: GABPBX both accepts a browser's offered video and offers video itself, negotiating VP8 or H.264 with its own DTLS/ICE/fingerprint. Video runs on its own separate transport (non-BUNDLE) — a distinct mid, port and DTLS association from the audio. Non-BUNDLE m=video block at channels/sofia/sofia_sdp.c:386-491; offerer provision and answerer accept in the same file.

Opus with passthrough-correctness fixes

Opus (RFC 7587, 48 kHz, stereo, useinbandfec) is offered and answered, and a both-Opus call relays with no transcoding. Three core gaps that garbled browser-to-browser Opus were fixed: codec selection now knows Opus, the format rate returns 48 kHz so the RTP TX timestamp clocks +960 per 20 ms (not +160), and the RTP smoother no longer re-chunks Opus's variable-size frames. Opus rtpmap/fmtp at channels/sofia/sofia_sdp.c:172-174; smoother exemption at res/res_rtp_gabpbx.c:2840-2845.

T.38 fax (UDPTL) with state machine

Real-time T.38 over UDPTL with a 4-state negotiation machine, re-INVITE handling, far-max-IFP signaling and a 5-second abort timeout. T.38 is correctly suppressed inside WebRTC SDP (a plain m=image there would 488 the session). sofia_change_t38_state() at channels/sofia/sofia_t38.c:34.

Direct media (re-INVITE bridging) with safety gates

directmedia (alias canreinvite) lets two endpoints exchange RTP directly when safe; it is gated conservatively — any SRTP/DTLS leg, any NAT'd peer, or a cross-leg ACL mismatch forces local relay, so encryption is never bridged to a non-secure peer. get_rtp_peer glue at channels/chan_sofia.c:3119-3168.

Codec negotiation (offer/answer, preference, narrowing)

Codecs are emitted in configured preference order, the answer is intersected with local capability, and a no-common-audio offer is cleanly rejected with 488 (logged to SIP history). preferred_codec_only narrows the answer to the single best codec; per-codec fmtp for G.729 (annexb=no), Opus and iLBC (mode=20). channels/sofia/sofia_sdp.c:143-222 and :1276-1311.

DTMF: RFC 2833, SIP INFO, inband, auto

All standard modes per peer: rfc2833 (default, telephone-event), info, inband (DSP), auto. The telephone-event payload type avoids colliding with a negotiated codec's PT, relaxdtmf loosens detection on poor lines, and SIPDtmfMode switches mode mid-call. dtmfmode config at channels/chan_sofia.c:2551-2555.

RFC 7983 packet demux

On a WebRTC leg the one muxed socket carries STUN, DTLS and (S)RTP/RTCP interleaved. GABPBX demuxes by first byte per RFC 7983 — STUN to the ICE responder, DTLS records to the handshake, RTP to SRTP-unprotect — with muxed SRTCP dropped and a flood guard. The whole demux is dormant unless DTLS is active, so plain calls are untouched. __rtp_recvfrom at res/res_rtp_gabpbx.c:1732-1786.

Transport, operations and chan_sip parity

Multi-transport listener (UDP/TCP/TLS/WS/WSS)

One nua_create() spins up every SIP transport from [general] bind ports, each enabled only when its bind port is non-zero, passed as separate NUTAG_URL/SIPS_URL/WS_URL/WSS_URL tags. channels/chan_sofia.c:11568-11660.

Per-transport bind addresses/ports

[general] exposes bindaddr/bindport, tlsbindaddr/tlsbindport, wsbindaddr/wsbindport, wssbindaddr/wssbindport, plus the udpbindaddr host:port alias. Each listener URL is IPv6-aware (bracket-wrapped per RFC 3261 §19.1.2). These are baked in at module load; sip reload aborts if a listener-level value changed.

TLS hardening (mTLS, min-version, ciphers, verify-depth/date)

Opt-in TLS security on the TLS listener: tlsverify, tlsverifyclient (mutual TLS), tls_min_version, tls_ciphers, tls_verify_depth, and TLS verify-date. Closes the accept-any-cert MITM hole sofia-sip leaves open by default. channels/chan_sofia.c:11647-11681.

CLI parity — sip show …

sip show peers, sip show peer <name> (full detail, tab-completed), sip show settings, sip show registry, sip show channels / show channel / show channelstats, sip show inuse, all in chan_sip's column layout, snapshotting under peer->lock before the blocking write. channels/sofia/sofia_cli.c.

CLI operations

sip reload (alias for module reload chan_sofia.so, aborts on a listener-only change), sip set debug [on|off|peer|ip], sip qualify peer, sip unregister, sip prune realtime, sip notify, plus sip show/set/clear history and the blacklist family. channels/sofia/sofia_cli.c.

AMI parity

SIPpeers/SIPshowpeer, SIPqualifypeer, SIPshowregistry, SIPnotify, and SofiaMessageSend, each mirroring chan_sip's field set (Transport extended to ws/wss). channels/sofia/sofia_ami.c; registered in channels/chan_sofia.c.

Realtime sippeers family

On a cache miss a peer is loaded from the sippeers realtime table, with optional dual-load of registration state from sipregs auto-detected via ast_check_realtime('sipregs'); cache lookup is atomic to avoid duplicate links on concurrent miss. sofia_find_peer_realtime() at channels/chan_sofia.c:2921-2961. See PostgreSQL-Realtime-Cache.

Realtime registration write-back

For realtime peers with rtupdate=yes, the binding is written back via ast_update_realtime on REGISTER and cleared on unregister, optionally stamping rtsave_sysname. A bounded background pool can offload the blocking DB write off sofia_thread. channels/chan_sofia.c:7466-7500.

Dialplan functions

${SIPPEER()}, ${SIP_HEADER()}, ${SIPCHANINFO()}, ${CHECKSIPDOMAIN()} — chan_sip-parity verbatim. The channel registers tech type SIP, so ${CHANNEL(...)}, AMI and CDR all see SIP/<peer> exactly as before. channels/chan_sofia.c:5789-6128.

Per-peer option parity

The peer parser accepts the full chan_sip per-peer vocabulary — host/context/secret/transport/allow/disallow/nat/directmedia (=canreinvite)/qualify/callgroup/mohinterpret/mohsuggest/session timers/insecure/permit/deny and more — so existing sip.conf-style peer blocks load unchanged. sofia_config_peer at channels/chan_sofia.c:2556-2910.

NAT, ACL, MOH, qualify

nat=force_rport,comedia; three independent ACL chains (source permit/deny, contactpermit/contactdeny, directmediapermit/directmediadeny) plus a global localha; per-peer mohinterpret/mohsuggest; qualify with RTT and PeerStatus AMI transitions. See Chan-Sofia for the per-knob detail.

Clone this wiki locally