Repository navigation
fix: route the ACK of a 2xx to the INVITE with the same CSeq (rebase of #167) - #170
Merged
Merged
Conversation
ACKs for 2xx are routed to their server INVITE transaction by dialog through waiting_ack, which holds one transaction per dialog. Over UDP the ACK of a re-INVITE can arrive after the next re-INVITE on the same dialog: the UAC sends the next re-INVITE once its ACK is out, and the two can be reordered. By then the newer transaction owns the entry, so the late ACK is routed to it and ignored there (its CSeq does not match), while the older transaction never sees its ACK, retransmits its 2xx until 64*T1 and then ends the call with a BYE. An ACK carries the CSeq number of the INVITE it acknowledges (RFC 3261 §13.2.2.4) and stops that 2xx's retransmissions (§13.3.1.4). Keep the waiting transactions by dialog and CSeq number and route an ACK to the one with its CSeq. waiting_ack is kept as before, and a transaction now removes only its own entries, so an older transaction ending no longer drops a newer one's route. Only a 2xx gets a CSeq route: the ACK of a non-2xx is part of the INVITE transaction and matches it by branch (§17.2.3), so it is no longer routed by dialog.
This was referenced Oct 6, 2026
shenjinti
added a commit
that referenced
this pull request
Oct 6, 2026
Ships this round on top of 0.7.0: proxy-mode auto_ack_2xx (#146/#172), ACK CSeq routing (#155/#170/#172), digest auth_username (#153), dead stream retirement (#161), remote-ack getter (#157), UAS ACK timeout → BYE (#149/#169), RFC 6026 Accepted state + Timer L/M with documented deviations (#164/#169), CANCEL/2xx race handling (#162/#171), in-dialog Via transport (#163), flow-reuse and ACK hardening tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebase of #167 by @tgeorge06, closes #165.
Original change: a second ACK index
waiting_ack_cseq: (DialogId, INVITE CSeq) → TransactionKeyso the ACK of re-INVITE N reaches its own transaction even after re-INVITE N+1 was answered;forget_waiting_ackremoves only a transaction's own routes.Adaptation for the merged RFC 6026 state machine (#164/#169): the PR was cut against pre-#164 main where a server 2xx entered
Completed; here thewaiting_ack_cseqinsert moved to the Accepted entry (itsanswered_2xx-gated copy in the Completed entry would have been dead code — Accepted only carries 2xx, so it is unconditional there). The Accepted ACK arm already ended the transaction (#169), so confirmed calls clean both ACK routes synchronously.Local verification: 378 lib + 65 doc tests green across repeated runs, fmt clean. The PR's #165 reproduction test (re-INVITE 2 → re-INVITE 3 → ACK 2 → ACK 3) passes.