Troubleshooting
Concrete fixes for the failures you are most likely to hit. Pair each with a Trace log
and quality snapshots — see Diagnostics.
Registration fails
- 401/407 loop — wrong username/password/realm. The SDK does a bounded stale-nonce retry; a persistent challenge means credentials. For 3CX, use the auth ID, not the extension number (3CX).
- No response to REGISTER — registrar host/port unreachable, or the box expects TLS.
Check
SipServerand network path. - Binding lingers after restart — fixed: unregister reuses the registration Call-ID +
CSeq (RFC 3261 §10.2.2). Prefer an awaited
UnregisterAsyncon shutdown over relying on dispose.
One-way or no audio
- SDP advertises a wrong/unreachable media address → check
c=/m=in the trace. The SDK advertises a routable (non-loopback) address; on complex NAT you may still need an SBC. See NAT and SIP trunks. - No common codec → align
PreferredAudioCodecswith the peer; keep G.711 (PCMU/PCMA) as a baseline.
Choppy / robotic audio
- High jitter/loss in the quality snapshots → a network problem, not the SDK. The adaptive jitter buffer compensates within limits.
- A stalled RTP timestamp burst (comfort noise / repeats) no longer derails the jitter estimator (fixed in 4.3.1).
DTMF not detected
- Confirm RFC 4733 telephone-events are negotiated in the SDP and the peer's DTMF mode
matches. Inbound DTMF fires
DtmfReceived— remember it can arrive on two threads (Events).
SRTP call fails
- With
SrtpPolicy.Required, a peer that can't do SDES SRTP yields a failed call by design (no silent downgrade). Confirma=cryptoin the trace and the peer's SRTP setting. UseOptionalto allow fallback. See SRTP/SRTCP.
Calls linger after the process exits
- Explicitly
HangupAsyncactive calls andUnregisterAsynclines beforeDispose(); the dispose-time cleanup is best-effort (Lifecycle & dispose).
Still stuck?
Capture a Trace log of the failing call and open a conversation at
info@bechstein.digital.