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 */