neoben neoben - 1 month ago 16
Linux Question

libwebsocket: unable to write frame bigger than 7160 bytes

I'm addressing an issue with WebSocket that I'm not able to understand.

Please, use the code below as reference:

int write_buffer_size = 8000 +
LWS_SEND_BUFFER_PRE_PADDING +
LWS_SEND_BUFFER_POST_PADDING;

char *write_buffer = new unsigned char[write_buffer_size];

/* ... other code
write_buffer is filled in some way that is not important for the question
*/

n = libwebsocket_write(wsi, &write_buffer[LWS_SEND_BUFFER_PRE_PADDING], write_len,
(libwebsocket_write_protocol)write_mode);
if (n < 0) {
cerr << "ERROR " << n << " writing to socket, hanging up" << endl;
if (utils) {
log = "wsmanager::error: hanging up writing to websocket";
utils->writeLog(log);
}
return -1;
}
if (n < write_len) {
cerr << "Partial write: " << n << " < " << write_len << endl;
if (utils) {
log = "wsmanager-error: websocket partial write";
utils->writeLog(log);
}
return -1;
}


When I try to send data bigger than 7160 bytes I receive always the same error, e.g. Partial write: 7160 < 8000.

Do you have any kind of explanation for that behavior?

I have allocated a buffer with 8000 bytes reserved for the payload so I was expecting to be able to send a maximum amount of data of 8K, but 7160 (bytes) seems to be the maximum amount of data I can send.

Any help is appreciated, thanks!

Answer

We solved the issue updating libwebsockets to 1.7.3 version.
We also optimized the code using a custom callback called when the channel is writable

void
WSManager::onWritable() {
    int ret, n;
    struct fragment *frg;

    pthread_mutex_lock(&send_queue_mutex);

    if (!send_queue.empty() && !lws_partial_buffered(wsi)) {
        frg = send_queue.front();

        n = lws_write(wsi, frg->content + LWS_PRE, frg->len, (lws_write_protocol)frg->mode);
        ret = checkWsWrite(n, frg->len);

        if (ret >= 0 && !lws_partial_buffered(wsi)) {
            if (frg->mode == WS_SINGLE_FRAGMENT || frg->mode == WS_LAST_FRAGMENT)
                signalResponseSent();

            // pop fragment and free memory only if lws_write was successful
            send_queue.pop();
            delete(frg);
        }
    }
    pthread_mutex_unlock(&send_queue_mutex);
}
Comments