提交 18db50c4 authored 作者: Anthony Minessale's avatar Anthony Minessale

FS-9099 #resolve [Websocket raw frame read timeout is too short]

上级 f705ae23
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, ...@@ -267,26 +267,15 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
msg_iovec_t iov[], msg_iovec_t iov[],
size_t iovlen) size_t iovlen)
{ {
size_t i, j, n, m, size = 0; size_t i, j, m, size = 0;
ssize_t nerror; ssize_t nerror;
tport_ws_t *wstp = (tport_ws_t *)self; tport_ws_t *wstp = (tport_ws_t *)self;
enum { WSBUFSIZE = 2048 }; wstp->wstp_buflen = 0;
for (i = 0; i < iovlen; i = j) { for (i = 0; i < iovlen; i = j) {
char *buf = wstp->wstp_buffer; char *buf = NULL;
unsigned wsbufsize = WSBUFSIZE; unsigned wsbufsize = sizeof(wstp->wstp_buffer);
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);
}
for (j = i, m = 0; buf && j < iovlen; j++) { for (j = i, m = 0; buf && j < iovlen; j++) {
if (m + iov[j].siv_len > wsbufsize) { if (m + iov[j].siv_len > wsbufsize) {
...@@ -304,8 +293,20 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg, ...@@ -304,8 +293,20 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg,
iov[j].siv_base = buf, iov[j].siv_len = m; 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", 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, (void *)&wstp->ws, (void *)iov[i].siv_base, (LU)iov[i].siv_len,
nerror)); nerror));
...@@ -317,17 +318,13 @@ ssize_t tport_send_stream_ws(tport_t const *self, msg_t *msg, ...@@ -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))); SU_DEBUG_3(("ws_write: %s\n", strerror(err)));
return -1; 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; return size;
} }
......
...@@ -56,7 +56,8 @@ typedef enum { ...@@ -56,7 +56,8 @@ typedef enum {
typedef struct tport_ws_s { typedef struct tport_ws_s {
tport_t wstp_tp[1]; tport_t wstp_tp[1];
wsh_t ws; wsh_t ws;
char *wstp_buffer; char wstp_buffer[65536];
size_t wstp_buflen;
SU_S8_T ws_initialized; SU_S8_T ws_initialized;
unsigned ws_secure:1; unsigned ws_secure:1;
unsigned:0; unsigned:0;
......
#include <switch.h>
#include "ws.h" #include "ws.h"
#include <pthread.h> #include <pthread.h>
...@@ -146,7 +147,7 @@ static int cheezy_get_var(char *data, char *name, char *buf, size_t buflen) ...@@ -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); } 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; char *v, *e = 0;
v = strchr(p, ':'); v = strchr(p, ':');
...@@ -264,7 +265,7 @@ int ws_handshake(wsh_t *wsh) ...@@ -264,7 +265,7 @@ int ws_handshake(wsh_t *wsh)
} }
} }
if (bytes > sizeof(wsh->buffer) -1) { if (bytes > wsh->buflen -1) {
goto err; goto err;
} }
...@@ -362,7 +363,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block) ...@@ -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; goto end;
} }
...@@ -382,9 +383,9 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block) ...@@ -382,9 +383,9 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block)
ms_sleep(10); 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; r = -1;
} }
...@@ -596,7 +597,15 @@ int ws_init(wsh_t *wsh, ws_socket_t sock, SSL_CTX *ssl_ctx, int close_sock, int ...@@ -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->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; wsh->secure = ssl_ctx ? 1 : 0;
setup_socket(sock); setup_socket(sock);
...@@ -644,6 +653,12 @@ void ws_destroy(wsh_t *wsh) ...@@ -644,6 +653,12 @@ void ws_destroy(wsh_t *wsh)
SSL_free(wsh->ssl); SSL_free(wsh->ssl);
wsh->ssl = NULL; 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) ssize_t ws_close(wsh_t *wsh, int16_t reason)
...@@ -685,6 +700,20 @@ 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) 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) ...@@ -692,6 +721,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
char *maskp; char *maskp;
int ll = 0; int ll = 0;
int frag = 0; int frag = 0;
int blen;
wsh->body = wsh->bbuffer;
wsh->packetlen = 0;
again: again:
need = 2; need = 2;
...@@ -745,12 +778,11 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -745,12 +778,11 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
int fin = (wsh->buffer[0] >> 7) & 1; int fin = (wsh->buffer[0] >> 7) & 1;
int mask = (wsh->buffer[1] >> 7) & 1; int mask = (wsh->buffer[1] >> 7) & 1;
if (fin) {
if (*oc == WSOC_CONTINUATION) { if (!fin && *oc != WSOC_CONTINUATION) {
frag = 1; frag = 1;
} else { } else if (fin && *oc == WSOC_CONTINUATION) {
frag = 0; frag = 0;
}
} }
if (mask) { if (mask) {
...@@ -765,23 +797,33 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -765,23 +797,33 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
wsh->plen = wsh->buffer[1] & 0x7f; wsh->plen = wsh->buffer[1] & 0x7f;
wsh->payload = &wsh->buffer[2]; wsh->payload = &wsh->buffer[2];
if (wsh->plen == 127) { if (wsh->plen == 127) {
uint64_t *u64; uint64_t *u64;
int more = 0;
need += 8; need += 8;
if (need > wsh->datalen) { if (need > wsh->datalen) {
/* too small - protocol err */ /* too small - protocol err */
*oc = WSOC_CLOSE; //*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR); //return ws_close(wsh, WS_PROTO_ERR);
}
u64 = (uint64_t *) wsh->payload; more = ws_raw_read(wsh, wsh->buffer + wsh->datalen, need - wsh->datalen, WS_BLOCK);
wsh->payload += 8;
if (more < need - wsh->datalen) {
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_PROTO_ERR);
} else {
wsh->datalen += more;
}
wsh->plen = ntohl((u_long)*u64);
}
u64 = (uint64_t *) wsh->payload;
wsh->payload += 8;
wsh->plen = ntoh64(*u64);
} else if (wsh->plen == 126) { } else if (wsh->plen == 126) {
uint16_t *u16; uint16_t *u16;
...@@ -811,16 +853,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -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); return ws_close(wsh, WS_PROTO_ERR);
} }
if ((need + wsh->datalen) > (ssize_t)wsh->buflen) { blen = wsh->body - wsh->bbuffer;
/* too big - Ain't nobody got time fo' dat */
*oc = WSOC_CLOSE; if (need + blen > (ssize_t)wsh->bbuflen) {
return ws_close(wsh, WS_DATA_TOO_BIG); 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; wsh->rplen = wsh->plen - need;
if (wsh->rplen) {
memcpy(wsh->body, wsh->payload, wsh->rplen);
}
while(need) { 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) { if (r < 1) {
/* invalid read - protocol err .. */ /* invalid read - protocol err .. */
...@@ -837,28 +893,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -837,28 +893,30 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
ssize_t i; ssize_t i;
for (i = 0; i < wsh->datalen; i++) { for (i = 0; i < wsh->datalen; i++) {
wsh->payload[i] ^= maskp[i % 4]; wsh->body[i] ^= maskp[i % 4];
} }
} }
if (*oc == WSOC_PING) { 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; goto again;
} }
*(wsh->body+wsh->rplen) = '\0';
wsh->packetlen += wsh->rplen;
wsh->body += wsh->rplen;
if (frag) { if (frag) {
goto again; goto again;
} }
*(wsh->payload+wsh->rplen) = '\0';
*data = (uint8_t *)wsh->payload;
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data); *data = (uint8_t *)wsh->bbuffer;
//printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->packetlen, *oc, (char *)*data);
return wsh->rplen; return wsh->packetlen;
} }
break; break;
default: default:
...@@ -871,36 +929,6 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -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) ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
{ {
uint8_t hdr[14] = { 0 }; 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) ...@@ -934,7 +962,7 @@ ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
hlen += 8; hlen += 8;
u64 = (uint64_t *) &hdr[2]; u64 = (uint64_t *) &hdr[2];
*u64 = htonl(bytes); *u64 = hton64(bytes);
} }
if (wsh->write_buffer_len < (hlen + bytes + 1)) { if (wsh->write_buffer_len < (hlen + bytes + 1)) {
......
...@@ -25,6 +25,17 @@ ...@@ -25,6 +25,17 @@
//#include "sha1.h" //#include "sha1.h"
#include <openssl/ssl.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 #ifdef _MSC_VER
#ifndef strncasecmp #ifndef strncasecmp
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
...@@ -78,15 +89,17 @@ typedef enum { ...@@ -78,15 +89,17 @@ typedef enum {
typedef struct wsh_s { typedef struct wsh_s {
ws_socket_t sock; ws_socket_t sock;
char buffer[65536]; char *buffer;
char wbuffer[65536]; char *bbuffer;
char *body;
char *uri; char *uri;
size_t buflen; size_t buflen;
size_t bbuflen;
ssize_t datalen; ssize_t datalen;
ssize_t wdatalen;
char *payload; char *payload;
ssize_t plen; ssize_t plen;
ssize_t rplen; ssize_t rplen;
ssize_t packetlen;
SSL *ssl; SSL *ssl;
int handshake; int handshake;
uint8_t down; uint8_t down;
......
...@@ -385,7 +385,7 @@ ssize_t ws_raw_read(wsh_t *wsh, void *data, size_t bytes, int block) ...@@ -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); } 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; r = -1;
} }
...@@ -929,7 +929,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ...@@ -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) 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) ...@@ -937,9 +937,9 @@ ssize_t ws_feed_buf(wsh_t *wsh, void *data, size_t bytes)
return -1; 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; return bytes;
} }
...@@ -953,13 +953,13 @@ ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc) ...@@ -953,13 +953,13 @@ ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc)
return -1; 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; wsh->wdatalen = 0;
return r; return r;
} }
#endif
ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes) ssize_t ws_write_frame(wsh_t *wsh, ws_opcode_t oc, void *data, size_t bytes)
{ {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论