SippyEngine had never successfully placed a call or registered a trunk. Every failure was masked by broad exception handlers that logged and marked the leg terminated, so the gateway reported "ringing" and then ended the call rather than surfacing the fault. None of it was visible to the test suite, which runs exclusively on MockSIPEngine. Found by pointing the gateway at a local Asterisk instance (tests/lab) — each fix uncovered the next. 1. Trunk registration used kwargs the installed sippy (2.3.0) does not accept (auth_name/auth_password → user/passw), called register() instead of doregister(), and passed aor/contact as strings where SipRegistrationAgent calls .getCopy() and mutates .username/.port, so SipURL objects are required. It also posted registered=True at *send* time. Registration is asynchronous, so a rejected REGISTER would still have reported success — and /health treats a registered trunk as a condition for "healthy". Now wired to sippy's rok_cb/rfail_cb, so the rejection status line (typically a bad trunk password) reaches the operator. The Contact also fell back to loopback when the SIP bind is 0.0.0.0; a wildcard address is not somewhere a trunk can send an INVITE. 2. The INVITE passed SDP as a `body` kwarg. CCEventTry takes no such argument: UacStateIdle unpacks exactly six fields from the data tuple and expects the SDP as a MsgBody in position four. callingID/calledID are bare usernames — sippy builds the URIs itself from nh_address. 3. _sip_logger was absent from the global config. SipTransactionManager dereferences it on every message, so the first SIP packet in either direction raised KeyError inside the ED thread. 4. SippyCallController was not callable. Sippy invokes event_cb(event, ua) with CCEvent objects; the class only exposed on_* methods that nothing called. Added __call__ to dispatch CCEventRing/Connect/Disconnect/Fail to the existing handlers, guarding the body because an exception escaping into the ED dispatcher would hang the leg silently. 5. The UA was constructed without credentials, so sippy could not answer the 401/407 challenge that any authenticating trunk sends. Every outbound call died on the challenge. Verified end to end against Asterisk 22.10.1: 180 Ringing → Connected → 23s of audio → clean teardown, with the dialplan executing and audio playing in real time. Not fixed here, and still blocking media: MediaPipeline.create_tap is a stub that logs success and returns a tap nothing ever feeds, so the classifier receives no audio on a live call. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
39 KiB
39 KiB