mirror of https://github.com/aria2/aria2
Update wslay
parent
90452ae11b
commit
fb380d4016
|
@ -27,3 +27,17 @@ stamp-h1
|
||||||
INSTALL
|
INSTALL
|
||||||
.DS_STORE
|
.DS_STORE
|
||||||
tests/main
|
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
|
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.
|
Wslay is a WebSocket library written in C.
|
||||||
It implements the protocol version 13 described in
|
It implements the protocol version 13 described in
|
||||||
|
@ -34,7 +34,8 @@ and
|
||||||
Requirements
|
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
|
To build and run the unit test programs, the following packages are
|
||||||
needed:
|
needed:
|
||||||
|
|
|
@ -145,10 +145,15 @@ enum wslay_opcode {
|
||||||
#define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1)
|
#define wslay_is_ctrl_frame(opcode) ((opcode >> 3) & 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros that returns reserved bits: RSV1, RSV2, RSV3. These macros
|
* Macros that represent and return reserved bits: RSV1, RSV2, RSV3.
|
||||||
* assumes that rsv is constructed by ((RSV1 << 2) | (RSV2 << 1) |
|
* These macros assume that rsv is constructed by ((RSV1 << 2) |
|
||||||
* RSV3)
|
* (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_rsv1(rsv) ((rsv >> 2) & 1)
|
||||||
#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1)
|
#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1)
|
||||||
#define wslay_get_rsv3(rsv) (rsv & 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
|
* 1 if this is masked frame, otherwise 0. iocb->payload_length is
|
||||||
* the payload_length of this frame. iocb->data must point to the
|
* 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
|
* 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
|
* to send bytes. This function calls gen_mask_callback function if
|
||||||
* it needs new mask key. This function returns the number of payload
|
* it needs new mask key. This function returns the number of payload
|
||||||
* bytes sent. Please note that it does not include any number of
|
* 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);
|
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
|
* Enables or disables buffering of an entire message for non-control
|
||||||
* frames. If val is 0, buffering is enabled. Otherwise, buffering is
|
* 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,
|
int wslay_event_queue_msg(wslay_event_context_ptr ctx,
|
||||||
const struct wslay_event_msg *arg);
|
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.
|
* Specify "source" to generate message.
|
||||||
*/
|
*/
|
||||||
|
@ -607,6 +628,13 @@ struct wslay_event_fragmented_msg {
|
||||||
int wslay_event_queue_fragmented_msg
|
int wslay_event_queue_fragmented_msg
|
||||||
(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg);
|
(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
|
* Queues close control frame. This function is provided just for
|
||||||
* convenience. wslay_event_queue_msg() can queue a close control
|
* 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
|
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)
|
const uint8_t *msg, size_t msg_length)
|
||||||
{
|
{
|
||||||
*m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg));
|
*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));
|
memset(*m, 0, sizeof(struct wslay_event_omsg));
|
||||||
(*m)->fin = 1;
|
(*m)->fin = 1;
|
||||||
(*m)->opcode = opcode;
|
(*m)->opcode = opcode;
|
||||||
|
(*m)->rsv = rsv;
|
||||||
(*m)->type = WSLAY_NON_FRAGMENTED;
|
(*m)->type = WSLAY_NON_FRAGMENTED;
|
||||||
if(msg_length) {
|
if(msg_length) {
|
||||||
(*m)->data = (uint8_t*)malloc(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
|
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,
|
const union wslay_event_msg_source source,
|
||||||
wslay_event_fragmented_msg_callback read_callback)
|
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));
|
memset(*m, 0, sizeof(struct wslay_event_omsg));
|
||||||
(*m)->opcode = opcode;
|
(*m)->opcode = opcode;
|
||||||
|
(*m)->rsv = rsv;
|
||||||
(*m)->type = WSLAY_FRAGMENTED;
|
(*m)->type = WSLAY_FRAGMENTED;
|
||||||
(*m)->source = source;
|
(*m)->source = source;
|
||||||
(*m)->read_callback = read_callback;
|
(*m)->read_callback = read_callback;
|
||||||
|
@ -301,7 +303,9 @@ int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code,
|
||||||
} else {
|
} else {
|
||||||
ncode = htons(status_code);
|
ncode = htons(status_code);
|
||||||
memcpy(msg, &ncode, 2);
|
memcpy(msg, &ncode, 2);
|
||||||
memcpy(msg+2, reason, reason_length);
|
if(reason_length) {
|
||||||
|
memcpy(msg+2, reason, reason_length);
|
||||||
|
}
|
||||||
msg_length = reason_length+2;
|
msg_length = reason_length+2;
|
||||||
}
|
}
|
||||||
arg.opcode = WSLAY_CONNECTION_CLOSE;
|
arg.opcode = WSLAY_CONNECTION_CLOSE;
|
||||||
|
@ -328,19 +332,33 @@ static int wslay_event_queue_close_wrapper
|
||||||
return 0;
|
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,
|
int wslay_event_queue_msg(wslay_event_context_ptr ctx,
|
||||||
const struct wslay_event_msg *arg)
|
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;
|
int r;
|
||||||
struct wslay_event_omsg *omsg;
|
struct wslay_event_omsg *omsg;
|
||||||
if(!wslay_event_is_msg_queueable(ctx)) {
|
if(!wslay_event_is_msg_queueable(ctx)) {
|
||||||
return WSLAY_ERR_NO_MORE_MSG;
|
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;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if((r = wslay_event_omsg_non_fragmented_init
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
if(wslay_is_ctrl_frame(arg->opcode)) {
|
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
|
int wslay_event_queue_fragmented_msg
|
||||||
(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg)
|
(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;
|
int r;
|
||||||
struct wslay_event_omsg *omsg;
|
struct wslay_event_omsg *omsg;
|
||||||
if(!wslay_event_is_msg_queueable(ctx)) {
|
if(!wslay_event_is_msg_queueable(ctx)) {
|
||||||
return WSLAY_ERR_NO_MORE_MSG;
|
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;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if((r = wslay_event_omsg_fragmented_init
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) {
|
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);
|
r = wslay_frame_recv(ctx->frame_ctx, &iocb);
|
||||||
if(r >= 0) {
|
if(r >= 0) {
|
||||||
int new_frame = 0;
|
int new_frame = 0;
|
||||||
/* We only allow rsv == 0 ATM. */
|
/* RSV1 is not allowed on control and continuation frames */
|
||||||
if(iocb.rsv != 0 ||
|
if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) ||
|
||||||
((ctx->server && !iocb.mask) || (!ctx->server && iocb.mask))) {
|
(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
|
if((r = wslay_event_queue_close_wrapper
|
||||||
(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
|
(ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) {
|
||||||
return r;
|
return r;
|
||||||
|
@ -608,8 +635,10 @@ int wslay_event_recv(wslay_event_context_ptr ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ctx->imsg->opcode == WSLAY_TEXT_FRAME ||
|
/* If RSV1 bit is set then it is too early for utf-8 validation */
|
||||||
ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
|
if((!wslay_get_rsv1(ctx->imsg->rsv) &&
|
||||||
|
ctx->imsg->opcode == WSLAY_TEXT_FRAME) ||
|
||||||
|
ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
|
if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) {
|
||||||
i = 2;
|
i = 2;
|
||||||
|
@ -815,6 +844,7 @@ int wslay_event_send(wslay_event_context_ptr ctx)
|
||||||
memset(&iocb, 0, sizeof(iocb));
|
memset(&iocb, 0, sizeof(iocb));
|
||||||
iocb.fin = 1;
|
iocb.fin = 1;
|
||||||
iocb.opcode = ctx->omsg->opcode;
|
iocb.opcode = ctx->omsg->opcode;
|
||||||
|
iocb.rsv = ctx->omsg->rsv;
|
||||||
iocb.mask = ctx->server^1;
|
iocb.mask = ctx->server^1;
|
||||||
iocb.data = ctx->omsg->data+ctx->opayloadoff;
|
iocb.data = ctx->omsg->data+ctx->opayloadoff;
|
||||||
iocb.data_length = ctx->opayloadlen-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));
|
memset(&iocb, 0, sizeof(iocb));
|
||||||
iocb.fin = ctx->omsg->fin;
|
iocb.fin = ctx->omsg->fin;
|
||||||
iocb.opcode = ctx->omsg->opcode;
|
iocb.opcode = ctx->omsg->opcode;
|
||||||
|
iocb.rsv = ctx->omsg->rsv;
|
||||||
iocb.mask = ctx->server ? 0 : 1;
|
iocb.mask = ctx->server ? 0 : 1;
|
||||||
iocb.data = ctx->obufmark;
|
iocb.data = ctx->obufmark;
|
||||||
iocb.data_length = ctx->obuflimit-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;
|
ctx->omsg = NULL;
|
||||||
} else {
|
} else {
|
||||||
ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME;
|
ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME;
|
||||||
|
/* RSV1 is not set on continuation frames */
|
||||||
|
ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -951,6 +984,13 @@ int wslay_event_get_close_sent(wslay_event_context_ptr ctx)
|
||||||
return (ctx->close_status & WSLAY_CLOSE_SENT) > 0;
|
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)
|
void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val)
|
||||||
{
|
{
|
||||||
if(val) {
|
if(val) {
|
||||||
|
|
|
@ -56,6 +56,7 @@ enum wslay_event_msg_type {
|
||||||
struct wslay_event_omsg {
|
struct wslay_event_omsg {
|
||||||
uint8_t fin;
|
uint8_t fin;
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
|
uint8_t rsv;
|
||||||
enum wslay_event_msg_type type;
|
enum wslay_event_msg_type type;
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
|
@ -135,6 +136,7 @@ struct wslay_event_context {
|
||||||
struct wslay_event_callbacks callbacks;
|
struct wslay_event_callbacks callbacks;
|
||||||
struct wslay_event_frame_user_data frame_user_data;
|
struct wslay_event_frame_user_data frame_user_data;
|
||||||
void *user_data;
|
void *user_data;
|
||||||
|
uint8_t allowed_rsv_bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* WSLAY_EVENT_H */
|
#endif /* WSLAY_EVENT_H */
|
||||||
|
|
|
@ -44,6 +44,7 @@ static int clean_suite1(void)
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
CU_pSuite pSuite = NULL;
|
CU_pSuite pSuite = NULL;
|
||||||
|
unsigned int num_tests_failed;
|
||||||
|
|
||||||
/* initialize the CUnit test registry */
|
/* initialize the CUnit test registry */
|
||||||
if (CUE_SUCCESS != CU_initialize_registry())
|
if (CUE_SUCCESS != CU_initialize_registry())
|
||||||
|
@ -93,8 +94,14 @@ int main(void)
|
||||||
test_wslay_event_send_fragmented_msg) ||
|
test_wslay_event_send_fragmented_msg) ||
|
||||||
!CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_ctrl",
|
!CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_ctrl",
|
||||||
test_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",
|
!CU_add_test(pSuite, "wslay_event_send_ctrl_msg_first",
|
||||||
test_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",
|
!CU_add_test(pSuite, "wslay_event_queue_close",
|
||||||
test_wslay_event_queue_close) ||
|
test_wslay_event_queue_close) ||
|
||||||
!CU_add_test(pSuite, "wslay_event_queue_close_without_code",
|
!CU_add_test(pSuite, "wslay_event_queue_close_without_code",
|
||||||
|
@ -109,10 +116,14 @@ int main(void)
|
||||||
test_wslay_event_callback_failure) ||
|
test_wslay_event_callback_failure) ||
|
||||||
!CU_add_test(pSuite, "wslay_event_no_buffering",
|
!CU_add_test(pSuite, "wslay_event_no_buffering",
|
||||||
test_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",
|
!CU_add_test(pSuite, "wslay_event_frame_too_big",
|
||||||
test_wslay_event_frame_too_big) ||
|
test_wslay_event_frame_too_big) ||
|
||||||
!CU_add_test(pSuite, "wslay_event_message_too_big",
|
!CU_add_test(pSuite, "wslay_event_message_too_big",
|
||||||
test_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_add_test(pSuite, "wslay_queue", test_wslay_queue)) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
@ -121,6 +132,12 @@ int main(void)
|
||||||
/* Run all tests using the CUnit Basic interface */
|
/* Run all tests using the CUnit Basic interface */
|
||||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||||
CU_basic_run_tests();
|
CU_basic_run_tests();
|
||||||
|
num_tests_failed = CU_get_number_of_tests_failed();
|
||||||
CU_cleanup_registry();
|
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);
|
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)
|
void test_wslay_event_send_ctrl_msg_first(void)
|
||||||
{
|
{
|
||||||
wslay_event_context_ptr ctx;
|
wslay_event_context_ptr ctx;
|
||||||
|
@ -246,6 +311,26 @@ void test_wslay_event_send_ctrl_msg_first(void)
|
||||||
wslay_event_context_free(ctx);
|
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)
|
void test_wslay_event_queue_close(void)
|
||||||
{
|
{
|
||||||
wslay_event_context_ptr ctx;
|
wslay_event_context_ptr ctx;
|
||||||
|
@ -422,6 +507,89 @@ void test_wslay_event_no_buffering(void)
|
||||||
wslay_event_context_free(ctx);
|
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)
|
void test_wslay_event_frame_too_big(void)
|
||||||
{
|
{
|
||||||
wslay_event_context_ptr ctx;
|
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_get_status_code_sent(ctx));
|
||||||
wslay_event_context_free(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(void);
|
||||||
void test_wslay_event_send_fragmented_msg_with_ctrl(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_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(void);
|
||||||
void test_wslay_event_queue_close_without_code(void);
|
void test_wslay_event_queue_close_without_code(void);
|
||||||
void test_wslay_event_recv_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_no_more_msg(void);
|
||||||
void test_wslay_event_callback_failure(void);
|
void test_wslay_event_callback_failure(void);
|
||||||
void test_wslay_event_no_buffering(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_frame_too_big(void);
|
||||||
void test_wslay_event_message_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 */
|
#endif /* WSLAY_EVENT_TEST_H */
|
||||||
|
|
Loading…
Reference in New Issue