fix: enforce RFC 6455 websocket framing and close semantics#2
Merged
ThePedroo merged 8 commits intoPerformanC:PWSL-serverfrom Feb 4, 2026
Merged
fix: enforce RFC 6455 websocket framing and close semantics#2ThePedroo merged 8 commits intoPerformanC:PWSL-serverfrom
ThePedroo merged 8 commits intoPerformanC:PWSL-serverfrom
Conversation
Reject frames with RSV1/RSV2/RSV3 set when no extensions are negotiated (protocol error 1002). Enforce control-frame rules: control frames must not be fragmented (FIN required) and payload length must be ≤ 125 (protocol error 1002). Reject unknown / unsupported opcodes instead of silently ignoring them (protocol error 1002). Enforce fragmentation rules: continuation frames (opcode 0x0) are only accepted when a fragmented message is in progress; new data frames (0x1/0x2) are rejected if a fragmented message is already in progress (protocol error 1002). Fix outgoing fragmentation uncork bug (was calling socket.uncork() instead of this.socket.uncork()), preventing writes from staying corked. Correct 64-bit payload length encoding for server-to-client frames (opcode length 127 uses 8-byte unsigned length). Harden close handling: Reject close frames with a 1-byte payload (invalid per RFC; protocol error 1002). Validate received close codes (disallow reserved/invalid ranges) and reject invalid ones (protocol error 1002). Enforce close reason max length (125 total payload including 2-byte status). Add missing socket close cleanup to avoid duplicate close emissions and dangling listeners in edge cases. Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
ThePedroo
requested changes
Jan 24, 2026
Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
Co-authored-by: Pedro.js <pedroolimpioguerra@gmail.com> Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
Co-authored-by: Pedro.js <pedroolimpioguerra@gmail.com> Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
ThePedroo
requested changes
Jan 25, 2026
- Adjust vertical spacing between close, destroy, and return statements. - Merge validation checks in close frame handling (case 0x8) to reduce LoC. - Move `this.socket = null` inside the existence check in `destroy()`. Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
ThePedroo
requested changes
Jan 29, 2026
Refactor socket handling to use activeSocket variable for better clarity and safety. Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
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.
This PR tightens our custom WebSocket implementation to match RFC 6455 behavior more strictly, especially around framing, fragmentation, and close semantics. The goal is to fail fast on invalid peer frames (instead of silently accepting weird states), and to fix a couple of correctness bugs in our outbound framing.
What changed
RSV bits are now enforced: frames with RSV1/RSV2/RSV3 set are rejected when no extensions are negotiated (close 1002).
Control frames follow the spec: control frames must be FIN-only (no fragmentation) and their payload must be ≤ 125 bytes (close 1002).
Unknown opcodes are no longer ignored: unsupported/invalid opcodes now trigger a protocol error instead of being silently dropped (close 1002).
Fragmentation state is validated:
0x0) are only accepted when a fragmented message is actually in progress0x1/0x2) are rejected if a fragmented message is already in progress(close 1002)
Fixed outbound fragmentation uncork: we were calling
socket.uncork()instead ofthis.socket.uncork(), which could leave writes corked and delay/lock flushing.Correct 64-bit length encoding for server→client frames: payload length
127now emits the proper 8-byte unsigned length field (RFC-compliant).Close handling is stricter and safer: