Skip to content

fix: enforce RFC 6455 websocket framing and close semantics#2

Merged
ThePedroo merged 8 commits intoPerformanC:PWSL-serverfrom
1Lucas1apk:patch-2
Feb 4, 2026
Merged

fix: enforce RFC 6455 websocket framing and close semantics#2
ThePedroo merged 8 commits intoPerformanC:PWSL-serverfrom
1Lucas1apk:patch-2

Conversation

@1Lucas1apk
Copy link
Copy Markdown
Member

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:

    • continuation frames (opcode 0x0) are only accepted when a fragmented message is actually in progress
    • new data frames (0x1 / 0x2) are rejected if a fragmented message is already in progress
      (close 1002)
  • Fixed outbound fragmentation uncork: we were calling socket.uncork() instead of this.socket.uncork(), which could leave writes corked and delay/lock flushing.

  • Correct 64-bit length encoding for server→client frames: payload length 127 now emits the proper 8-byte unsigned length field (RFC-compliant).

  • Close handling is stricter and safer:

    • close frames with a 1-byte payload are rejected (invalid per RFC, close 1002)
    • received close codes are validated (reserved/invalid ranges rejected, close 1002)
    • close reason length is capped so the close payload stays within 125 bytes total (including the 2-byte status)

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>
Comment thread index.js Outdated
Comment thread index.js Outdated
Comment thread index.js
Comment thread index.js
Comment thread index.js Outdated
Comment thread index.js Outdated
Comment thread index.js Outdated
Comment thread index.js
Comment thread index.js Outdated
Comment thread index.js
1Lucas1apk and others added 5 commits January 24, 2026 15:58
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>
@1Lucas1apk 1Lucas1apk requested a review from ThePedroo January 24, 2026 20:19
Comment thread index.js Outdated
Comment thread index.js
Comment thread index.js
Comment thread index.js
Comment thread index.js
Comment thread index.js Outdated
Comment thread index.js Outdated
Comment thread index.js
Comment thread index.js Outdated
Comment thread index.js Outdated
- 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>
@1Lucas1apk 1Lucas1apk requested a review from ThePedroo January 25, 2026 16:49
Copy link
Copy Markdown
Member

@ThePedroo ThePedroo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last changes

Comment thread index.js Outdated
Comment thread index.js Outdated
Refactor socket handling to use activeSocket variable for better clarity and safety.

Signed-off-by: Lucas Morais Rodrigues <76886832+1Lucas1apk@users.noreply.github.com>
@ThePedroo ThePedroo merged commit df3ed81 into PerformanC:PWSL-server Feb 4, 2026
@1Lucas1apk 1Lucas1apk deleted the patch-2 branch February 4, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants