Repository navigation
Raise CallRinging when an outbound call starts ringing - #28
Conversation
SipClient reported the first ringing response only as StatusMessage text, and CallAsync's ring timeout starts when the INVITE is sent, so digest challenges, PBX routing, and carrier setup all counted against the ring time. A host that wants to time the ring from when the phone actually rings had no reliable signal. SipClient.CallRinging is raised once per CallAsync call, on the first 180 Ringing or 183 Session Progress (exactly what SIPSorcery routes to ClientCallRinging), with that status code. It is not raised without a ringing response and never twice for one call. StatusMessage and the other events are unchanged; the private handler was renamed to free the name. Tests: a scripted loopback callee sends 180, 183, 180 twice, 183 then 180, 181 only, or nothing, then 486. The event fires once with the first 180 or 183, never for 181 or no provisional response, resets for the next call, and StatusMessage still reports ringing. Closes #27 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Live checkTested against a VitalPBX (Asterisk 20.14) lab PBX, extension to extension. The caller behaved like the intended host:
All three calls ended with The PBX sends its own ringing. VitalPBX dials extensions with Asterisk's The silent callee got no CANCEL. Per RFC 3261 a CANCEL can't be sent until the callee has sent a provisional response. The caller's side still ended at the cancel. This is a quirk of the test callee, since real phones send 100 Trying right away. Other checks on |
Summary
Closes #27. This is the v0.1.5 change (PR-DIAL-1 in the pbx-voice requirements).
SipClientreported the first ringing response only asStatusMessagetext, andCallAsync's ring timeout starts when the INVITE is sent. A host that wants to time the ring from when the phone actually rings had no reliable signal. The pbx-voice daemon needs one: it measures ring time from the first 180 or 183, and treats "no ringing within 7 s of the INVITE" as a setup failure.Change
public event Action<SipClient, int>? CallRinging. It is raised once perCallAsynccall, on the first180 Ringingor183 Session Progress, with that status code. Those are exactly the responses SIPSorcery routes toClientCallRinging; other provisional responses go toClientCallTrying.CallAsync.StatusMessage("Call ringing: 180 Ringing.") and all other events are unchanged. The private handler was renamed fromCallRingingtoOnClientCallRingingto free the name.Intended use: pass a large
ringTimeoutSecondstoCallAsync, start your own timer onCallRinging, and cancel through theCancellationToken.Tests
New
CallRingingEventTests(the plan's D-U1). A scripted loopback callee answers each INVITE with the given provisional responses, then486, so no media is needed:It also fires again for the next call, and
StatusMessagestill reports ringing.dotnet test: 106 passed (98 + 8). The new tests passed 3 of 3 repeated runs. Build warnings unchanged (17).Compatibility
Additive only. SipBotOpen and homeline compile unchanged, and
sipbot serve's JSONL does not change. Live checks against the lab PBX (D-L1 to D-L3) follow before tagging v0.1.5.🤖 Generated with Claude Code