FS-9099 #resolve [Websocket raw frame read timeout is too short]
This commit is contained in:
parent
f705ae2384
commit
18db50c46a
|
@ -1 +1 @@
|
|||
Mon Apr 18 10:41:03 CEST 2016
|
||||
Mon Apr 25 17:16:25 CDT 2016
|
||||
|
|
|
@ -267,26 +267,15 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
|
|||
msg_iovec_t iov[],
|
||||
size_t iovlen)
|
||||
{
|
||||
size_t i, j, n, m, size = 0;
|
||||
size_t i, j, m, size = 0;
|
||||
ssize_t nerror;
|
||||
tport_ws_t *wstp = (tport_ws_t *)self;
|
||||
|
||||
enum { WSBUFSIZE = 2048 };
|
||||
wstp->wstp_buflen = 0;
|
||||
|
||||
for (i = 0; i < iovlen; i = j) {
|
||||
char *buf = wstp->wstp_buffer;
|
||||
unsigned wsbufsize = WSBUFSIZE;
|
||||
|
||||
if (i + 1 == iovlen) {
|
||||
buf = NULL; /* Don't bother copying single chunk */
|
||||
}
|
||||
|
||||
if (buf &&
|
||||
(char *)iov[i].siv_base - buf < WSBUFSIZE &&
|
||||
(char *)iov[i].siv_base - buf >= 0) {
|
||||
wsbufsize = buf + WSBUFSIZE - (char *)iov[i].siv_base;
|
||||
assert(wsbufsize <= WSBUFSIZE);
|
||||
}
|
||||
char *buf = NULL;
|
||||
unsigned wsbufsize = sizeof(wstp->wstp_buffer);
|
||||
|
||||
for (j = i, m = 0; buf && j < iovlen; j++) {
|
||||
if (m + iov[j].siv_len > wsbufsize) {
|
||||
|
@ -304,7 +293,19 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
|
|||
iov[j].siv_base = buf, iov[j].siv_len = m;
|
||||
}
|
||||
|
||||
nerror = ws_feed_buf(&wstp->ws, buf, m);
|
||||
nerror = 0;
|
||||
|
||||
if (m + wstp->wstp_buflen >= wsbufsize) {
|
||||
nerror = -1;
|
||||
errno = ENOMEM;
|
||||
} else {
|
||||
if (memcpy(wstp->wstp_buffer + wstp->wstp_buflen, buf, m)) {
|
||||
wstp->wstp_buflen += m;
|
||||
} else {
|
||||
nerror = -1;
|
||||
errno = ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
SU_DEBUG_9(("tport_ws_writevec: vec %p %p %lu ("MOD_ZD")\n",
|
||||
(void *)&wstp->ws, (void *)iov[i].siv_base, (LU)iov[i].siv_len,
|
||||
|
@ -317,17 +318,13 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
|
|||
SU_DEBUG_3(("ws_write: %s\n", strerror(err)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = (size_t)nerror;
|
||||
size += n;
|
||||
|
||||
/* Return if the write buffer is full for now */
|
||||
if (n != m)
|
||||
break;
|
||||
}
|
||||
|
||||
ws_send_buf(&wstp->ws, WSOC_TEXT);
|
||||
|
||||
if (wstp->wstp_buflen) {
|
||||
*(wstp->wstp_buffer + wstp->wstp_buflen) = '\0';
|
||||
ws_write_frame(&wstp->ws, WSOC_TEXT, wstp->wstp_buffer, wstp->wstp_buflen);
|
||||
size = wstp->wstp_buflen;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,8 @@ typedef enum {
|
|||
typedef struct tport_ws_s {
|
||||
tport_t wstp_tp[1];
|
||||
wsh_t ws;
|
||||
char *wstp_buffer;
|
||||
char wstp_buffer[65536];
|
||||
size_t wstp_buflen;
|
||||
SU_S8_T ws_initialized;
|
||||
unsigned ws_secure:1;
|
||||
unsigned:0;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <switch.h>
|
||||
#include "ws.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
@ -146,7 +147,7 @@ static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen)
|
|||
} while((p = (strstr(p,"\n")+1))!=(char *)1);
|
||||
|
||||
|
||||
if (p != (char *)1 && *p!='\0') {
|
||||
if (p && p != (char *)1 && *p!='\0') {
|
||||
char *v, *e = 0;
|
||||
|
||||
v = strchr(p, ':');
|
||||
|
@ -264,7 +265,7 @@ int ws_handshake(wsh_t *wsh)
|
|||
}
|
||||
}
|
||||
|
||||
if (bytes > sizeof(wsh->buffer) -1) {
|
||||
if (bytes > wsh->buflen -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -362,7 +363,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
|
|||
}
|
||||
}
|
||||
|
||||
} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 100);
|
||||
} while (r == -1 && err == SSL_ERROR_WANT_READ && wsh->x < 1000);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
@ -382,9 +383,9 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
|
|||
ms_sleep(10);
|
||||
}
|
||||
}
|
||||
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 100);
|
||||
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 1000);
|
||||
|
||||
if (wsh->x >= 1000 || (block && wsh->x >= 100)) {
|
||||
if (wsh->x >= 10000 || (block && wsh->x >= 1000)) {
|
||||
r = -1;
|
||||
}
|
||||
|
||||
|
@ -596,7 +597,15 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int
|
|||
wsh->close_sock = 1;
|
||||
}
|
||||
|
||||
wsh->buflen = sizeof(wsh->buffer);
|
||||
wsh->buflen = 1024 * 64;
|
||||
wsh->bbuflen = wsh->buflen;
|
||||
|
||||
wsh->buffer = malloc(wsh->buflen);
|
||||
wsh->bbuffer = malloc(wsh->bbuflen);
|
||||
//printf("init %p %ld\n", (void *) wsh->bbuffer, wsh->bbuflen);
|
||||
//memset(wsh->buffer, 0, wsh->buflen);
|
||||
//memset(wsh->bbuffer, 0, wsh->bbuflen);
|
||||
|
||||
wsh->secure = ssl_ctx ? 1 : 0;
|
||||
|
||||
setup_socket(sock);
|
||||
|
@ -644,6 +653,12 @@ void ws_destroy(wsh_t *wsh)
|
|||
SSL_free(wsh->ssl);
|
||||
wsh->ssl = NULL;
|
||||
}
|
||||
|
||||
if (wsh->buffer) free(wsh->buffer);
|
||||
if (wsh->bbuffer) free(wsh->bbuffer);
|
||||
|
||||
wsh->buffer = wsh->bbuffer = NULL;
|
||||
|
||||
}
|
||||
|
||||
ssize_t ws_close(wsh_t *wsh, int16_t reason)
|
||||
|
@ -685,6 +700,20 @@ ssize_t ws_close(wsh_t *wsh, int16_t reason)
|
|||
|
||||
}
|
||||
|
||||
|
||||
uint64_t hton64(uint64_t val)
|
||||
{
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN) return (val);
|
||||
else return __bswap_64(val);
|
||||
}
|
||||
|
||||
uint64_t ntoh64(uint64_t val)
|
||||
{
|
||||
if (__BYTE_ORDER == __BIG_ENDIAN) return (val);
|
||||
else return __bswap_64(val);
|
||||
}
|
||||
|
||||
|
||||
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
||||
{
|
||||
|
||||
|
@ -692,6 +721,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
char *maskp;
|
||||
int ll = 0;
|
||||
int frag = 0;
|
||||
int blen;
|
||||
|
||||
wsh->body = wsh->bbuffer;
|
||||
wsh->packetlen = 0;
|
||||
|
||||
again:
|
||||
need = 2;
|
||||
|
@ -745,13 +778,12 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
int fin = (wsh->buffer[0] >> 7) & 1;
|
||||
int mask = (wsh->buffer[1] >> 7) & 1;
|
||||
|
||||
if (fin) {
|
||||
if (*oc == WSOC_CONTINUATION) {
|
||||
|
||||
if (!fin && *oc != WSOC_CONTINUATION) {
|
||||
frag = 1;
|
||||
} else {
|
||||
} else if (fin && *oc == WSOC_CONTINUATION) {
|
||||
frag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
need += 4;
|
||||
|
@ -768,20 +800,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
|
||||
if (wsh->plen == 127) {
|
||||
uint64_t *u64;
|
||||
int more = 0;
|
||||
|
||||
need += 8;
|
||||
|
||||
if (need > wsh->datalen) {
|
||||
/* too small - protocol err */
|
||||
//*oc = WSOC_CLOSE;
|
||||
//return ws_close(wsh, WS_PROTO_ERR);
|
||||
|
||||
more = ws_raw_read(wsh, wsh->buffer + wsh->datalen, need - wsh->datalen, WS_BLOCK);
|
||||
|
||||
if (more < need - wsh->datalen) {
|
||||
*oc = WSOC_CLOSE;
|
||||
return ws_close(wsh, WS_PROTO_ERR);
|
||||
} else {
|
||||
wsh->datalen += more;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
u64 = (uint64_t *) wsh->payload;
|
||||
wsh->payload += 8;
|
||||
|
||||
wsh->plen = ntohl((u_long)*u64);
|
||||
|
||||
wsh->plen = ntoh64(*u64);
|
||||
} else if (wsh->plen == 126) {
|
||||
uint16_t *u16;
|
||||
|
||||
|
@ -811,16 +853,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
return ws_close(wsh, WS_PROTO_ERR);
|
||||
}
|
||||
|
||||
if ((need + wsh->datalen) > (ssize_t)wsh->buflen) {
|
||||
/* too big - Ain't nobody got time fo' dat */
|
||||
*oc = WSOC_CLOSE;
|
||||
return ws_close(wsh, WS_DATA_TOO_BIG);
|
||||
blen = wsh->body - wsh->bbuffer;
|
||||
|
||||
if (need + blen > (ssize_t)wsh->bbuflen) {
|
||||
void *tmp;
|
||||
|
||||
wsh->bbuflen = need + blen + wsh->rplen;
|
||||
|
||||
if ((tmp = realloc(wsh->bbuffer, wsh->bbuflen))) {
|
||||
wsh->bbuffer = tmp;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
wsh->body = wsh->bbuffer + blen;
|
||||
}
|
||||
|
||||
wsh->rplen = wsh->plen - need;
|
||||
|
||||
if (wsh->rplen) {
|
||||
memcpy(wsh->body, wsh->payload, wsh->rplen);
|
||||
}
|
||||
|
||||
while(need) {
|
||||
ssize_t r = ws_raw_read(wsh, wsh->payload + wsh->rplen, need, WS_BLOCK);
|
||||
ssize_t r = ws_raw_read(wsh, wsh->body + wsh->rplen, need, WS_BLOCK);
|
||||
|
||||
if (r < 1) {
|
||||
/* invalid read - protocol err .. */
|
||||
|
@ -837,28 +893,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
ssize_t i;
|
||||
|
||||
for (i = 0; i < wsh->datalen; i++) {
|
||||
wsh->payload[i] ^= maskp[i % 4];
|
||||
wsh->body[i] ^= maskp[i % 4];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (*oc == WSOC_PING) {
|
||||
ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen);
|
||||
ws_write_frame(wsh, WSOC_PONG, wsh->body, wsh->rplen);
|
||||
goto again;
|
||||
}
|
||||
|
||||
*(wsh->body+wsh->rplen) = '\0';
|
||||
wsh->packetlen += wsh->rplen;
|
||||
wsh->body += wsh->rplen;
|
||||
|
||||
if (frag) {
|
||||
goto again;
|
||||
}
|
||||
|
||||
*data = (uint8_t *)wsh->bbuffer;
|
||||
|
||||
*(wsh->payload+wsh->rplen) = '\0';
|
||||
*data = (uint8_t *)wsh->payload;
|
||||
|
||||
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data);
|
||||
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->packetlen, *oc, (char *)*data);
|
||||
|
||||
|
||||
return wsh->rplen;
|
||||
return wsh->packetlen;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -871,36 +929,6 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
|
||||
{
|
||||
|
||||
if (bytes + wsh->wdatalen > wsh->buflen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(wsh->wbuffer + wsh->wdatalen, data, bytes);
|
||||
|
||||
wsh->wdatalen += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
|
||||
{
|
||||
ssize_t r = 0;
|
||||
|
||||
if (!wsh->wdatalen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = ws_write_frame(wsh, oc, wsh->wbuffer, wsh->wdatalen);
|
||||
|
||||
wsh->wdatalen = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
|
||||
{
|
||||
uint8_t hdr[14] = { 0 };
|
||||
|
@ -934,7 +962,7 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
|
|||
hlen += 8;
|
||||
|
||||
u64 = (uint64_t *) &hdr[2];
|
||||
*u64 = htonl(bytes);
|
||||
*u64 = hton64(bytes);
|
||||
}
|
||||
|
||||
if (wsh->write_buffer_len < (hlen + bytes + 1)) {
|
||||
|
|
|
@ -25,6 +25,17 @@
|
|||
//#include "sha1.h"
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#if defined(_MSC_VER) || defined(__APPLE__) || defined(__FreeBSD__) || (defined(__SVR4) && defined(__sun))
|
||||
#define __bswap_64(x) \
|
||||
x = (x>>56) | \
|
||||
((x<<40) & 0x00FF000000000000) | \
|
||||
((x<<24) & 0x0000FF0000000000) | \
|
||||
((x<<8) & 0x000000FF00000000) | \
|
||||
((x>>8) & 0x00000000FF000000) | \
|
||||
((x>>24) & 0x0000000000FF0000) | \
|
||||
((x>>40) & 0x000000000000FF00) | \
|
||||
(x<<56)
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#ifndef strncasecmp
|
||||
#define strncasecmp _strnicmp
|
||||
|
@ -78,15 +89,17 @@ typedef enum {
|
|||
|
||||
typedef struct wsh_s {
|
||||
ws_socket_t sock;
|
||||
char buffer[65536];
|
||||
char wbuffer[65536];
|
||||
char *buffer;
|
||||
char *bbuffer;
|
||||
char *body;
|
||||
char *uri;
|
||||
size_t buflen;
|
||||
size_t bbuflen;
|
||||
ssize_t datalen;
|
||||
ssize_t wdatalen;
|
||||
char *payload;
|
||||
ssize_t plen;
|
||||
ssize_t rplen;
|
||||
ssize_t packetlen;
|
||||
SSL *ssl;
|
||||
int handshake;
|
||||
uint8_t down;
|
||||
|
|
|
@ -385,7 +385,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
|
|||
}
|
||||
} while (r == -1 && xp_is_blocking(xp_errno()) && wsh->x < 1000);
|
||||
|
||||
if (wsh->x >= 1000 || (block && wsh->x >= 100)) {
|
||||
if (wsh->x >= 10000 || (block && wsh->x >= 1000)) {
|
||||
r = -1;
|
||||
}
|
||||
|
||||
|
@ -929,7 +929,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
|
||||
{
|
||||
|
||||
|
@ -937,9 +937,9 @@ ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
|
|||
return -1;
|
||||
}
|
||||
|
||||
memcpy(wsh->wbuffer + wsh->wdatalen, data, bytes);
|
||||
memcpy((unsigned char *)wsh->write_buffer + wsh->write_buffer_len, data, bytes);
|
||||
|
||||
wsh->wdatalen += bytes;
|
||||
wsh->write_buffer_len += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
@ -953,13 +953,13 @@ ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
|
|||
return -1;
|
||||
}
|
||||
|
||||
r = ws_write_frame(wsh, oc, wsh->wbuffer, wsh->wdatalen);
|
||||
r = ws_write_frame(wsh, oc, wsh->write_buffer, wsh->write_buffer_len);
|
||||
|
||||
wsh->wdatalen = 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue