Repository navigation
Releases: calebtt/SipBotLib
Release list
v0.1.6
sipbot serve's play command now accepts μ-law and A-law WAV files, as its documentation already said.
Fix (#29, #30)
- The bug:
playrejected 8 kHz μ-law WAV files with "not a readable WAV … decode produced no PCM".AudioAlgospassed the WAV reader to NAudio'sToSampleProvider(), which only takes PCM and IEEE float. - The fix: WAV data in μ-law or A-law is now decoded to 16-bit PCM with NAudio's managed decoders before resampling.
- Where it applies:
ConvertWavToPcm(behindsipbot play),ReadWelcomeWavBytesAsPcmu, andReadWelcomeWavBytesAsPcm16kHz. - Compatibility: no public API change. PCM WAV files behave as before.
Testing
- Unit tests: 114, including 8 new decode tests for μ-law and A-law, resampling, both welcome-WAV readers, and
PlayWavwith a μ-law file. - Live against a VitalPBX (Asterisk 20.14) lab PBX, with the downloaded release binary:
- the agent E2E suite passed 5/5
- calls in both directions were answered
sipbot serveplayed an 8 kHz μ-law WAV into an answered call, and the far end's recording matched it (correlation 0.993)
🤖 Generated with Claude Code
v0.1.5
Adds an event for when an outbound call starts ringing, so a host can time the ring from that moment instead of from the INVITE.
SipClient.CallRinging (#27, #28)
- What it is:
event Action<SipClient, int> CallRinging. It is raised once perCallAsync, on the first180 Ringingor183 Session Progress, and carries that status code. - When it doesn't fire: after a second ringing response or after other provisional responses such as 181. It also doesn't fire when no ringing response arrives.
- Why: before this, the first ringing response was reported only as
StatusMessagetext, which is not a contract.CallAsync'sringTimeoutSecondscounts from the INVITE, so authentication challenges, PBX routing, and carrier setup all used up ring time. - Usage: to time the ring from ringing, pass a larger
ringTimeoutSecondsas an overall cap, start your own timer whenCallRingingfires, and cancel the call through theCancellationToken. - Unchanged: the
StatusMessagetext ("Call ringing: 180 Ringing.") and thecall_ringingmetric.
What "ringing" means depends on the PBX. Some PBXs report ringing to the caller as soon as they start dialing an extension, whatever the handset does. VitalPBX is one: it dials extensions with Asterisk's Dial option r. On such a PBX the event marks "the PBX started dialing". On a trunk call, the carrier's ringing response is what reaches the caller.
Compatibility
- Additive only. Existing events,
StatusMessagetext, andCallAsyncbehavior are unchanged. sipbot servedoes not expose the event, and its JSONL output is unchanged.
Testing
- Unit tests: 106. The new tests use a scripted loopback callee to cover 180, 183, repeated and mixed ringing responses, 181, and no provisional response.
- Live tests against a VitalPBX (Asterisk 20.14) lab PBX, extension to extension, with a scripted callee:
- The event fired once per call, 258–380 ms after the INVITE.
- A cancel timed from the event left 7004–7012 ms later.
- The existing agent E2E suite passed, and the JSONL contract matched v0.1.4.
- These release assets were re-tested after download.
v0.1.4
Registration now recovers after outages, and hard registration failures stop cleanly. Also fixes to transfer, NOTIFY handling, and unregistering, plus PSTN target normalization. There was no separate v0.1.3; its changes are included here.
Registration (#13, #19, #22, #23)
- Recovers after an outage. Before, a failed refresh threw
SIPRegistrationUserAgent is already runningand the client stopped retrying; recovery came only from SIPSorcery's own retry, 300 s later. Each start now stops the old registration agent and starts a fresh one. - Default retry is unchanged. Up to 5 attempts at 2 s × n, then SIPSorcery's own retry stays armed.
IsRegisteredandstatus.registeredarefalsewhile registration is failing. Before, they stayedtruethrough an outage.- Optional extended retry, for always-on hosts:
SipConfig.RegistrationRetry.Extended, orsipbot serve --extended-retry/SIP_EXTENDED_RETRY=1. After a temporary failure it retries forever, the delay doubling from 30 s to at most 5 min. - Hard failures stop. A 401/407 after authentication, or a 402, 403, or 404, stops the agent. No further REGISTER is sent until
StartRegistration()is called again or the process restarts, so rejected credentials are not re-sent to the PBX. - New API:
SipClient.RegistrationStateandLastRegistrationError.StartRegistration()is safe to call again at any time.
Calls and messages
- Blind transfer hangs up the original leg once the transfer is accepted, as documented. It first waits up to 5 s for the final progress NOTIFY, so the PBX gets an answer (#14, #18, #24, #25).
sipbot serveemitsendedafter a successfultransfer. - Out-of-dialog NOTIFYs are answered with 200 OK. These are the unsolicited message-waiting notices the PBX sends after registration; the PBX used to retransmit them for ~32 s (#15, #17).
- Shutdown completes the unregister, waiting up to 3 s, so no stale contact stays on the PBX (#16, #20).
- PSTN targets:
tel:URIs and E.164 or punctuated numbers are normalized for dial and transfer. Targets with control characters, encoded CR/LF, or over 1024 characters are rejected.dial failedincludes the SIP status, for example(603 Decline)(#11, #12).
sipbot serve
- New flags
--extended-retryand--sip-trace(lab use: logs full SIP messages to stderr). Both are off by default.SIP_EXTENDED_RETRYandSIP_TRACEare read bysipbotonly. The startup line reports both settings. - JSONL event and field names are unchanged.
Compatibility
- Existing consumers keep the default retry schedule and recovery.
- A rejected account now stops registering instead of retrying, so restart after fixing credentials.
Dispose()can take up to 3 s longer when the registrar does not answer the unregister.BlindTransferAsynccan take up to 5 s longer when the transferee sends no progress NOTIFY.
Testing
- Unit tests: 98, including a scripted loopback registrar for the registration paths.
- Live tests against a VitalPBX (Asterisk 20.14) lab PBX:
- 60 s and 4-minute outages in default and extended retry, and three repeated cycles. Threads and file descriptors stayed flat. Registration returned within the pending retry wait (19–24 s in extended mode, 11.7 s in default).
- Dial and transfer targets, and the transfer, NOTIFY, and unregister fixes.
- The existing agent E2E suite, and the JSONL contract compared with v0.1.2.
- These release assets were re-tested after download.
v0.1.2
v0.1.2 — play/resample and negotiated codec for agents
v0.1.1
v0.1.1 CI: contents:write for GitHub Releases
v0.1.0 — sipbot linux-x64
Agent packaging for SipBotLib (#6).
sipbot (linux-x64)
Self-contained binary in sipbot-linux-x64.tar.gz. Unpack and run:
tar -xzf sipbot-linux-x64.tar.gz
export SIP_SERVER=pbx.example.com SIP_USERNAME=101 SIP_PASSWORD='...'
./sipbot-linux-x64/sipbot serve --auto-answerJSONL events on stdout, logs on stderr, JSON commands on stdin. See AGENTS.md.
Library
SipBotLib.0.1.0.nupkg from dotnet pack (not published to nuget.org).
Closes #6