Skip to content

fix: handle unmatched 487 response on delayed call cancellation#1542

Merged
sipsorcery merged 2 commits intosipsorcery-org:masterfrom
shokoban:fix/unmatched-487-on-delayed-cancel
Mar 8, 2026
Merged

fix: handle unmatched 487 response on delayed call cancellation#1542
sipsorcery merged 2 commits intosipsorcery-org:masterfrom
shokoban:fix/unmatched-487-on-delayed-cancel

Conversation

@shokoban
Copy link
Copy Markdown
Contributor

@shokoban shokoban commented Mar 1, 2026

Summary

  • Delayed INVITE cancellation (around 32 seconds after creation) could cause a cancelled transaction to be immediately expired.
  • As a result, the final 487 Request Terminated could no longer be matched to the transaction and was surfaced as a generic SIPTransportResponseReceived event.

This PR updates cancellation lifecycle handling in SIP transactions:

  • Add CancelledAt property to SIPTransaction to track the cancellation timestamp.
  • Change SIPTransactionEngine to use CancelledAt (instead of Created) when expiring transactions in the Cancelled state.

Why this approach:

  • Expiration for cancelled transactions should be based on when cancellation happened, not when the transaction was originally created.
  • This keeps the transaction available to correctly consume the final 487 and complete cleanup gracefully.

Test plan

  • dotnet build SIPSorcery.slnf -c Release
  • dotnet test test/unit/SIPSorcery.UnitTests.csproj -c Release -f net8.0
  • dotnet test test/unit/SIPSorcery.UnitTests.csproj -c Release --framework net10.0

Notes

  • Behavior change: Cancelled INVITE transactions are no longer prematurely garbage-collected solely due to age since creation.

References

Assisted-by: GPT-5.3-Codex

- Add 'CancelledAt' property to SIPTransaction to track cancellation time.
- Modify SIPTransactionEngine to use 'CancelledAt' instead of 'Created'
  when expiring transactions in the Cancelled state.

This resolves an issue where cancelling an INVITE after 32 seconds
resulted in the transaction being immediately garbage collected,
leaving the final 487 response orphaned and triggering a generic
SIPTransportResponseReceived event instead of closing gracefully.

Assisted-by: GPT-5.3-Codex
@sipsorcery sipsorcery added the sip label Mar 2, 2026
@shokoban
Copy link
Copy Markdown
Contributor Author

shokoban commented Mar 8, 2026

Please accept my apologies for the delayed response. I have made the changes based on your feedback. Could you please review it?

@sipsorcery sipsorcery merged commit 186d7ec into sipsorcery-org:master Mar 8, 2026
4 checks passed
@shokoban shokoban deleted the fix/unmatched-487-on-delayed-cancel branch March 20, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants