mirror of https://github.com/aria2/aria2
Update wslay
parent
90452ae11b
commit
fb380d4016
|
@ -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
|
||||
|
|
|
@ -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 <http://sphinx.pocoo.org/>`_ is used to generate man pages.
|
||||
`Sphinx <http://www.sphinx-doc.org/en/stable/>`_ is used to generate
|
||||
man pages.
|
||||
|
||||
To build and run the unit test programs, the following packages are
|
||||
needed:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue