Skip to content

keep websocket compression state across interleaved control frames#12988

Open
arshsmith1 wants to merge 5 commits into
aio-libs:masterfrom
arshsmith1:ws-compress-interleaved-control
Open

keep websocket compression state across interleaved control frames#12988
arshsmith1 wants to merge 5 commits into
aio-libs:masterfrom
arshsmith1:ws-compress-interleaved-control

Conversation

@arshsmith1

Copy link
Copy Markdown

What do these changes do?

When a permessage-deflate message is split across several frames, a peer may interleave a control frame (ping/pong/close) between the fragments (RFC 6455 §5.4). The reader uses _frame_fin to spot the start of a new message and (re)latch the per-message compression flag, but control frames always carry FIN, so an interleaved one makes the following continuation look like a fresh message and clears that flag. The continuation is then handled as uncompressed: raw deflate bytes are delivered for a binary message, or a UTF-8 error closes the connection for a text one.

The fix lets only data frames advance that tracker, so control frames stay transparent to the message framing and the compression state carries across them. The added test feeds a compressed first fragment, a ping, then the continuation and checks the binary message still decompresses.

Are there changes in behavior for the user?

No public API change. A compressed message that previously came back corrupted (or dropped the connection) when a control frame landed mid-message now decodes correctly.

Is it a substantial burden for the maintainers to support this?

No, it is a few lines in the reader plus one regression test.

Related issue number

N/A

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
  • Add a new news fragment into the CHANGES/ folder

@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided There is a change note present in this PR label Jun 25, 2026
@Dreamsorcerer

Copy link
Copy Markdown
Member

Is this ready? PR is still in draft.

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.97%. Comparing base (4306796) to head (3bd36f6).
⚠️ Report is 39 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12988      +/-   ##
==========================================
+ Coverage   98.96%   98.97%   +0.01%     
==========================================
  Files         131      131              
  Lines       48087    48747     +660     
  Branches     2496     2541      +45     
==========================================
+ Hits        47587    48247     +660     
  Misses        376      376              
  Partials      124      124              
Flag Coverage Δ
Autobahn 22.12% <5.55%> (-0.11%) ⬇️
CI-GHA 98.90% <100.00%> (-0.01%) ⬇️
OS-Linux 98.67% <100.00%> (+<0.01%) ⬆️
OS-Windows 97.02% <100.00%> (-0.03%) ⬇️
OS-macOS 97.93% <100.00%> (-0.02%) ⬇️
Py-3.10 98.11% <100.00%> (-0.03%) ⬇️
Py-3.11 98.37% <100.00%> (-0.04%) ⬇️
Py-3.12 98.46% <100.00%> (-0.05%) ⬇️
Py-3.13 98.44% <100.00%> (-0.03%) ⬇️
Py-3.14 98.46% <100.00%> (-0.03%) ⬇️
Py-3.14t 97.55% <100.00%> (-0.03%) ⬇️
Py-pypy-3.11 97.43% <100.00%> (-0.02%) ⬇️
VM-macos 97.93% <100.00%> (-0.02%) ⬇️
VM-ubuntu 98.67% <100.00%> (+<0.01%) ⬆️
VM-windows 97.02% <100.00%> (-0.03%) ⬇️
cython-coverage 37.89% <100.00%> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@codspeed-hq

codspeed-hq Bot commented Jul 8, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 83 untouched benchmarks
⏩ 83 skipped benchmarks1


Comparing arshsmith1:ws-compress-interleaved-control (3bd36f6) with master (706ecdc)

Open in CodSpeed

Footnotes

  1. 83 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@arshsmith1 arshsmith1 marked this pull request as ready for review July 8, 2026 04:52
@arshsmith1

Copy link
Copy Markdown
Author

Yeah, it's ready, just marked it out of draft. The fix, regression test, changelog and CONTRIBUTORS entry are all in and CI is green. Sorry for leaving it in draft.

Comment thread aiohttp/_websocket/reader_py.py Outdated
Comment thread tests/test_websocket_parser.py Outdated
Co-authored-by: Sam Bull <aa6bs0@sambull.org>
Comment thread tests/test_websocket_parser.py Outdated
Comment on lines +613 to +617
parser._feed_data(PACK_LEN1(0x40 | WSMsgType.BINARY, half) + compressed[:half])
# interleaved ping
parser._feed_data(PACK_LEN1(0x80 | WSMsgType.PING, 0))
# final continuation fragment
parser._feed_data(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are we not using the public .feed_data() here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good point, no reason not to. Switched all three feeds to the public feed_data() and dropped a duplicate comment line that slipped in when I applied the suggestions. Suite still green (67 passed).

@Dreamsorcerer Dreamsorcerer added backport-3.14 Trigger automatic backporting to the 3.14 release branch by Patchback robot backport-3.15 Trigger automatic backporting to the 3.15 release branch by Patchback robot labels Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-3.14 Trigger automatic backporting to the 3.14 release branch by Patchback robot backport-3.15 Trigger automatic backporting to the 3.15 release branch by Patchback robot bot:chronographer:provided There is a change note present in this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants