Repository navigation
Conversation
Owner
|
I could see point to have this merged, but fix could be simpler. Instead me spending tokens, |
fridokus
force-pushed
the
oskar-fridell/keepalive-upstream
branch
from
September 14, 2026 04:08
07cbac1 to
106217a
Compare
Author
|
Done, all three.
The test splits the message at each of its CRLFs so the LF lands in a read of its own. Without the guard it delivers 0 messages instead of 2, at the first boundary. Full suite passes. |
RFC 5626 section 3.5.1 puts a keep-alive between SIP messages, but readConnection treated any read of four bytes or fewer holding nothing but CR and LF as one, wherever it landed. A read is whatever TCP chose to deliver, so the LF ending a header line can arrive on its own. It was then swallowed and the parser left on a bare CR: the next message failed to frame with "line has no CRLF" although nothing was wrong with it, and the connection was closed. Splitting a real 1568-byte REGISTER at any of its 22 CRLFs reproduces it every time. Before emiago#352 the connection went deaf instead, seen in production as a proxy that stopped processing SIP while its CPU sat idle. parseStream now returns ErrParseSipPartial up instead of folding it into nil, and the read loop keeps the last parse result: while it is that error the parser is part way through a message, so a CRLF-only read is a continuation rather than a keep-alive. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fridokus
force-pushed
the
oskar-fridell/keepalive-upstream
branch
from
October 5, 2026 12:46
106217a to
fb17ef5
Compare
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.
The bug
readConnectiontreats any read of ≤4 bytes containing only CR and LF as an RFC 5626 §3.5.1 keep-alive, wherever it lands. But a read is whatever TCP chose to deliver, so the LF ending a header line can arrive on its own — and is then swallowed, leaving the parser on a bare CR.The next message fails to frame with
line has no CRLFeven though it is well formed, and the connection is closed.Splitting a real 1568-byte REGISTER at any of its 22 CRLFs reproduces it every time. Before #352 the connection went deaf instead, seen in production as a proxy that stopped processing SIP entirely, sockets draining normally and CPU idle.
The change
A keep-alive only counts between messages.
ParseSIPStreamalready knows when it is part way through one — it returnsErrParseSipPartialuntil it has drained its buffer — soparseStreampasses that error up instead of folding it intonil, and the read loop keeps the last parse result and checks it.Guarding on "the parser's buffer is empty" instead looks equivalent and is not: body bytes are copied out as they arrive, so a message waiting for the last two bytes of its body has an empty buffer.