Refactor the code handling WS data event to remove code duplication and fix the usages of pinfo->opcode in examples#388
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors the WebSocket data event handling code to eliminate duplication by extracting repeated logic into a dedicated helper function. The refactoring addresses code that was duplicated across two locations where WebSocket data frames are processed.
Changes:
- Extracted duplicated buffer allocation and event handling logic into a new
_handleDataEventhelper method - Modernized memory management by replacing manual
malloc/freecalls withstd::unique_ptr - Consolidated error handling for allocation failures into the new helper function
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/AsyncWebSocket.h | Added declaration for the new _handleDataEvent private helper method |
| src/AsyncWebSocket.cpp | Replaced two instances of duplicated code with calls to _handleDataEvent and implemented the new helper method using modern C++ memory management |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5b0c586 to
8e63fe2
Compare
…nd fix the usages of pinfo->opcode in examples
41f83cf to
4306f1f
Compare
willmmiles
left a comment
There was a problem hiding this comment.
Looks very good to me, though I haven't personally tested it. We could optimize further, and IMO an opt-out feature would be nice to have, but this is already a clean improvement.
Aside: frankly, seeing this make me wonder if there isn't some small value in doing a similar factor-out-to-function on some of the other handler paths, even though there would be only one call site for each. I find this actually makes the code easier to read, keeping the "what to do with a specific frame" in an easily identifiable section unmixed from the "how we find frames in the packet buffer" loop.
yes I agree! |
…ge_opcode non set for non fragmented frames
|
@willmmiles I added a commit based on our discussion here. I tested sending a long message with websocat with It turns out the copy will always be used as long as the tcp buffer is filled. But if the last frame is shorter, then the disconnect control frame can be put together by websocat or browser. So for the last frame processing, we can see that a backup is done, then last character restored, then the control frame for the disconnection is processed. I also fixed another bug where the message_opcode was not initialized in the case of a short message where there is 1 segment 1 frame. |
| if (_pinfo.index == 0) { // first fragment of the frame | ||
| // init message_opcode for this frame | ||
| // note: For next WS_CONTINUATION frames, they have opcode 0, so message_opcode will stay like the first frame | ||
| if (_pinfo.opcode == WS_TEXT || _pinfo.opcode == WS_BINARY) { | ||
| _pinfo.message_opcode = _pinfo.opcode; | ||
| } | ||
| // init frame number to 0 if only 1 frame or if this is the first frame of a fragmented message | ||
| if (_pinfo.final || datalen < _pinfo.len) { | ||
| _pinfo.num = 0; | ||
| } | ||
| } |
There was a problem hiding this comment.
message_opcode was not properly initialized when the text/binary frame fitted in 1 tcp buffer
=> (datalen + _pinfo.index) == _pinfo.len)
The way I do not know if browsers behave the same way, but I suspect so. In practice I guess the implication is that the multi-packet optimization doesn't help very often. I did hack |
4b07181 to
fad8ca3
Compare
Ahah that’s clever! I searched for the CLI parameters to tweak the tcp layer but I completely forgot it was OSS! I don’t know though of I would be able to do what you did 😅 |
this is a little refactoring following PR #385.