summaryrefslogtreecommitdiffstats
path: root/src/websock.c
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2016-04-07 19:57:25 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2016-04-07 19:57:25 +0200
commit911df9d068b3e259dcab970ded4132a7397f565f (patch)
treeaa514a649d95c13fa6dffa048584ff35d7870464 /src/websock.c
parent5d088cbac7130e9ec8655218acb15dd22b20a7f8 (diff)
improves websockets
Change-Id: I5b941a043838d438c0acc31623ce9361fa742f35 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'src/websock.c')
-rw-r--r--src/websock.c72
1 files changed, 50 insertions, 22 deletions
diff --git a/src/websock.c b/src/websock.c
index 22e91be9..e583a49d 100644
--- a/src/websock.c
+++ b/src/websock.c
@@ -190,6 +190,22 @@ static int read_header(struct websock *ws)
return 0;
}
+static int check_control_header(struct websock *ws)
+{
+ /* sanity checks */
+ if (FRAME_GET_RSV1(ws->header[0]) != 0)
+ return 0;
+ if (FRAME_GET_RSV2(ws->header[0]) != 0)
+ return 0;
+ if (FRAME_GET_RSV3(ws->header[0]) != 0)
+ return 0;
+ if (FRAME_GET_MASK(ws->header[1]))
+ return 0;
+ if (FRAME_GET_OPCODE(ws->header[0]) == OPCODE_CLOSE)
+ return FRAME_GET_PAYLOAD_LEN(ws->header[1]) != 1;
+ return FRAME_GET_PAYLOAD_LEN(ws->header[1]) == 0;
+}
+
int websock_dispatch(struct websock *ws)
{
loop:
@@ -205,13 +221,6 @@ loop:
return -1;
else if (ws->lenhead < ws->szhead)
return 0;
- /* sanity checks */
- if (FRAME_GET_RSV1(ws->header[0]) != 0)
- goto protocol_error;
- if (FRAME_GET_RSV2(ws->header[0]) != 0)
- goto protocol_error;
- if (FRAME_GET_RSV3(ws->header[0]) != 0)
- goto protocol_error;
/* fast track */
switch (FRAME_GET_OPCODE(ws->header[0])) {
case OPCODE_CONTINUATION:
@@ -219,17 +228,13 @@ loop:
case OPCODE_BINARY:
break;
case OPCODE_CLOSE:
- if (FRAME_GET_MASK(ws->header[1]))
- goto protocol_error;
- if (FRAME_GET_PAYLOAD_LEN(ws->header[1]) == 1)
+ if (!check_control_header(ws))
goto protocol_error;
if (FRAME_GET_PAYLOAD_LEN(ws->header[1]))
ws->szhead += 2;
break;
case OPCODE_PING:
- if (FRAME_GET_MASK(ws->header[1]))
- goto protocol_error;
- if (FRAME_GET_PAYLOAD_LEN(ws->header[1]) != 0)
+ if (!check_control_header(ws))
goto protocol_error;
if (ws->itf->on_ping)
ws->itf->on_ping(ws->closure);
@@ -238,16 +243,14 @@ loop:
ws->state = STATE_INIT;
goto loop;
case OPCODE_PONG:
- if (FRAME_GET_MASK(ws->header[1]))
- goto protocol_error;
- if (FRAME_GET_PAYLOAD_LEN(ws->header[1]) != 0)
+ if (!check_control_header(ws))
goto protocol_error;
if (ws->itf->on_pong)
ws->itf->on_pong(ws->closure);
ws->state = STATE_INIT;
goto loop;
default:
- goto protocol_error;
+ break;
}
/* update heading size */
switch (FRAME_GET_PAYLOAD_LEN(ws->header[1])) {
@@ -295,7 +298,30 @@ loop:
((unsigned char *)&ws->mask)[3] = ws->header[ws->szhead - 1];
} else
ws->mask = 0;
+
+ /* all heading fields are known, process */
ws->state = STATE_DATA;
+ if (ws->itf->on_extension != NULL) {
+ if (ws->itf->on_extension(ws->closure,
+ FRAME_GET_FIN(ws->header[0]),
+ FRAME_GET_RSV1(ws->header[0]),
+ FRAME_GET_RSV2(ws->header[0]),
+ FRAME_GET_RSV3(ws->header[0]),
+ FRAME_GET_OPCODE(ws->header[0]),
+ (size_t) ws->length)) {
+ return 0;
+ }
+ }
+
+ /* not an extension case */
+ if (FRAME_GET_RSV1(ws->header[0]) != 0)
+ goto protocol_error;
+ if (FRAME_GET_RSV2(ws->header[0]) != 0)
+ goto protocol_error;
+ if (FRAME_GET_RSV3(ws->header[0]) != 0)
+ goto protocol_error;
+
+ /* handle */
switch (FRAME_GET_OPCODE(ws->header[0])) {
case OPCODE_CONTINUATION:
ws->itf->on_continue(ws->closure,
@@ -320,9 +346,11 @@ loop:
(size_t) ws->length);
else
ws->itf->on_close(ws->closure,
- STATUS_CODE_UNSET, 0);
+ WEBSOCKET_CODE_UNSET, 0);
ws->itf->disconnect(ws->closure);
return 0;
+ default:
+ goto protocol_error;
}
break;
@@ -338,11 +366,11 @@ loop:
goto loop;
too_long_error:
- websock_close_code(ws, STATUS_CODE_MESSAGE_TOO_LARGE);
+ websock_close_code(ws, WEBSOCKET_CODE_MESSAGE_TOO_LARGE);
return 0;
protocol_error:
- websock_close_code(ws, STATUS_CODE_PROTOCOL_ERROR);
+ websock_close_code(ws, WEBSOCKET_CODE_PROTOCOL_ERROR);
return 0;
}
@@ -398,12 +426,12 @@ ssize_t websock_read(struct websock * ws, void *buffer, size_t size)
void websock_drop(struct websock *ws)
{
- char buffer[4096];
+ char buffer[8000];
while (ws->length && ws_read(ws, buffer, sizeof buffer) >= 0) ;
}
-struct websock *websock_create(const struct websock_itf *itf, void *closure)
+struct websock *websock_create_v13(const struct websock_itf *itf, void *closure)
{
struct websock *result = calloc(1, sizeof *result);
if (result) {