Closed AfflatusX closed 3 years ago
Hello @AfflatusX, Thanks for the compliments, I'm glad my library is useful to you.
As for the issue, quite curious, wsServer under no circumstances sends masked packets to the client. The ws_sendframe_bin()
and ws_sendframe_txt()
routines both use ws_sendframe()
behind the scenes, and the latter does not mask frames, you can check the implementation here. Somehow it looks like this frame is being malformed, perhaps due to memory corruption or something.
Could you tell me more about your environment? e.g. Google Chrome version, operating system, compiler, etc. It would be interesting if you could provide me with a minimal example that reproduces this problem, so I can also test here and better isolate the issue. I suspect that it might be something with your port for Zephyr RTOS but I can't say without further information.
As for debugging, I recommend checking the ws_sendframe()
function and the content of the variables frame
and response
, since they are sent to the client. A common practice that I also usually do is to capture packets from the network with some monitoring tool, such as Wireshark or tcpdump, so I can accurately know the content of the frame sent to the client. If you can capture this malformed packet and send me a '.pcap' it would also be interesting.
@Theldus appreciate the reply! I spent the night debugging this and finally figured it out. Like you said, the issue is not about the mask bit - but a mal-formated frame which Chrome ended up thinking the mask bit is 1.
I have a very large blob of data, so multiple send frame call needs to be made. My initial code looks like this (psudo-code):
while (sent < total) { sent += ws_sendframe_bin(fd, buffer + sent, FIX_CHUNK_SIZE); }
The error happens right after the first FIX_CHUNK_SIZE frame is sent. I then checked how much data was actually sent on each call - turned out my network interface only allows a much smaller payload per request.
So I suspected all the requests after the initial one serves as continuation of the first request. It works fine until it reaches the full size of that frame (FIX_CHUNK_SIZE). Since I always pass the FIX_CHUNK_SIZE for size parameter, the last one sent MORE data than what's remaining according to the first request (even though my full buffer has way more data in it). Maybe that extra data stuck in the pipe, and when Chrome reads the next request, it became mal-formatted.
To fix this, I basically use (FIX_CHUNK_SIZE - byte_sent_for_this_frame) for the size parameter, that fixed the issue.
btw, the reason that empty byte array didn't trigger the bug is because those extra bytes in the pipe are all zeros, which led Chrome to think it's unmasked :P
Hey @AfflatusX,
Thank you for such dedication to this issue, now I understand what is happening. To be honest, the fault is mine: the send()
routine that wsServer uses to send the frame does not guarantee 100% of the time that all content will be sent in a single call, and when this occurs, the common approach is to start looping sending the remaining number of bytes until you have sent all the content; it was my fault to mistakenly assume this, your code was probably all right from the beginning.
More info about this: send() function in C how to handle if not all bytes are sent?
So, I'm going to reopen this issue, mark it as a 'bug' and work on the fix for that, I will ping you when fixed.
Thank you very much for your time investigating this =).
Hi - first, I would like to thank you for this awesome library! It's very well written and easy to modify (I ported it to Zephyr RTOS platform for my project).
I encountered an issue where the client (Chrome web app) reports: A server must not mask any frames that it sends to the client. My server side logic sends multiple 64KB frames using ws_sendframe_bin().
It puzzles me because that issue seem to be data dependent - I tried with an empty byte array and it works fine. How could I debug this further?