From 6c80281ce9c4dc53ee76e1931490947d31c2c39e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 17 Jul 2014 01:07:49 +0500 Subject: [PATCH] buffer websocket headers and body before sending to avoid fragmentation --- libs/sofia-sip/.update | 2 +- libs/sofia-sip/libsofia-sip-ua/tport/ws.c | 43 +++++++++++++++++++---- libs/sofia-sip/libsofia-sip-ua/tport/ws.h | 2 ++ src/mod/endpoints/mod_verto/ws.c | 43 +++++++++++++++++++---- src/mod/endpoints/mod_verto/ws.h | 2 ++ 5 files changed, 79 insertions(+), 13 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 1ff6ae92de..09ad6c7180 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Sat Jul 12 04:39:49 CDT 2014 +Thu Jul 17 01:07:28 CDT 2014 diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 0ee867dba5..3b152e4fec 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -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; diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h index 699779b515..b4d30b47f2 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.h +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.h @@ -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); diff --git a/src/mod/endpoints/mod_verto/ws.c b/src/mod/endpoints/mod_verto/ws.c index 0ee867dba5..3b152e4fec 100644 --- a/src/mod/endpoints/mod_verto/ws.c +++ b/src/mod/endpoints/mod_verto/ws.c @@ -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; diff --git a/src/mod/endpoints/mod_verto/ws.h b/src/mod/endpoints/mod_verto/ws.h index 699779b515..b4d30b47f2 100644 --- a/src/mod/endpoints/mod_verto/ws.h +++ b/src/mod/endpoints/mod_verto/ws.h @@ -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);