Tolerate UnrealIRCd's trailing space in the CAP ACK #8
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/cap-ack-trailing-space"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The actual root cause of the registration stall, found in the DEBUG capture:
UnrealIRCd puts a trailing space inside the final parameter, so the parsed argument is
'sasl '. The library's step tests:'sasl' in ['ACK', 'sasl ']isFalse. Neither the ACK nor the NAK branch runs,_sasl_stepstays parked on_sasl_cap_req, AUTHENTICATE is never sent, and registration stalls until the server times the connection out. The log shows precisely that — nothing at all after the PONG.Its sibling
_sasl_cap_lssplits the same field on whitespace, which is whyCAP REQgoes out fine. Only this one step is intolerant, so splitting the capability list the same way is the entire fix.It's installed on the connection instance because
_sasl_cap_lsadvances withself._sasl_step = self._sasl_cap_req— the instance attribute wins, and there's a test pinning that assumption.Replaying the server's captured lines verbatim
A bug in my own patch, caught by the test
My first version advanced to
_sasl_auth_sentinstead of_sasl_auth_plain. That sendsAUTHENTICATE PLAINand then waits forever for a903that cannot arrive, because the credentials are never sent — a different hang at a later point.A test asserting only "AUTHENTICATE PLAIN was sent" would have passed and shipped it. The end-to-end test that drives the whole exchange to
CAP ENDfailed instead.Verification
420 tests, up from 407. They cover both ACK spellings, NAK, malformed and non-CAP events, and pin the library's unstripped membership test — so when upstream fixes it, CI tells us the patch can be dropped rather than leaving it to rot.
Root cause of the stall, from the DEBUG capture: FROM SERVER: :hertz.slopnode.net CAP zuckerberg ACK :sasl arguments: ['ACK', 'sasl '] UnrealIRCd puts a trailing space inside the final parameter, so the parsed argument is 'sasl ' rather than 'sasl'. The library's step tests if event.arguments[0] == "ACK" and 'sasl' in event.arguments: which is False against ['ACK', 'sasl ']. Neither the ACK nor the NAK branch runs, _sasl_step stays parked on _sasl_cap_req, AUTHENTICATE is never sent, and registration stalls until the server times the connection out. The log shows exactly that: nothing at all after the PONG. Its sibling _sasl_cap_ls splits the same field on whitespace, which is why CAP REQ went out fine. Only this one step is intolerant, so the fix is to split the capability list the same way. Installed on the connection instance, because _sasl_cap_ls advances with `self._sasl_step = self._sasl_cap_req` and therefore picks up the instance attribute. Replaying the server's captured lines verbatim, trailing space included: before: CAP REQ sasl -> PONG -> (nothing) after: CAP REQ sasl -> PONG -> AUTHENTICATE PLAIN -> AUTHENTICATE <credentials> -> CAP END My first version advanced to _sasl_auth_sent instead of _sasl_auth_plain, which sends AUTHENTICATE PLAIN and then waits forever for a 903 that cannot arrive because the credentials were never sent. The end-to-end test caught it; a test that only checked "AUTHENTICATE PLAIN was sent" would not have. Tests: 420, up from 407. They pin the library's unstripped membership test so that when upstream fixes it, CI says the patch can be dropped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>