-
Notifications
You must be signed in to change notification settings - Fork 81
Deal with safari fragmented pong data #353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@DeqingSun thank you for the PR. Indeed since the new iOS and macOS updates safari does not work anymore with a few projects using websocket but not all. It depends highly on the UI used. I am wondering if this fix will solve this issue: hoylabs/OpenDTU-OnBattery#2331 (reply in thread) i will test it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses a WebSocket fragmentation issue that occurs when Safari sends pong frames (and potentially other frames) split across multiple packets. The fix modifies the mask reading logic to handle cases where the 4-byte WebSocket mask arrives in fragments rather than all at once.
Key Changes:
- Repurposed
_pinfo.maskedfrom a boolean flag to a counter that tracks mask reading progress (0=unmasked, 1-4=partial, 5=complete) - Moved mask reading logic outside the initial frame parsing block to support resuming mask reads across multiple data packets
- Added state machine logic to read mask bytes incrementally and wait for more data when needed
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
629dd98 to
4c16b79
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
27684a4 to
d015042
Compare
|
@DeqingSun : I tested your PR as-is with our WebSocket example (that I updated for that). We can correctly see the ping/pong mechanism. Also, refreshing the page in Safari works (closes the previous ws connection and opens a new one) and closing the browser also disconnects.
I tested the copilot suggestion to restore the boolean state after defragmentation - the code seemed OK to me - but without luck - it leads to a MCU crash when closing the browser window. There is also this safari bug to handle where it is sending some data when ws.close() is called on client side (this was a user report some time ago). I will mark this PR as draft for now - it still require some work. |
|
@DeqingSun @willmmiles @me-no-dev @vortigont : I added a second commit to fix.
|
|
@DeqingSun : please test again with your setup and let us know! I tested on my side and it works. |
|
Yes, your improvement is confirmed, working on my setup. |
willmmiles
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it will work for the specific case. I cannot personally test this as I do not own any Apple hardware.
I'm happy to accept this as a quick fix; but broadly I'd prefer a general solution for arbitrary fragmentation over the whole function. (At no point is there any guarantee of how websocket traffic is divided into TCP packets - that's very much implementation dependent, right up to fragmentation at the physical interface.) It's somewhat ironic that we've ended up with a synchronous protocol decode function in a library named "AsyncWebServer"... ;) Helpfully we've got a _pstate variable already declared that could be expanded to a full state machine; alternately, if the current synchronous implementation is preferred, we could implement either a deferred-processing buffer or a continuation-passing style.
Yes this PR adds fragmentation support for the control frames like pong (mask) which was not supported before. But more generally defragmenting to support any kind of incoming buffer len and be able to progressively reconstruct the object is out of this scope and a lot more work. That's funny that this global defragmentation was never needed since the lib exist... Maybe because we can be sure that the websocket info object will always fit into a minimal tcp frame 🤷 ? |
Pong in Chrome 8A 80 8B 9B 7E 64 Pong in Safari 8A 80 46 DC 9F 25 This commit addresses the pointer corruption that occurs when Safari sends a Pong. Without this change, the library will use the mask as beginning of the data packet and misbehave. Use _pinfo.masked as a counter to minimize change of the code.
bc3ab80 to
3c9bb75
Compare
|
Sorry, missed this topic. P.S. Sorry, I do not have any apple stuff in possession (lucky me :) ) |
There is no way to have a backward compatible api with your changes, even merly ? If this is just about adapting a little that could be ok. |
|
No backward compat, sorry. The new API is more feature reach and implies a bit different approaches to use. |
OK! Maybe that could be an option then.... We need to discuss it. |
I have a kiosk iPad application that has to use Safari. The iPad app works with this library in 2019, but not with the new iOS and the new library. The fragmented data, especially pong, causes data corruption.
Pong data in Chrome
8A 80 8B 9B 7E 64
Pong data in Safari
8A 80
46 DC 9F 25
This commit addresses the pointer corruption that occurs when Safari sends a Pong. Without this change, the library will use the mask as the beginning of a new data frame and misbehave.
I used _pinfo.masked as a counter to minimize change of the code.