diff --git a/deps/wslay/.gitignore b/deps/wslay/.gitignore index 50ec1376..189ef711 100644 --- a/deps/wslay/.gitignore +++ b/deps/wslay/.gitignore @@ -27,3 +27,17 @@ stamp-h1 INSTALL .DS_STORE tests/main +tests/main.log +tests/main.trs +tests/test-suite.log +/compile +/test-driver +/build.* +doc/man +doc/sphinx/_build +/CMakeFiles/ +/cmake_install.cmake +/lib/cmake_install.cmake +/lib/libwslay.a +/wslay-config.cmake +/wslay.cmake diff --git a/deps/wslay/README.rst b/deps/wslay/README.rst index 1396b777..446539dc 100644 --- a/deps/wslay/README.rst +++ b/deps/wslay/README.rst @@ -1,7 +1,7 @@ Wslay - The WebSocket library ============================= -Project Web: http://wslay.sourceforge.net/ +Project Web: https://github.com/tatsuhiro-t/wslay Wslay is a WebSocket library written in C. It implements the protocol version 13 described in @@ -34,7 +34,8 @@ and Requirements ------------ -`Sphinx `_ is used to generate man pages. +`Sphinx `_ is used to generate +man pages. To build and run the unit test programs, the following packages are needed: diff --git a/deps/wslay/lib/includes/wslay/wslay.h b/deps/wslay/lib/includes/wslay/wslay.h index 71db0ac2..2fde81a4 100644 --- a/deps/wslay/lib/includes/wslay/wslay.h +++ b/deps/wslay/lib/includes/wslay/wslay.h @@ -145,10 +145,15 @@ enum wslay_opcode { #define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1) /* - * Macros that returns reserved bits: RSV1, RSV2, RSV3. These macros - * assumes that rsv is constructed by ((RSV1 << 2) | (RSV2 << 1) | - * RSV3) + * Macros that represent and return reserved bits: RSV1, RSV2, RSV3. + * These macros assume that rsv is constructed by ((RSV1 << 2) | + * (RSV2 << 1) | RSV3) */ +#define WSLAY_RSV_NONE ((uint8_t) 0) +#define WSLAY_RSV1_BIT (((uint8_t) 1) << 2) +#define WSLAY_RSV2_BIT (((uint8_t) 1) << 1) +#define WSLAY_RSV3_BIT (((uint8_t) 1) << 0) + #define wslay_get_rsv1(rsv) ((rsv >> 2) & 1) #define wslay_get_rsv2(rsv) ((rsv >> 1) & 1) #define wslay_get_rsv3(rsv) (rsv & 1) @@ -201,7 +206,7 @@ void wslay_frame_context_free(wslay_frame_context_ptr ctx); * 1 if this is masked frame, otherwise 0. iocb->payload_length is * the payload_length of this frame. iocb->data must point to the * payload data to be sent. iocb->data_length must be the length of - * the data. This function calls recv_callback function if it needs + * the data. This function calls send_callback function if it needs * to send bytes. This function calls gen_mask_callback function if * it needs new mask key. This function returns the number of payload * bytes sent. Please note that it does not include any number of @@ -407,6 +412,16 @@ int wslay_event_context_client_init */ void wslay_event_context_free(wslay_event_context_ptr ctx); +/* + * Sets a bit mask of allowed reserved bits. + * Currently only permitted values are WSLAY_RSV1_BIT to allow PMCE + * extension (see RFC-7692) or WSLAY_RSV_NONE to disable. + * + * Default: WSLAY_RSV_NONE + */ +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv); + /* * Enables or disables buffering of an entire message for non-control * frames. If val is 0, buffering is enabled. Otherwise, buffering is @@ -550,6 +565,12 @@ struct wslay_event_msg { int wslay_event_queue_msg(wslay_event_context_ptr ctx, const struct wslay_event_msg *arg); +/* + * Extended version of wslay_event_queue_msg which allows to set reserved bits. + */ +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv); + /* * Specify "source" to generate message. */ @@ -607,6 +628,13 @@ struct wslay_event_fragmented_msg { int wslay_event_queue_fragmented_msg (wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg); +/* + * Extended version of wslay_event_queue_fragmented_msg which allows to set + * reserved bits. + */ +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv); + /* * Queues close control frame. This function is provided just for * convenience. wslay_event_queue_msg() can queue a close control diff --git a/deps/wslay/lib/wslay_event.c b/deps/wslay/lib/wslay_event.c index cc8b0e92..57415c51 100644 --- a/deps/wslay/lib/wslay_event.c +++ b/deps/wslay/lib/wslay_event.c @@ -206,7 +206,7 @@ static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len) } static int wslay_event_omsg_non_fragmented_init -(struct wslay_event_omsg **m, uint8_t opcode, +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, const uint8_t *msg, size_t msg_length) { *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); @@ -216,6 +216,7 @@ static int wslay_event_omsg_non_fragmented_init memset(*m, 0, sizeof(struct wslay_event_omsg)); (*m)->fin = 1; (*m)->opcode = opcode; + (*m)->rsv = rsv; (*m)->type = WSLAY_NON_FRAGMENTED; if(msg_length) { (*m)->data = (uint8_t*)malloc(msg_length); @@ -230,7 +231,7 @@ static int wslay_event_omsg_non_fragmented_init } static int wslay_event_omsg_fragmented_init -(struct wslay_event_omsg **m, uint8_t opcode, +(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, const union wslay_event_msg_source source, wslay_event_fragmented_msg_callback read_callback) { @@ -240,6 +241,7 @@ static int wslay_event_omsg_fragmented_init } memset(*m, 0, sizeof(struct wslay_event_omsg)); (*m)->opcode = opcode; + (*m)->rsv = rsv; (*m)->type = WSLAY_FRAGMENTED; (*m)->source = source; (*m)->read_callback = read_callback; @@ -301,7 +303,9 @@ int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, } else { ncode = htons(status_code); memcpy(msg, &ncode, 2); - memcpy(msg+2, reason, reason_length); + if(reason_length) { + memcpy(msg+2, reason, reason_length); + } msg_length = reason_length+2; } arg.opcode = WSLAY_CONNECTION_CLOSE; @@ -328,19 +332,33 @@ static int wslay_event_queue_close_wrapper return 0; } +static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv) +{ + return ((rsv & ~ctx->allowed_rsv_bits) == 0); +} + int wslay_event_queue_msg(wslay_event_context_ptr ctx, const struct wslay_event_msg *arg) +{ + return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_msg *arg, uint8_t rsv) { int r; struct wslay_event_omsg *omsg; if(!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; } - if(wslay_is_ctrl_frame(arg->opcode) && arg->msg_length > 125) { + /* RSV1 is not allowed for control frames */ + if((wslay_is_ctrl_frame(arg->opcode) && + (arg->msg_length > 125 || wslay_get_rsv1(rsv))) + || !wslay_event_verify_rsv_bits(ctx, rsv)) { return WSLAY_ERR_INVALID_ARGUMENT; } if((r = wslay_event_omsg_non_fragmented_init - (&omsg, arg->opcode, arg->msg, arg->msg_length)) != 0) { + (&omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { return r; } if(wslay_is_ctrl_frame(arg->opcode)) { @@ -359,17 +377,24 @@ int wslay_event_queue_msg(wslay_event_context_ptr ctx, int wslay_event_queue_fragmented_msg (wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) +{ + return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE); +} + +int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, + const struct wslay_event_fragmented_msg *arg, uint8_t rsv) { int r; struct wslay_event_omsg *omsg; if(!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; } - if(wslay_is_ctrl_frame(arg->opcode)) { + if(wslay_is_ctrl_frame(arg->opcode) || + !wslay_event_verify_rsv_bits(ctx, rsv)) { return WSLAY_ERR_INVALID_ARGUMENT; } if((r = wslay_event_omsg_fragmented_init - (&omsg, arg->opcode, arg->source, arg->read_callback)) != 0) { + (&omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { return r; } if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { @@ -547,9 +572,11 @@ int wslay_event_recv(wslay_event_context_ptr ctx) r = wslay_frame_recv(ctx->frame_ctx, &iocb); if(r >= 0) { int new_frame = 0; - /* We only allow rsv == 0 ATM. */ - if(iocb.rsv != 0 || - ((ctx->server && !iocb.mask) || (!ctx->server && iocb.mask))) { + /* RSV1 is not allowed on control and continuation frames */ + if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || + (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) || + iocb.opcode == WSLAY_CONTINUATION_FRAME)) || + (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) { if((r = wslay_event_queue_close_wrapper (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { return r; @@ -608,8 +635,10 @@ int wslay_event_recv(wslay_event_context_ptr ctx) } } } - if(ctx->imsg->opcode == WSLAY_TEXT_FRAME || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + /* If RSV1 bit is set then it is too early for utf-8 validation */ + if((!wslay_get_rsv1(ctx->imsg->rsv) && + ctx->imsg->opcode == WSLAY_TEXT_FRAME) || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { size_t i; if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { i = 2; @@ -815,6 +844,7 @@ int wslay_event_send(wslay_event_context_ptr ctx) memset(&iocb, 0, sizeof(iocb)); iocb.fin = 1; iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; iocb.mask = ctx->server^1; iocb.data = ctx->omsg->data+ctx->opayloadoff; iocb.data_length = ctx->opayloadlen-ctx->opayloadoff; @@ -871,6 +901,7 @@ int wslay_event_send(wslay_event_context_ptr ctx) memset(&iocb, 0, sizeof(iocb)); iocb.fin = ctx->omsg->fin; iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; iocb.mask = ctx->server ? 0 : 1; iocb.data = ctx->obufmark; iocb.data_length = ctx->obuflimit-ctx->obufmark; @@ -886,6 +917,8 @@ int wslay_event_send(wslay_event_context_ptr ctx) ctx->omsg = NULL; } else { ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; + /* RSV1 is not set on continuation frames */ + ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT; } } else { break; @@ -951,6 +984,13 @@ int wslay_event_get_close_sent(wslay_event_context_ptr ctx) return (ctx->close_status & WSLAY_CLOSE_SENT) > 0; } +void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv) +{ + /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */ + ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT; +} + void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) { if(val) { diff --git a/deps/wslay/lib/wslay_event.h b/deps/wslay/lib/wslay_event.h index f1826cb8..36feb903 100644 --- a/deps/wslay/lib/wslay_event.h +++ b/deps/wslay/lib/wslay_event.h @@ -56,6 +56,7 @@ enum wslay_event_msg_type { struct wslay_event_omsg { uint8_t fin; uint8_t opcode; + uint8_t rsv; enum wslay_event_msg_type type; uint8_t *data; @@ -135,6 +136,7 @@ struct wslay_event_context { struct wslay_event_callbacks callbacks; struct wslay_event_frame_user_data frame_user_data; void *user_data; + uint8_t allowed_rsv_bits; }; #endif /* WSLAY_EVENT_H */ diff --git a/deps/wslay/tests/main.c b/deps/wslay/tests/main.c index 360a6d4a..66a387c3 100644 --- a/deps/wslay/tests/main.c +++ b/deps/wslay/tests/main.c @@ -44,6 +44,7 @@ static int clean_suite1(void) int main(void) { CU_pSuite pSuite = NULL; + unsigned int num_tests_failed; /* initialize the CUnit test registry */ if (CUE_SUCCESS != CU_initialize_registry()) @@ -93,8 +94,14 @@ int main(void) test_wslay_event_send_fragmented_msg) || !CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_ctrl", test_wslay_event_send_fragmented_msg_with_ctrl) || + !CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_rsv1", + test_wslay_event_send_fragmented_msg_with_rsv1) || + !CU_add_test(pSuite, "wslay_event_send_msg_with_rsv1", + test_wslay_event_send_msg_with_rsv1) || !CU_add_test(pSuite, "wslay_event_send_ctrl_msg_first", test_wslay_event_send_ctrl_msg_first) || + !CU_add_test(pSuite, "wslay_event_send_ctrl_msg_with_rsv1", + test_wslay_event_send_ctrl_msg_with_rsv1) || !CU_add_test(pSuite, "wslay_event_queue_close", test_wslay_event_queue_close) || !CU_add_test(pSuite, "wslay_event_queue_close_without_code", @@ -109,10 +116,14 @@ int main(void) test_wslay_event_callback_failure) || !CU_add_test(pSuite, "wslay_event_no_buffering", test_wslay_event_no_buffering) || + !CU_add_test(pSuite, "wslay_event_recv_text_frame_with_rsv1", + test_wslay_event_recv_text_frame_with_rsv1) || !CU_add_test(pSuite, "wslay_event_frame_too_big", test_wslay_event_frame_too_big) || !CU_add_test(pSuite, "wslay_event_message_too_big", test_wslay_event_message_too_big) || + !CU_add_test(pSuite, "wslay_event_config_set_allowed_rsv_bits", + test_wslay_event_config_set_allowed_rsv_bits) || !CU_add_test(pSuite, "wslay_queue", test_wslay_queue)) { CU_cleanup_registry(); return CU_get_error(); @@ -121,6 +132,12 @@ int main(void) /* Run all tests using the CUnit Basic interface */ CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests(); + num_tests_failed = CU_get_number_of_tests_failed(); CU_cleanup_registry(); - return CU_get_error(); + if (CU_get_error() == CUE_SUCCESS) { + return (int)num_tests_failed; + } else { + printf("CUnit Error: %s\n", CU_get_error_msg()); + return CU_get_error(); + } } diff --git a/deps/wslay/tests/wslay_event_test.c b/deps/wslay/tests/wslay_event_test.c index 983b3bc2..b023b89b 100644 --- a/deps/wslay/tests/wslay_event_test.c +++ b/deps/wslay/tests/wslay_event_test.c @@ -214,6 +214,71 @@ void test_wslay_event_send_fragmented_msg_with_ctrl(void) wslay_event_context_free(ctx); } +void test_wslay_event_send_fragmented_msg_with_rsv1(void) +{ + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct my_user_data ud; + struct accumulator acc; + const char msg[] = "Hello"; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + const uint8_t ans[] = { + 0x41, 0x03, 0x48, 0x65, 0x6c, + 0x80, 0x02, 0x6c, 0x6f + }; + scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)-1); + df.feedseq[0] = 3; + df.feedseq[1] = 2; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = accumulator_send_callback; + memset(&acc, 0, sizeof(acc)); + ud.acc = &acc; + wslay_event_context_server_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == + wslay_event_queue_fragmented_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); + CU_ASSERT(0 == wslay_event_send(ctx)); + CU_ASSERT_EQUAL(9, acc.length); + CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length)); + wslay_event_context_free(ctx); +} + +void test_wslay_event_send_msg_with_rsv1(void) +{ + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct my_user_data ud; + struct accumulator acc; + const char msg[] = "Hello"; + struct wslay_event_msg arg; + const uint8_t ans[] = { + 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + }; + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = accumulator_send_callback; + memset(&acc, 0, sizeof(acc)); + ud.acc = &acc; + wslay_event_context_server_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.msg = (const uint8_t*)msg; + arg.msg_length = 5; + CU_ASSERT(0 == wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); + CU_ASSERT(0 == wslay_event_send(ctx)); + CU_ASSERT(7 == acc.length); + CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length)); + wslay_event_context_free(ctx); +} + void test_wslay_event_send_ctrl_msg_first(void) { wslay_event_context_ptr ctx; @@ -246,6 +311,26 @@ void test_wslay_event_send_ctrl_msg_first(void) wslay_event_context_free(ctx); } +void test_wslay_event_send_ctrl_msg_with_rsv1(void) +{ + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct wslay_event_msg arg; + + memset(&callbacks, 0, sizeof(callbacks)); + + wslay_event_context_server_init(&ctx, &callbacks, NULL); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_PING; + arg.msg_length = 0; + CU_ASSERT(WSLAY_ERR_INVALID_ARGUMENT == + wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); + + wslay_event_context_free(ctx); +} + void test_wslay_event_queue_close(void) { wslay_event_context_ptr ctx; @@ -422,6 +507,89 @@ void test_wslay_event_no_buffering(void) wslay_event_context_free(ctx); } +static void +text_rsv1_on_msg_recv_callback(wslay_event_context_ptr ctx, + const struct wslay_event_on_msg_recv_arg *arg, + void *user_data) +{ + CU_ASSERT(WSLAY_TEXT_FRAME == arg->opcode); + CU_ASSERT(WSLAY_RSV1_BIT == arg->rsv); +} + +void test_wslay_event_recv_text_frame_with_rsv1(void) +{ + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct my_user_data ud; + const uint8_t msg[] = { + 0xc1, 0x07, 0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00 // "Hello" pm-deflate + }; + const uint8_t fragmented[] = { + 0x41, 0x03, 0xf2, 0x48, 0xcd, // First fragment + 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00 // Second fragment, RSV1 bit off + }; + const uint8_t bad_fragment[] = { + 0x41, 0x03, 0xf2, 0x48, 0xcd, + 0xc0, 0x04, 0xc9, 0xc9, 0x07, 0x00 // RSV1 bit on + }; + const uint8_t pingmsg[] = { + 0xc9, 0x03, 0x46, 0x6f, 0x6f /* ping with "Foo" */ + }; + struct scripted_data_feed df; + + /* Message marked with RSV1 should skip UTF-8 validation */ + scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + memset(&callbacks, 0, sizeof(callbacks)); + ud.df = &df; + callbacks.recv_callback = scripted_recv_callback; + callbacks.on_msg_recv_callback = text_rsv1_on_msg_recv_callback; + wslay_event_context_client_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + CU_ASSERT(0 == wslay_event_recv(ctx)); + CU_ASSERT(0 == wslay_event_want_write(ctx)); + wslay_event_context_free(ctx); + + /* UTF-8 validation is skipped for continuation frames if the + * initial frame was marked with RSV1 bit */ + scripted_data_feed_init(&df, (const uint8_t*)fragmented, sizeof(fragmented)); + memset(&callbacks, 0, sizeof(callbacks)); + ud.df = &df; + callbacks.recv_callback = scripted_recv_callback; + callbacks.on_msg_recv_callback = text_rsv1_on_msg_recv_callback; + wslay_event_context_client_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + CU_ASSERT(0 == wslay_event_recv(ctx)); + CU_ASSERT(0 == wslay_event_want_write(ctx)); + wslay_event_context_free(ctx); + + /* disallow RSV1 */ + scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + wslay_event_context_client_init(&ctx, &callbacks, &ud); + CU_ASSERT(0 == wslay_event_recv(ctx)); + /* Close frame must be queued */ + CU_ASSERT(wslay_event_want_write(ctx)); + wslay_event_context_free(ctx); + + /* RSV1 is not allowed in continuation frame */ + scripted_data_feed_init(&df, (const uint8_t*)bad_fragment, + sizeof(bad_fragment)); + wslay_event_context_client_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + CU_ASSERT(0 == wslay_event_recv(ctx)); + /* Close frame must be queued */ + CU_ASSERT(wslay_event_want_write(ctx)); + wslay_event_context_free(ctx); + + /* RSV1 is not allowed in ping frame */ + scripted_data_feed_init(&df, (const uint8_t*)pingmsg, sizeof(pingmsg)); + wslay_event_context_client_init(&ctx, &callbacks, &ud); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + CU_ASSERT(0 == wslay_event_recv(ctx)); + /* Close frame must be queued */ + CU_ASSERT(wslay_event_want_write(ctx)); + wslay_event_context_free(ctx); +} + void test_wslay_event_frame_too_big(void) { wslay_event_context_ptr ctx; @@ -489,3 +657,29 @@ void test_wslay_event_message_too_big(void) wslay_event_get_status_code_sent(ctx)); wslay_event_context_free(ctx); } + +void test_wslay_event_config_set_allowed_rsv_bits(void) +{ + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + + memset(&callbacks, 0, sizeof(callbacks)); + + CU_ASSERT(0 == wslay_event_context_server_init(&ctx, &callbacks, NULL)); + CU_ASSERT(WSLAY_RSV_NONE == ctx->allowed_rsv_bits); + + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + CU_ASSERT(WSLAY_RSV1_BIT == ctx->allowed_rsv_bits); + + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT | WSLAY_RSV2_BIT | + WSLAY_RSV3_BIT); + + CU_ASSERT(WSLAY_RSV1_BIT == ctx->allowed_rsv_bits); + + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV2_BIT | WSLAY_RSV3_BIT); + + CU_ASSERT(WSLAY_RSV_NONE == ctx->allowed_rsv_bits); + + wslay_event_context_free(ctx); +} diff --git a/deps/wslay/tests/wslay_event_test.h b/deps/wslay/tests/wslay_event_test.h index 7814b106..834be263 100644 --- a/deps/wslay/tests/wslay_event_test.h +++ b/deps/wslay/tests/wslay_event_test.h @@ -27,7 +27,10 @@ void test_wslay_event_send_fragmented_msg(void); void test_wslay_event_send_fragmented_msg_with_ctrl(void); +void test_wslay_event_send_fragmented_msg_with_rsv1(void); +void test_wslay_event_send_msg_with_rsv1(void); void test_wslay_event_send_ctrl_msg_first(void); +void test_wslay_event_send_ctrl_msg_with_rsv1(void); void test_wslay_event_queue_close(void); void test_wslay_event_queue_close_without_code(void); void test_wslay_event_recv_close_without_code(void); @@ -35,7 +38,9 @@ void test_wslay_event_reply_close(void); void test_wslay_event_no_more_msg(void); void test_wslay_event_callback_failure(void); void test_wslay_event_no_buffering(void); +void test_wslay_event_recv_text_frame_with_rsv1(void); void test_wslay_event_frame_too_big(void); void test_wslay_event_message_too_big(void); +void test_wslay_event_config_set_allowed_rsv_bits(void); #endif /* WSLAY_EVENT_TEST_H */