-
Notifications
You must be signed in to change notification settings - Fork 2
Home
GABPBX is a GPLv2 open source PBX based on the Asterisk architecture and maintained as the Germán Aracil Boned PBX project.
This wiki documents GABPBX as a system: architecture, modules, configuration, operation and implementation notes taken from the source tree.
The current release is GABPBX 1.5.17. It completes chan_sofia as a broad,
production-grade, drop-in replacement for chan_sip, and delivers reliable
two-way WebRTC media — DTLS-SRTP, an ICE-lite STUN responder, rtcp-mux,
BUNDLE and RTCP keyframe feedback — so a browser can register, call, be called,
hold and resume over secure WebSocket with audio and video, no pjproject and
no libnice in the tree. 1.5.0 adds video bridging between a legacy SIP video
phone and a WebRTC leg (H.264 passthrough), RFC 3264 o= version stickiness,
and DTMF logging.
A modern SIP channel driver built on the Sofia-SIP NUA stack — specifically our
own garacil/sofia-sip fork, tag
v2.0.4, a warning-clean build of Sofia-SIP 2.0.4 on GCC 14 and
OpenSSL 3 (no behavior or ABI change; see Build-and-Installation). Drop-in for
chan_sip (same SIP channel, sip show … CLI, SIPpeers AMI, sippeers
realtime), with capabilities chan_sip never had:
- Registration: SIP Outbound (RFC 5626), Path (RFC 3327), Service-Route (RFC 3608), GRUU.
- Presence/voicemail: outbound PUBLISH (RFC 3903), generic outbound SUBSCRIBE, an outbound MWI watcher, solicited and unsolicited MWI, presence/BLF dialog-info.
- Signaling: PRACK/100rel (RFC 3262), in-dialog UPDATE (RFC 3311), Q.850 Reason (RFC 3326), REFER transfer (blind and attended), out-of-dialog MESSAGE.
- Media: SRTP/SDES (RFC 4568), DTLS-SRTP (RFC 5763/5764), WebRTC audio and two-way video, Opus passthrough, T.38 fax with a state machine.
- Security: mutual TLS, TLS hardening, SHA-256 digest auth, a local anti-abuse SIP blacklist.
-
Diagnostics: per-call SIP history with verbose call analysis, plus a
richer
sip …CLI.
Start at Chan-Sofia, then Features for the full catalogue, WebRTC for the browser story, Migrating-from-chan_sip for the swap, and Security for the hardening posture.
Restores a faithful ${HANGUPCAUSE} after a bridged call ends, fixing a carrier-failover
double-dial / double-billing bug. No configuration change.
-
Symptom. A dialplan that dials a carrier and ends its retry loop on
$[${HANGUPCAUSE}=16](16 = normal clearing = the call was answered) re-dialed the next carrier even after a call that connected and completed normally — a second call, and a second bill, for every answered one — whenever the called party was the side that hung up. -
Root cause. When the callee ends an answered, bridged call, only the leaving channel carries its
own hangup cause; the surviving caller keeps whatever it had, usually
0.apps/app_dial.ccopies the dialed party's cause to the caller only inside theif (!ast_check_hangup(peer))guard — i.e. only when the caller hangs up — so on a callee hangup that copy was skipped and${HANGUPCAUSE}(the channel's own cause) stayed0, which the dialplan read as "not answered". -
Fix.
ast_bridge_call()now propagates the hung-up party's hangup cause to the surviving bridged channel when the bridge ends, mirroring modern Asterisk's bridging framework (bridge_dissolve→channel_set_cause): an existing positive cause is preserved, a zero/unknown real hangup is normalized toNORMAL_CLEARING(16), and a feature/time-limit return with no hung side is a no-op.chan_sipalready set the caller's cause on answer andchan_sofiadid not, so this restoreschan_sipparity:${HANGUPCAUSE}is now16after any normally-answered call regardless of which side hangs up, while busy / no-answer / congestion / reject — which never reach the bridge — are unchanged and still fail over. Validated live acrosschan_sofia,chan_sipandLocalchannels.
Makes chan_sofia BLF work end to end: a watcher subscribing to any configured extension now gets a
live lamp — including extensions that have not registered yet — without the duplicate/stranded hints
seen before. No configuration change.
-
Root cause.
sofia_create_peer_hint()placed the hint withast_context_find_or_create(), a check-then-act (read-lock lookup, unlock, write-lock insert). Under a same-name race the loser was prepended to the context list but rejected from the context hashtab (duplicate name), becoming a list-only orphan context. Hint resolution (ast_get_hint→pbx_find_extension→find_context) reads the hashtab only, so a hint on an orphan was unreachable: theSUBSCRIBEstill answered404and orphans piled up as duplicates (core show hintsshowed many same-named hints, allWatchers 0, while the lookup resolved none). -
Fix. The hint is added by context name with
ast_add_extension()— it resolves the hashtab-authoritative context under the contexts lock and adds atomically, so the hint lands exactly where the presence lookup resolves it and survives adialplan reload. Asubscribecontextis often a BLF-only namespace the dialplan does not define, so the context is created once only whenast_context_find()shows it genuinely absent — an already-defined context (e.g.default) is never re-created and so never duplicated, and a by-name add can never strand the hint on an orphan. -
Automatic hints. Hints are created at peer build (config load, realtime register/lookup) and, for
a configured peer whose hint does not exist yet, on demand when a watcher subscribes: the presence
SUBSCRIBEbuilds the target and creates its hint synchronously, then re-checks, so a BLFSUBSCRIBEto any configured target is answered202instead of404. The hint context resolvessubscribecontextfirst, else the peercontext; create, remove and lookup all use that resolution, and the peer string fields are snapshotted under the peer lock before the dialplan operations.
Two chan_sofia presence fixes that made watched-extension (BLF) lamps go stale and never settle into a
full mesh. No configuration change; no behavior change outside the broken presence paths.
-
BLF subscriptions no longer die at their first refresh. The presence
200/202andNOTIFYs carried the Sofia-SIP stack-default wildcardContact(<sip:*@host>), which is not routable. A watcher adopts thatContactas the dialog remote target (RFC 3261 §12.1.1) and — because a refreshingSUBSCRIBEand aNOTIFYare target-refresh requests (RFC 6665 §3.1/§4.4.1) — refreshes in-dialog toSUBSCRIBE sip:*, whichchan_sofiacannot resolve to a hint, so it answers404 Not Foundand tears the subscription down asterminated;reason=timeout. EveryEvent: dialogsubscription therefore established and then collapsed on its first renewal, so watcher meshes were uneven and never settled. The presence responses andNOTIFYs now emit a routableContactwhose user-part is the watched extension (via the Sofia-SIPNUTAG_M_USERNAMEtag), on those messages only — the stack still fills in host and port; refreshes route back and the subscription persists. MWI (Event: message-summary) was unaffected. -
On-hold device state no longer sticks busy. The per-peer on-hold counter leaked a
+1when a call was hung up or transferred while still on hold (the resume that would decrement it never arrives), pinningSIP/<peer>ONHOLD— which outranks in-use in the device-state calculation — with zero live channels, so BLF watchers saw the extension permanently busy. The count is now released on every teardown path, tracked independently of a mid-callnotifyholdreload and bounded against underflow.
A diagnostics addition. No configuration or behavior change.
-
sip show versionCLI. A new command reports which Sofia-SIP librarychan_sofiais using: the compile-time version it was built against, the runtime version exported by the shared object actually loaded (a differing value flags a library newer or older than the headerschan_sofiawas compiled against), and the resolved path of that shared object.
A follow-up to the 1.5.12 audit that closes one more memory-exhaustion leak. No configuration or behavior change for a correctly-configured deployment.
-
Blacklist-drop SIP handle leak closed (DoS under attack). Under an active SIP brute-force — the
exact condition the built-in IP blacklist exists to defend against — every out-of-dialog request the
blacklist dropped (
REGISTER,SUBSCRIBE,MESSAGE,NOTIFY,REFER,INFO,PUBLISH) leaked the fresh protocol handle the stack had created for it, along with its memory pool — and, forSUBSCRIBE, a dialog leg that is never reclaimed. OnlyOPTIONSwas reaped on the drop path, so a sustained flood of a blacklisted source grew memory without bound precisely while the box was under attack (the anti-brute-force defense amplifying the DoS). The drop path now reaps the unbound handle for every out-of-dialog method (the samemagic-guarded reap already used forOPTIONS); a bound, in-dialog handle is never touched. Verified on a live box withmalloc_trimbefore/after: the leak grew ~5 KB per dropped request and could not be reclaimed before the fix, and returns to baseline after it.
A focused security-hardening release from a full audit of chan_sofia (correctness, memory
safety, exploit-class). Eight fixes; no configuration or behavior change for a correctly-configured
deployment.
-
OPTIONS keep-alive handle leak closed (DoS). An out-of-dialog
OPTIONS— the common registrar/proxy keep-alive — is auto-answered200by the stack, but the fresh handle it created was never destroyed: every ping leaked a handle and its memory pool, unbounded, remote, unauthenticated. The handler now reaps the unbound handle and no longer double-responds. - Inbound DataChannel receive queue bounded (DoS). A peer flooding SCTP application data over an established WebRTC DataChannel could grow the shared worker queue and heap copies without limit; a per-DataChannel in-flight cap now drops under pressure (SCTP retransmits).
-
alwaysauthrejectis now a true anti-enumeration control. An unknown user got a401challenge while a known user with a bad password got403, so a credentialed retry revealed which accounts exist. Unknown-user auth now runs through the same digest verifier against an internal bogus account (matchingchan_sip), so the400/401/403result — and its timing — is identical either way. -
Delayed authentication rejections are now transmitted. The anti-enumeration delayed
401/403was bound to the request being processed, which does not exist in the timer that fires it, so the stack silently dropped every delayed reject; it is now bound to the saved request and reaches the wire. - Strict stateless-nonce parsing. A nonce with trailing bytes after its canonical form is now rejected (the validator no longer accepts a non-canonical suffix the digest/replay logic keyed on).
- Masquerade-race use-after-free closed. Off-thread finders and AMI/log emits that read a peer channel's name or linked-call id now take the channel lock, so a concurrent masquerade/rename can no longer free that string out from under the read.
-
Malformed / out-of-dialog REFER rejected before accept. A
REFERwith noRefer-Toor no active call was answered202 Acceptedfirst (orphaning a transfer subscription) then dropped; it is now rejected400/481before the 202.
-
Local-hold offer direction (experimental, default off). chan_sofia has always answered a local
hold with music-on-hold only, never telling the held peer over SIP. With
[general] hold_reinvite = sendonly(orinactive), a local hold now also re-INVITEs the peer toa=sendonly(peer stops sending and hears our MOH, RFC 6337) ora=inactive, restoringa=sendrecvon UNHOLD; a rejected/unanswered hold re-INVITE rolls back. A typed re-INVITE purpose keeps directmedia, T.38 and local-hold response handling isolated from each other. Defaultno= prior MOH-only behavior. Shipped experimental and off by default — the enabled path is validated end to end in a controlled test; still off by default pending production soak, validate before enabling.
-
Forked-call early media (experimental, default off). When a call to a peer forks to multiple
registered contacts, chan_sofia keeps the caller muted until one branch answers. With the new
[general] fork_early_media = yes, once the fork narrows to a single live non-WebRTC branch that sends a 180/183 with SDP, the caller hears that branch's early media (receive-only). Conservative by design: never binds while two or more branches are live, never sends media upstream before answer, no-op for WebRTC, and hands media to the winner (or restores silence) on answer/failure. Shipped experimental and off by default — the enabled path is validated end to end in a controlled test; still off by default pending production soak, validate before enabling.
Q.850 signaling reaches full chan_sip parity on rejected calls.
-
Q.850 Reason on INVITE rejects. With
use_q850_reason = yes, chan_sofia now stamps an RFC 3326Reason: Q.850;cause=N;text="..."header on INVITE-rejection responses (404, 480, 484, 486, 488, 503, and the in-dialog re-INVITE / UPDATE / T.38 488 rejects), not only on the BYE/CANCEL requests it already handled, so upstream proxies and billing see the real Q.850 cause behind a rejected call. The cause is taken from the channel hangup cause, or mapped from the SIP status via a port of chan_sip'shangup_sip2causefor pre-channel rejects. Gated byuse_q850_reason(default no).
A correctness follow-up to the audit — SDP body sizing, early-media signaling parity with chan_sip,
MWI summary completeness and RTCP report handling.
-
SDP buffer headroom. A WebRTC video answer using BUNDLE with several H.264/VP8 payload types, their
per-payload
a=rtcp-fblines and ICE candidates could exceed the fixed 2048-byte SDP body buffers, making the SDP builder fail closed and emit no SDP. The six response/offer SDP buffers now hold 4096 bytes, and the internal video attribute accumulators hold 2048 bytes (those can fill before the outer buffer on a rich video m-line), so a valid video answer is no longer silently dropped. -
progressinband=novsnever. Withprogressinband=no, a RINGING indication now degrades to in-band ringback once a 183 Session Progress has already been sent (early media exists), matchingchan_sip; previouslynocollapsed ontonever. -
MWI multi-class summaries. The
application/simple-message-summaryparser (RFC 3842) now aggregates the new/old message counts across all message classes (Voice, Fax, Pager, Multimedia, Text), each saturated, with theMessages-Waitingline as the fallback when no per-class counts are present. - RTCP multi-block reports. An RTCP SR/RR carrying more than one reception report block (RFC 3550) now selects the block that concerns our own SSRC for RTT/jitter/loss statistics, instead of always using the first block.
A further audit-hardening batch — correctness, security, concurrency and robustness across chan_sofia,
sofia_sdp, sdp_crypto, res_rtp and the RTP engine.
- RTP codec-map concurrency. The per-instance codec payload map has no lock of its own, so installing a freshly negotiated map on the SIP/SDP thread raced the media threads reading it; every live-map install and every media-thread reader now serialize under the RTP instance lock, and the peer-to-peer bridge takes its two instance locks separately so opposite bridge directions cannot deadlock. The outbound SRTP protect+send is likewise serialized against DTLS-SRTP (re)install and RTCP transmit on the same session.
-
SRTP key hygiene.
sdp_cryptonever logs the local SRTP master key, zeroizes key material before free (RFC 4568 §9.1), rejects an over-long inline key instead of truncating it, and echoes the accepted crypto tag on a re-keying re-INVITE (RFC 4568 §5.1.2). -
BUNDLE answer correctness. A WebRTC answer lists the
a=group:BUNDLEmids in the offered m-line order (RFC 8843 §7.3.1) instead of a fixed audio-first order, and the mid/group buffers are sized end to end for standards-legal long mids (no dropped group line, no truncated mid). -
T.38 and video re-offers. An image-only T.38 re-INVITE is answered with
m=imageonly (no phantomm=audio, RFC 3264 §6); a later re-INVITE on a leg that offered WebRTC video keeps offeringm=video(the emit is gated on the live video capability); and a forked call applies its winning branch's negotiated audio codec to the answered channel instead of relying on transcoding. -
Robustness. A malformed trailing RTCP sub-packet no longer discards a keyframe request latched earlier in the
same compound packet; the native bridge takes the second channel's video/text remote-address baselines from the
video/text instances; a very large
blacklist_banno longer overflows into a permanent ban; a refusedsip reloadno longer mutates the live blacklist window; REGISTER rejects bind their final response to the request; and the per-peer lock is destroyed on teardown.
An audit-hardening batch across chan_sofia, sdp_crypto, sofia_t38 and res_rtp — security, protocol
correctness and concurrency.
-
SRTP key confidentiality.
sdp_cryptono longer echoes the caller-controlleda=cryptoattribute — which carries the inline master key+salt (RFC 4568 §6.1) — at log level; the "lifetime unsupported" and malformed-line paths now log only non-secret fields (RFC 4568 §9.1). -
Per-suite key advertised == installed. In per-suite-fresh-key mode the emitted
a=cryptonow advertises the same key the local SRTP policy actually installed (a single selector feeds both), so the remote no longer decrypts with the wrong key; and the "unchanged crypto" short-circuit compares suite + selected index + key (not the key bytes alone), so a suite switch (…_80↔…_32) with a reused key correctly re-keys. -
RTCP concurrency. The scheduled RTCP SR/RR and the video-update PLI now serialize on the SRTCP session
(they protected+sent on the same libsrtp session concurrently); T.38 parameter interpretation and the
late-offer ACK SDP parse now run under the proper lock; and outbound-call paths no longer read freeable peer
string fields (
host/name) during asip reload. -
Inbound UAS hangup. An unanswered inbound INVITE is now rejected with a final response mapped from the hangup
cause (
chan_sipparity — 403/486/503/… instead ofCANCEL), with a guard so a call already rejected byBusy()/Congestion()never emits a double final response. -
Response binding. In-dialog UPDATE and NOTIFY responses are bound to their server transaction
(
NUTAG_WITH_THIS), so the 500/200 actually reaches the wire instead of being dropped and retransmitted to timeout. - Fork BLF. A forked call's winner now decrements the peer ringing counter on answer, so device state moves RINGING → INUSE instead of staying RINGING for the whole call.
-
fromuseroverrides the outboundFromuser (chan_sip parity). A peer'sfromuserwas only a fallback for the outboundFromURI user — used solely when no caller-ID resolved. chan_sip treats it as an override that wins over the resolved caller-ID (chan_sip.c:12900-12901), so a peer with nocalleridwhose channel carried the inbound SIP username emitted that username in the outboundFrominstead of the configuredfromuser(which some carriers reject).fromuser, when set, now overrides theFromURI user in both allowed and restricted presentation. Only theFromURI user changes — the display name, presentation,Contact, and any RPID/PAI headers are untouched (chan_sip's RPID builder never consumesfromuser). Restricted presentation now matches chan_sip exactly ("Anonymous" <sip:<fromuser>@anonymous.invalid>), andusereqphonetests the finalFromuser so a non-numericfromuserno longer inherits;user=phone. Completes the empty-callerid outbound parity from 1.5.3/1.5.4.
-
Outbound
Fromnever leaks the peer section name;[general] calleriddefault. The outboundFromidentity resolver used the peer/section name as a fallback when no caller-ID could be resolved (no channel/connected-line identity, no peercid_num, nofromuser) — so an anonymous inbound call from a peer with no callerid could leak the peer's account/auth name into theFrom. chan_sip never does this. Thepeer->namefallback is removed, and a new[general] calleridsets the last-resort fallback From identity (chan_sipdefault_calleridparity, defaultgabpbx; shown insip show settingsas "Default callerid"). It is only used when nothing else resolves an identity and does not override a real caller-ID. Completes the empty-callerid parity from 1.5.3 (an inboundFromstill passes through unchanged when the peer callerid is unset). Also silences a pre-existing build warning — chan_sofia now compiles with zero warnings.
-
Peer callerid on the outbound From (chan_sip parity) +
apply_peer_callerid. A peer that authenticates with one SIP username but is configured withcallerid=<number>was leaking its SIP username into the outboundFrominstead of presenting the configured number (which upstream proxies/SBCs may reject). Two-part fix: (1) a peer'scallerid=is now split into thecid_num/cid_namefields the driver actually uses — previously a duplicate config handler shadowed the split in both the static and realtime loaders, so the configured callerid never took effect; (2) new[general] apply_peer_callerid(defaultyes, chan_sip parity) forces the matched peer'scid_num/cid_name/callingpresonto an inbound call when no trusted RPID/PAI was accepted, so the configured callerid appears in the outboundFrom. A trusted RPID/PAI still wins;shrinkcalleridis honored;apply_peer_callerid=nokeeps the inboundFromuser (pass-through). The source of truth is the peercalleridfield; a dialplanSet(CALLERID(num/name))remains an optional later override. Applies onsip reload.
-
auth_qop— chan_sip legacy no-qop MD5 digest challenge. Some legacy handsets only authenticate against chan_sip's exact 401 challenge (the RFC 2069 formDigest algorithm=MD5, realm="…", nonce="…"with noqop); against chan_sofia's RFC 2617/7616qop="auth"form they failed the second REGISTER with403. New[general] auth_qop(defaultno) emits the chan_sip legacy no-qop MD5 challenge — withauth_algorithms=md5it is byte-for-byte chan_sip's — whileauth_qop=yesrestoresqop="auth"withnc/cnoncereplay protection. MD5 only (SHA-256 always keepsqop); applies onsip reload.⚠️ The defaultno(RFC 2069) has no digest replay protection, matching chan_sip — pair it with TLS/WSS, or setauth_qop=yeswhere handsets allow.
-
sip reloadno longer falsely refused ontls_min_version. On a config with no explicittls_min_version=line, the reload check compared the running effective default (TLS 1.2) against an empty scratch default and reported a phantom listener change, refusing everysip reloadwithlistener config changed (tls_min_version)until a full restart. The scratch now seeds the same effective default (shared with the load path so the two cannot drift), while a genuine change such astls_min_version=1.3is still correctly detected as requiring a restart.
-
Video between a legacy SIP video phone and a WebRTC leg. A SIP phone that
offers H.264 (RTP/AVP) can now exchange two-way video with a browser leg, with
no transcoding. The answer sent to the caller is narrowed to the video codec
the far/bridge leg actually negotiated (RFC 3264 §6): codecs the far leg cannot
produce are dropped instead of merely reordered, so the caller does not lock its
video onto a payload type the peer will never send. H.264
a=fmtp(profile-level-id/packetization-mode, RFC 6184 §8.2.2) is relayed and, when the two sides cannot agree, video fails closed to audio rather than sending a stream the peer drops. The intersection is SDP-only — no channel format state is mutated mid-call — and a keyframe request crosses the bridge in both directions (SIP INFOpicture_fast_update⇄ RTCP PLI/FIR, RFC 5168/4585/5104). The INFO answer is now bound to its own transaction (NUTAG_WITH_THIS), removing a ~32-second Timer-F cut. See WebRTC. -
SDP o= version stickiness (RFC 3264 §8). A re-offer that repeats the same
session origin with an unchanged (
<=) version is treated as a no-op, so a learned symmetric-RTP remote address survives anUPDATE/re-INVITE — matchingchan_sipprocess_sdp_oand preserving audio across NAT keepalive re-offers. Theignoresdpversionoption is honoured (defaultno). -
DTMF logging.
sip set debug dtmf on|offlogs every received DTMF digit (RFC 2833/telephone-event, SIP INFO, or inband) to the CLI and the messages log, the waychan_sipdid — useful when diagnosing IVR and feature-code entry. Default off. See Chan-Sofia.
-
WebRTC call hold/resume works end to end. Pressing Hold on a WebRTC phone
no longer tears the call down, and video resumes by itself on unhold, exactly
like audio — in every combination of WebRTC and desk-phone endpoints, on
either side of the call. Five fixes: the SDP answer now mirrors the offered
per-media direction (RFC 3264 §6.1); answers mirror every offered m-line
using the current offer/answer transaction role (RFC 3264 §6); the fork-winner
handover preserves the SDP stream identity (
cname/msid, RFC 7022/8830); negotiated video payload types survive renegotiation (RFC 3264 §8.3.2); and RTCP keyframe feedback (PSFB PLI/FIR, RFC 4585/5104) is implemented end to end — advertised asa=rtcp-fb, relayed across the bridge, and transmitted SRTCP-protected over the ICE-selected tuple. See WebRTC.
- WebRTC fork-winner media fix. When a call forks to an extension registered from both a browser (wss) and a desk phone (udp) and the browser answers first, the call now carries two-way audio and video (previously the winning leg's DTLS never completed because stale media descriptors starved its socket). See WebRTC.
-
Native peer-to-peer SIP text messaging. An out-of-dialog
MESSAGEbetween two registered users is delivered to the recipient's live devices, resolved through the same auto-created hint namespace as BLF and fanned out to every registered contact (RFC 3428). New optionmessage_autorelay(default on); themessage_contextdialplan route remains available as a fallback. See Features.
- Reliable WebRTC audio. The ICE media tuple is now latched on every integrity-authenticated connectivity check, not only the nominated pair, removing intermittent one-way audio and the 10–20 s startup gap and making inbound calls to a browser come up cleanly (RFC 8445 / RFC 7675). See WebRTC.
-
Bundled WebRTC video. A new option
webrtc_video_bundle(per-peer and[general], default off, requireswebrtc=yes) carries audio and video over a single ICE/DTLS transport with payload-type demux and the RTP MID header extension (RFC 8843 max-bundle, RFC 8285). See WebRTC. -
Per-Contact registration. Each Contact in a REGISTER now binds, refreshes
and de-registers independently with its own
;expires(RFC 3261 §10.3), and a call to a peer whose bindings have all expired returnsCHANUNAVAILinstead of routing to a stale binding. See Chan-Sofia. -
DTMF parity with
chan_sip. The negotiated DTMF mode is reflected end to end: telephone-event is advertised only for RFC 2833 modes,dtmfmode=autoresolves at SDP commit with a fax-safe detector reconfigure, and inbound SIP INFO signals are parsed. See Features. -
TLS 1.2 accepted by default.
tls_min_versionnow defaults to TLS 1.2 (1.2 and 1.3) instead of 1.3-only, so endpoints that cap at TLS 1.2 connect. See Security. -
Live decrypted SIP capture.
sip_capture_addressstreams every decrypted SIP message (udp/tcp/tls/ws/wss, with SDP) as HEP to a Homer/sipcapture server,sip_capture_filewrites the same to a text file, andrtp set debug ice/sip set debug forkadd targeted tracers. See Operations.
-
Inbound WebRTC calls now connect. A call placed to a wss-registered
browser (GABPBX as the SDP offerer) comes up with two-way audio, alongside the
already-working browser-originated calls. Two RFC-grounded fixes make it work:
an ICE role-conflict repair (GABPBX replies
487 Role Conflictso the browser flips to controlling and nominates a pair, RFC 8445), and deferring inbound DTLS until the answer'sa=fingerprintis installed instead of failing closed (RFC 5763/8842). Rejected video tears down only its own pre-armed DTLS/ICE and never drops the audio call. See WebRTC. -
SDP/ICE diagnostics.
sip set debug sdp [on|off]traces the generated offer SDP, the WebRTC offer-gate decision, the incoming answer SDP and the offerer answer-apply path — the WSS/TLS signalling already decrypted. EverySofia: …debug line now carries a[from-user|to-user|callid]transaction tag. See Operations.
- WebRTC media is no longer roadmap. Two WSS browsers can hold a real two-way audio call, with two-way video (VP8/H.264) on top. See WebRTC.
- Opus relays without transcoding. Three core fixes (codec selection, the 48 kHz clock rate, and the RTP smoother) let a both-Opus call pass through cleanly. See Features → Opus.
- The full
chan_sofiaSIP and media catalogue is documented one feature at a time in Features.
-
Chan-Sofia - the Sofia-SIP based SIP channel driver and
chan_sipreplacement. -
Features - the complete
chan_sofiacapability catalogue, one by one. - WebRTC - browser SIP over WSS, DTLS-SRTP, ICE-lite, audio and video.
- Migrating-from-chan_sip - the two-line swap and what carries over.
- Security - the security and robustness posture.
- Architecture
- Build-and-Installation
- Module-Families
- Channel-Drivers
- Applications
- Dialplan-Functions
- Codecs-and-Formats
- Realtime-and-Resources
- CDR-CEL
- PBX-and-Bridges
- Operations
Documentation in this wiki follows the source code first. When a behavior is uncertain, the source file and sample configuration are authoritative.
SIP — chan_sofia
Subsystems
Realtime & data
Operations