poco icon indicating copy to clipboard operation
poco copied to clipboard

Issues with WebSocket sending binary (2048x2048 image)...

Open skipe777 opened this issue 7 years ago • 2 comments

Expected behavior

I am trying to send relatively large set of bytes via a WebSocket running in Poco. The data is just an image that is represented by an int[] that is 4194304 in size.

Actual behavior

The data makes it across to the client (Java/Android) successfully sometimes. The number of times is not consistent. Meaning, sometimes I will get one image across. Sometimes I will get 10. Sometimes I get none. What is consistent is what happens during the send. In Wireshark I can see that it turns into a PDU reassembled packet and gets and undefined op_code of 15, or a payload length invalid, or invalid flag (the failure is consistent, but the reason as defined by the client is not).

UPDATE: I can't confirm just yet, but it looks like the Frame is being corrupted. I have seen reserved bits get set, payload length being invalid, and a few other undefined op_codes. Best guess I have is that during the send (or in the network interface?) the packets become corrupted. Thoughts?

UPDATE 2: I have tried the code with 4 different Android libraries and all experience similar issues. The Poco WebSocket throws and IOException on the next attempted send. This demonstrates as if its trying to send the binary data as a string and is catching a null character or something. I used a different C++ WebSocket implementation to test the rest of the code out (uWebSockets) and everything else is solid (including each of the Android implementations that I tried). I am going to try to debug through the Poco libraries and see where the failure is coming from and hopefully send over a test case that shows the bug in action.

Steps to reproduce the problem

I setup a WebSocket:

_ws = new WebSocket(request, response);
_ws->setKeepAlive(true);
std::cout << "WebSocket connection established\n";

std::cout << "Request from " << request.clientAddress().toString() << std::endl;

Then I send data (for testing just in a loop firing every few seconds:

int width = 2048;
int height = 2048;
int length = width * height;
uint8_t buffer2[ width * height ];

for( int i = 0; i < 100; ++i) {
    std::memset(buffer2, 1, length);
    int sent = _ws->sendFrame(buffer2, length, Poco::Net::WebSocket::FRAME_BINARY);
    std::cout << "Size: " << length << ". But actually sent: " << sent << std::endl;
}

I have also tried changing that last line to use the sendBytes method as well will the same results: int sent = _ws->sendBytes(buffer2, length, Poco::Net::WebSocket::FRAME_BINARY);

POCO version

1.9.0

Compiler and version

GNU Make 4.1 Built for x86_64-pc-linux-gnu

Operating system and version

Linux 16.04

Other relevant information

skipe777 avatar Apr 27 '18 11:04 skipe777

From just skimming over the issue (I have no time to examine or try to reproduce right now), it sounds like you expect all the data you request to be sent to go through in a single attempt, which is not necessarily the case, see documentation:

Returns the number of bytes sent, which may be less than the number of bytes specified.

Edit: Actually, that is not quite accurate, because sendFrame() returns exactly the requested length. I'm not sure why the problem, @obiltschnig may have an explanation.

In the meantime, if you can produce a short example reproducing it, it would help.

aleks-f avatar May 08 '18 23:05 aleks-f

This issue is stale because it has been open for 365 days with no activity.

github-actions[bot] avatar Jul 04 '22 03:07 github-actions[bot]

This issue was closed because it has been inactive for 60 days since being marked as stale.

github-actions[bot] avatar Sep 03 '22 03:09 github-actions[bot]