Skip to content

Complete the unregister before shutting the transport down - #20

Merged
calebtt merged 1 commit into
fix/issue-13-registration-recoveryfrom
fix/issue-16-shutdown-unregister
Sep 26, 2026
Merged

calebtt merged 1 commit into
fix/issue-13-registration-recoveryfrom
fix/issue-16-shutdown-unregister

Conversation

@calebtt

@calebtt calebtt commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #16. Stacked on #13's branch; merge after it. It uses #13's FakeRegistrar and its _isShutdown check in ScheduleReconnection.

SipClient.Shutdown() called SIPRegistrationUserAgent.Stop(), which queues the unregister (REGISTER with Expires 0) on a thread-pool thread, and then shut the transport down straight away. The unregister is usually challenged (401, then an authenticated retry), so it rarely completed. The registrar kept a dead contact until it expired and forked calls to it. With sipbot serve and quit, a lab extension ended up listing three contacts.

Changes

Tests

New ShutdownUnregisterTests, against #13's scripted loopback registrar:

  • A registered client's last REGISTER has Expires 0, both unchallenged and after a 401 challenge. Shutdown returns in under 2 s, and no REGISTER follows (no reconnect after RegistrationRemoved).
  • An unregister the registrar never answers is bounded to the 3 s timeout.
  • A client that is not registered sends nothing and returns immediately.

Without the fix, the first three fail: the unregister never goes out. dotnet test: 90 passed (86 on #13 + 4 new). Build warnings unchanged (17).

Compatibility

Dispose() and Shutdown() can now take up to 3 s longer when the registrar does not answer the unregister. When it answers, the delay is a round trip or two. SipBotOpen, homeline, and sipbot (quit) now leave no stale contact behind.

🤖 Generated with Claude Code

SipClient.Shutdown() called SIPRegistrationUserAgent.Stop(), which queues
the unregister (REGISTER with Expires 0) on a thread-pool thread, and then
shut the transport down straight away. The unregister is usually
challenged, so it rarely completed: the registrar kept a dead contact until
it expired and forked calls to it.

Shutdown now sends the unregister and waits up to 3 s for the registrar to
confirm it (RegistrationRemoved, or a failure) before shutting the transport
down. When the client is not registered it stops the agent and sends
nothing. RegistrationRemoved no longer leads to a reconnect once shutdown
has begun (ScheduleReconnection checks _isShutdown).

Closes #16

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@calebtt
calebtt force-pushed the fix/issue-16-shutdown-unregister branch from 6952270 to 0c36b26 Compare September 26, 2026 01:17
@calebtt
calebtt added this pull request to stack #21 September 26, 2026 01:23
@calebtt
calebtt merged commit a598942 into master Sep 26, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shutdown does not complete unregistration, so a stale contact stays on the PBX

1 participant