buffer websocket headers and body before sending to avoid fragmentation

This commit is contained in:
Anthony Minessale 2014-07-17 01:07:49 +05:00
parent 3df080a79f
commit 6c80281ce9
5 changed files with 79 additions and 13 deletions

View File

@ -1 +1 @@
Sat Jul 12 04:39:49 CDT 2014
Thu Jul 17 01:07:28 CDT 2014

View File

@ -369,6 +369,7 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
{
size_t r;
int sanity = 2000;
int ssl_err = 0;
if (wsh->ssl) {
do {
@ -376,8 +377,17 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
if (sanity < 2000) {
ms_sleep(1);
}
} while (--sanity > 0 && r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE);
if (r == -1) {
ssl_err = SSL_get_error(wsh->ssl, r);
}
} while (--sanity > 0 && r == -1 && ssl_err == SSL_ERROR_WANT_WRITE);
if (ssl_err) {
r = ssl_err * -1;
}
return r;
}
@ -570,6 +580,12 @@ void ws_destroy(wsh_t *wsh)
wsh->down = 2;
if (wsh->write_buffer) {
free(wsh->write_buffer);
wsh->write_buffer = NULL;
wsh->write_buffer_len = 0;
}
if (wsh->ssl) {
int code;
do {
@ -818,6 +834,8 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
{
uint8_t hdr[14] = { 0 };
size_t hlen = 2;
uint8_t *bp;
ssize_t raw_ret = 0;
if (wsh->down) {
return -1;
@ -848,12 +866,25 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
*u64 = htonl(bytes);
}
if (ws_raw_write(wsh, (void *) &hdr[0], hlen) != (ssize_t)hlen) {
return -1;
}
if (wsh->write_buffer_len < (hlen + bytes + 1)) {
void *tmp;
if (ws_raw_write(wsh, data, bytes) != (ssize_t)bytes) {
return -2;
wsh->write_buffer_len = hlen + bytes + 1;
if ((tmp = realloc(wsh->write_buffer, wsh->write_buffer_len))) {
wsh->write_buffer = tmp;
} else {
abort();
}
}
bp = (uint8_t *) wsh->write_buffer;
memcpy(bp, (void *) &hdr[0], hlen);
memcpy(bp + hlen, data, bytes);
raw_ret = ws_raw_write(wsh, bp, (hlen + bytes));
if (raw_ret != (ssize_t) (hlen + bytes)) {
return raw_ret;
}
return bytes;

View File

@ -89,6 +89,8 @@ typedef struct wsh_s {
int secure_established;
int logical_established;
int x;
void *write_buffer;
size_t write_buffer_len;
} wsh_t;
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc);

View File

@ -369,6 +369,7 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
{
size_t r;
int sanity = 2000;
int ssl_err = 0;
if (wsh->ssl) {
do {
@ -376,8 +377,17 @@ ssize_t ws_raw_write(wsh_t *wsh, void *data, size_t bytes)
if (sanity < 2000) {
ms_sleep(1);
}
} while (--sanity > 0 && r == -1 && SSL_get_error(wsh->ssl, r) == SSL_ERROR_WANT_WRITE);
if (r == -1) {
ssl_err = SSL_get_error(wsh->ssl, r);
}
} while (--sanity > 0 && r == -1 && ssl_err == SSL_ERROR_WANT_WRITE);
if (ssl_err) {
r = ssl_err * -1;
}
return r;
}
@ -570,6 +580,12 @@ void ws_destroy(wsh_t *wsh)
wsh->down = 2;
if (wsh->write_buffer) {
free(wsh->write_buffer);
wsh->write_buffer = NULL;
wsh->write_buffer_len = 0;
}
if (wsh->ssl) {
int code;
do {
@ -818,6 +834,8 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
{
uint8_t hdr[14] = { 0 };
size_t hlen = 2;
uint8_t *bp;
ssize_t raw_ret = 0;
if (wsh->down) {
return -1;
@ -848,12 +866,25 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
*u64 = htonl(bytes);
}
if (ws_raw_write(wsh, (void *) &hdr[0], hlen) != (ssize_t)hlen) {
return -1;
}
if (wsh->write_buffer_len < (hlen + bytes + 1)) {
void *tmp;
if (ws_raw_write(wsh, data, bytes) != (ssize_t)bytes) {
return -2;
wsh->write_buffer_len = hlen + bytes + 1;
if ((tmp = realloc(wsh->write_buffer, wsh->write_buffer_len))) {
wsh->write_buffer = tmp;
} else {
abort();
}
}
bp = (uint8_t *) wsh->write_buffer;
memcpy(bp, (void *) &hdr[0], hlen);
memcpy(bp + hlen, data, bytes);
raw_ret = ws_raw_write(wsh, bp, (hlen + bytes));
if (raw_ret != (ssize_t) (hlen + bytes)) {
return raw_ret;
}
return bytes;

View File

@ -89,6 +89,8 @@ typedef struct wsh_s {
int secure_established;
int logical_established;
int x;
void *write_buffer;
size_t write_buffer_len;
} wsh_t;
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc);