X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fwebsock.c;h=c578eba46a714e7667219663083ae3252df96045;hb=fcef933b69ccc363ad10d9f7308f02c5dc474ff6;hp=41e47a0a4eb1880608a7da09a2d376d1aacadad0;hpb=cc4b56b6710624c069642d1a510d0060949fe5b9;p=src%2Fapp-framework-binder.git diff --git a/src/websock.c b/src/websock.c index 41e47a0a..c578eba4 100644 --- a/src/websock.c +++ b/src/websock.c @@ -170,12 +170,12 @@ void websock_pong(struct websock *ws) void websock_text(struct websock *ws, const char *text, size_t length) { - websock_send(ws, OPCODE_TEXT, NULL, 0); + websock_send(ws, OPCODE_TEXT, text, length); } void websock_binary(struct websock *ws, const void *data, size_t length) { - websock_send(ws, OPCODE_BINARY, NULL, 0); + websock_send(ws, OPCODE_BINARY, data, length); } static int read_header(struct websock *ws) @@ -190,9 +190,25 @@ 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_OPCODE(ws->header[0]) == OPCODE_CLOSE) + return FRAME_GET_PAYLOAD_LEN(ws->header[1]) != 1; + if (FRAME_GET_MASK(ws->header[1])) + return 0; + return FRAME_GET_PAYLOAD_LEN(ws->header[1]) == 0; +} + int websock_dispatch(struct websock *ws) { - loop: +loop: switch (ws->state) { case STATE_INIT: ws->lenhead = 0; @@ -201,17 +217,10 @@ int websock_dispatch(struct websock *ws) case STATE_START: /* read the header */ - if (!read_header(ws)) + if (read_header(ws)) 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 @@ int websock_dispatch(struct websock *ws) 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 @@ int websock_dispatch(struct websock *ws) 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])) { @@ -262,7 +265,7 @@ int websock_dispatch(struct websock *ws) case STATE_LENGTH: /* continue to read the header */ - if (!read_header(ws)) + if (read_header(ws)) return -1; else if (ws->lenhead < ws->szhead) return 0; @@ -295,7 +298,30 @@ int websock_dispatch(struct websock *ws) ((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 @@ int websock_dispatch(struct websock *ws) (size_t) ws->length); else ws->itf->on_close(ws->closure, - STATUS_CODE_UNSET, 0); + WEBSOCKET_CODE_NOT_SET, 0); ws->itf->disconnect(ws->closure); return 0; + default: + goto protocol_error; } break; @@ -338,11 +366,11 @@ int websock_dispatch(struct websock *ws) 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,17 +426,18 @@ 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) { result->itf = itf; result->closure = closure; + result->maxlength = 65000; } return result; }