diff options
Diffstat (limited to 'thirdparty/wslay/wslay_event.c')
-rw-r--r-- | thirdparty/wslay/wslay_event.c | 887 |
1 files changed, 471 insertions, 416 deletions
diff --git a/thirdparty/wslay/wslay_event.c b/thirdparty/wslay/wslay_event.c index 140f7c01da..4c29fe4000 100644 --- a/thirdparty/wslay/wslay_event.c +++ b/thirdparty/wslay/wslay_event.c @@ -28,9 +28,9 @@ #include <assert.h> #include <stdio.h> -#include "wslay_queue.h" #include "wslay_frame.h" #include "wslay_net.h" +#include "wslay_macro.h" /* Start of utf8 dfa */ /* Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de> * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. @@ -60,6 +60,7 @@ #define UTF8_ACCEPT 0 #define UTF8_REJECT 12 +/* clang-format off */ static const uint8_t utf8d[] = { /* * The first part of the table maps bytes to character classes that @@ -84,14 +85,13 @@ static const uint8_t utf8d[] = { 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,12,12,12,12,12, }; +/* clang-format on */ -static uint32_t -decode(uint32_t* state, uint32_t* codep, uint32_t byte) { +static uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte) { uint32_t type = utf8d[byte]; - *codep = (*state != UTF8_ACCEPT) ? - (byte & 0x3fu) | (*codep << 6) : - (0xff >> type) & (byte); + *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) + : (0xff >> type) & (byte); *state = utf8d[256 + *state + type]; return *state; @@ -100,117 +100,96 @@ decode(uint32_t* state, uint32_t* codep, uint32_t byte) { /* End of utf8 dfa */ static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len, - int flags, void *user_data) -{ + int flags, void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data); } static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len, - int flags, void *user_data) -{ + int flags, void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.send_callback(e->ctx, data, len, flags, e->user_data); } static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len, - void *user_data) -{ + void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data); } -static int wslay_event_byte_chunk_init -(struct wslay_event_byte_chunk **chunk, size_t len) -{ - *chunk = (struct wslay_event_byte_chunk*)malloc - (sizeof(struct wslay_event_byte_chunk)); - if(*chunk == NULL) { +static int wslay_event_byte_chunk_init(struct wslay_event_byte_chunk **chunk, + size_t len) { + *chunk = malloc(sizeof(struct wslay_event_byte_chunk) + len); + if (*chunk == NULL) { return WSLAY_ERR_NOMEM; } memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk)); - if(len) { - (*chunk)->data = (uint8_t*)malloc(len); - if((*chunk)->data == NULL) { - free(*chunk); - return WSLAY_ERR_NOMEM; - } + if (len) { + (*chunk)->data = (uint8_t *)(*chunk) + sizeof(**chunk); (*chunk)->data_length = len; } return 0; } -static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) -{ - if(!c) { - return; - } - free(c->data); +static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) { free(c); } static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c, - size_t off, - const uint8_t *data, size_t data_length) -{ - memcpy(c->data+off, data, data_length); + size_t off, const uint8_t *data, + size_t data_length) { + memcpy(c->data + off, data, data_length); } -static void wslay_event_imsg_set(struct wslay_event_imsg *m, - uint8_t fin, uint8_t rsv, uint8_t opcode) -{ +static void wslay_event_imsg_set(struct wslay_event_imsg *m, uint8_t fin, + uint8_t rsv, uint8_t opcode) { m->fin = fin; m->rsv = rsv; m->opcode = opcode; m->msg_length = 0; } -static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) -{ - if(!m->chunks) { - return; - } - while(!wslay_queue_empty(m->chunks)) { - wslay_event_byte_chunk_free(wslay_queue_top(m->chunks)); - wslay_queue_pop(m->chunks); +static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) { + while (!wslay_queue_empty(&m->chunks)) { + struct wslay_event_byte_chunk *chunk = wslay_struct_of( + wslay_queue_top(&m->chunks), struct wslay_event_byte_chunk, qe); + wslay_queue_pop(&m->chunks); + wslay_event_byte_chunk_free(chunk); } } -static void wslay_event_imsg_reset(struct wslay_event_imsg *m) -{ +static void wslay_event_imsg_reset(struct wslay_event_imsg *m) { m->opcode = 0xffu; m->utf8state = UTF8_ACCEPT; wslay_event_imsg_chunks_free(m); } -static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len) -{ - if(len == 0) { +static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, + size_t len) { + if (len == 0) { return 0; } else { int r; struct wslay_event_byte_chunk *chunk; - if((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { - return r; - } - if((r = wslay_queue_push(m->chunks, chunk)) != 0) { + if ((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { return r; } + wslay_queue_push(&m->chunks, &chunk->qe); m->msg_length += len; return 0; } } -static int wslay_event_omsg_non_fragmented_init -(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)); - if(!*m) { +static int wslay_event_omsg_non_fragmented_init(struct wslay_event_omsg **m, + uint8_t opcode, uint8_t rsv, + const uint8_t *msg, + size_t msg_length) { + *m = malloc(sizeof(struct wslay_event_omsg) + msg_length); + if (!*m) { return WSLAY_ERR_NOMEM; } memset(*m, 0, sizeof(struct wslay_event_omsg)); @@ -218,28 +197,22 @@ static int wslay_event_omsg_non_fragmented_init (*m)->opcode = opcode; (*m)->rsv = rsv; (*m)->type = WSLAY_NON_FRAGMENTED; - if(msg_length) { - (*m)->data = (uint8_t*)malloc(msg_length); - if(!(*m)->data) { - free(*m); - return WSLAY_ERR_NOMEM; - } + if (msg_length) { + (*m)->data = (uint8_t *)(*m) + sizeof(**m); memcpy((*m)->data, msg, msg_length); (*m)->data_length = msg_length; } return 0; } -static int wslay_event_omsg_fragmented_init -(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) -{ - *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); - if(!*m) { +static int wslay_event_omsg_fragmented_init( + 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) { + *m = calloc(1, sizeof(struct wslay_event_omsg)); + if (!*m) { return WSLAY_ERR_NOMEM; } - memset(*m, 0, sizeof(struct wslay_event_omsg)); (*m)->opcode = opcode; (*m)->rsv = rsv; (*m)->type = WSLAY_FRAGMENTED; @@ -248,31 +221,25 @@ static int wslay_event_omsg_fragmented_init return 0; } -static void wslay_event_omsg_free(struct wslay_event_omsg *m) -{ - if(!m) { - return; - } - free(m->data); - free(m); -} +static void wslay_event_omsg_free(struct wslay_event_omsg *m) { free(m); } -static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) -{ - if(len == 0) { +static uint8_t *wslay_event_flatten_queue(struct wslay_queue *queue, + size_t len) { + if (len == 0) { return NULL; } else { size_t off = 0; - uint8_t *buf = (uint8_t*)malloc(len); - if(!buf) { + uint8_t *buf = malloc(len); + if (!buf) { return NULL; } - while(!wslay_queue_empty(queue)) { - struct wslay_event_byte_chunk *chunk = wslay_queue_top(queue); - memcpy(buf+off, chunk->data, chunk->data_length); + while (!wslay_queue_empty(queue)) { + struct wslay_event_byte_chunk *chunk = wslay_struct_of( + wslay_queue_top(queue), struct wslay_event_byte_chunk, qe); + wslay_queue_pop(queue); + memcpy(buf + off, chunk->data, chunk->data_length); off += chunk->data_length; wslay_event_byte_chunk_free(chunk); - wslay_queue_pop(queue); assert(off <= len); } assert(len == off); @@ -280,17 +247,15 @@ static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) } } -static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) -{ +static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) { return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0; } int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, - const uint8_t *reason, size_t reason_length) -{ - if(!wslay_event_is_msg_queueable(ctx)) { + const uint8_t *reason, size_t reason_length) { + if (!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; - } else if(reason_length > 123) { + } else if (reason_length > 123) { return WSLAY_ERR_INVALID_ARGUMENT; } else { uint8_t msg[128]; @@ -298,231 +263,203 @@ int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, struct wslay_event_msg arg; uint16_t ncode; int r; - if(status_code == 0) { + if (status_code == 0) { msg_length = 0; } else { ncode = htons(status_code); memcpy(msg, &ncode, 2); - if(reason_length) { - 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.msg = msg; arg.msg_length = msg_length; r = wslay_event_queue_msg(ctx, &arg); - if(r == 0) { + if (r == 0) { ctx->close_status |= WSLAY_CLOSE_QUEUED; } return r; } } -static int wslay_event_queue_close_wrapper -(wslay_event_context_ptr ctx, uint16_t status_code, - const uint8_t *reason, size_t reason_length) -{ +static int wslay_event_queue_close_wrapper(wslay_event_context_ptr ctx, + uint16_t status_code, + const uint8_t *reason, + size_t reason_length) { int r; ctx->read_enabled = 0; - if((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && - r != WSLAY_ERR_NO_MORE_MSG) { + if ((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && + r != WSLAY_ERR_NO_MORE_MSG) { return r; } return 0; } -static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv) -{ +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) -{ + 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) -{ + const struct wslay_event_msg *arg, uint8_t rsv) { int r; 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; } /* 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)) { + 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, rsv, arg->msg, arg->msg_length)) != 0) { + if ((r = wslay_event_omsg_non_fragmented_init( + &omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { return r; } - if(wslay_is_ctrl_frame(arg->opcode)) { - if((r = wslay_queue_push(ctx->send_ctrl_queue, omsg)) != 0) { - return r; - } + if (wslay_is_ctrl_frame(arg->opcode)) { + wslay_queue_push(&ctx->send_ctrl_queue, &omsg->qe); } else { - if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { - return r; - } + wslay_queue_push(&ctx->send_queue, &omsg->qe); } ++ctx->queued_msg_count; ctx->queued_msg_length += arg->msg_length; return 0; } -int wslay_event_queue_fragmented_msg -(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) -{ +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 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)) { + if (!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; } - if(wslay_is_ctrl_frame(arg->opcode) || - !wslay_event_verify_rsv_bits(ctx, rsv)) { + 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, rsv, arg->source, arg->read_callback)) != 0) { - return r; - } - if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + if ((r = wslay_event_omsg_fragmented_init( + &omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { return r; } + wslay_queue_push(&ctx->send_queue, &omsg->qe); ++ctx->queued_msg_count; return 0; } -void wslay_event_config_set_callbacks -(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks) -{ +void wslay_event_config_set_callbacks( + wslay_event_context_ptr ctx, + const struct wslay_event_callbacks *callbacks) { ctx->callbacks = *callbacks; } -static int wslay_event_context_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +static int +wslay_event_context_init(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) { int i, r; struct wslay_frame_callbacks frame_callbacks = { - wslay_event_frame_send_callback, - wslay_event_frame_recv_callback, - wslay_event_frame_genmask_callback - }; - *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context)); - if(!*ctx) { + wslay_event_frame_send_callback, wslay_event_frame_recv_callback, + wslay_event_frame_genmask_callback}; + *ctx = calloc(1, sizeof(struct wslay_event_context)); + if (!*ctx) { return WSLAY_ERR_NOMEM; } - memset(*ctx, 0, sizeof(struct wslay_event_context)); wslay_event_config_set_callbacks(*ctx, callbacks); (*ctx)->user_data = user_data; (*ctx)->frame_user_data.ctx = *ctx; (*ctx)->frame_user_data.user_data = user_data; - if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, - &(*ctx)->frame_user_data)) != 0) { + if ((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, + &(*ctx)->frame_user_data)) != 0) { wslay_event_context_free(*ctx); return r; } (*ctx)->read_enabled = (*ctx)->write_enabled = 1; - (*ctx)->send_queue = wslay_queue_new(); - if(!(*ctx)->send_queue) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } - (*ctx)->send_ctrl_queue = wslay_queue_new(); - if(!(*ctx)->send_ctrl_queue) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } + wslay_queue_init(&(*ctx)->send_queue); + wslay_queue_init(&(*ctx)->send_ctrl_queue); (*ctx)->queued_msg_count = 0; (*ctx)->queued_msg_length = 0; - for(i = 0; i < 2; ++i) { + for (i = 0; i < 2; ++i) { + wslay_queue_init(&(*ctx)->imsgs[i].chunks); wslay_event_imsg_reset(&(*ctx)->imsgs[i]); - (*ctx)->imsgs[i].chunks = wslay_queue_new(); - if(!(*ctx)->imsgs[i].chunks) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } } (*ctx)->imsg = &(*ctx)->imsgs[0]; (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf; (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE; (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE; - (*ctx)->max_recv_msg_length = (1u << 31)-1; + (*ctx)->max_recv_msg_length = (1u << 31) - 1; return 0; } -int wslay_event_context_server_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +int wslay_event_context_server_init( + wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks, + void *user_data) { int r; - if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { return r; } (*ctx)->server = 1; return 0; } -int wslay_event_context_client_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +int wslay_event_context_client_init( + wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks, + void *user_data) { int r; - if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { return r; } (*ctx)->server = 0; return 0; } -void wslay_event_context_free(wslay_event_context_ptr ctx) -{ +void wslay_event_context_free(wslay_event_context_ptr ctx) { int i; - if(!ctx) { + if (!ctx) { return; } - for(i = 0; i < 2; ++i) { + for (i = 0; i < 2; ++i) { wslay_event_imsg_chunks_free(&ctx->imsgs[i]); - wslay_queue_free(ctx->imsgs[i].chunks); + wslay_queue_deinit(&ctx->imsgs[i].chunks); } - if(ctx->send_queue) { - while(!wslay_queue_empty(ctx->send_queue)) { - wslay_event_omsg_free(wslay_queue_top(ctx->send_queue)); - wslay_queue_pop(ctx->send_queue); - } - wslay_queue_free(ctx->send_queue); + + while (!wslay_queue_empty(&ctx->send_queue)) { + struct wslay_event_omsg *omsg = wslay_struct_of( + wslay_queue_top(&ctx->send_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); + wslay_event_omsg_free(omsg); } - if(ctx->send_ctrl_queue) { - while(!wslay_queue_empty(ctx->send_ctrl_queue)) { - wslay_event_omsg_free(wslay_queue_top(ctx->send_ctrl_queue)); - wslay_queue_pop(ctx->send_ctrl_queue); - } - wslay_queue_free(ctx->send_ctrl_queue); + wslay_queue_deinit(&ctx->send_queue); + + while (!wslay_queue_empty(&ctx->send_ctrl_queue)) { + struct wslay_event_omsg *omsg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); + wslay_event_omsg_free(omsg); } + wslay_queue_deinit(&ctx->send_ctrl_queue); + wslay_frame_context_free(ctx->frame_ctx); wslay_event_omsg_free(ctx->omsg); free(ctx); } -static void wslay_event_call_on_frame_recv_start_callback -(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) -{ - if(ctx->callbacks.on_frame_recv_start_callback) { +static void wslay_event_call_on_frame_recv_start_callback( + wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) { + if (ctx->callbacks.on_frame_recv_start_callback) { struct wslay_event_on_frame_recv_start_arg arg; arg.fin = iocb->fin; arg.rsv = iocb->rsv; @@ -532,10 +469,9 @@ static void wslay_event_call_on_frame_recv_start_callback } } -static void wslay_event_call_on_frame_recv_chunk_callback -(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) -{ - if(ctx->callbacks.on_frame_recv_chunk_callback) { +static void wslay_event_call_on_frame_recv_chunk_callback( + wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) { + if (ctx->callbacks.on_frame_recv_chunk_callback) { struct wslay_event_on_frame_recv_chunk_arg arg; arg.data = iocb->data; arg.data_length = iocb->data_length; @@ -543,205 +479,202 @@ static void wslay_event_call_on_frame_recv_chunk_callback } } -static void wslay_event_call_on_frame_recv_end_callback -(wslay_event_context_ptr ctx) -{ - if(ctx->callbacks.on_frame_recv_end_callback) { +static void +wslay_event_call_on_frame_recv_end_callback(wslay_event_context_ptr ctx) { + if (ctx->callbacks.on_frame_recv_end_callback) { ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data); } } -static int wslay_event_is_valid_status_code(uint16_t status_code) -{ - return (1000 <= status_code && status_code <= 1011 && - status_code != 1004 && status_code != 1005 && status_code != 1006) || - (3000 <= status_code && status_code <= 4999); +static int wslay_event_is_valid_status_code(uint16_t status_code) { + return (1000 <= status_code && status_code <= 1011 && status_code != 1004 && + status_code != 1005 && status_code != 1006) || + (3000 <= status_code && status_code <= 4999); } -static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) -{ +static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) { return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0; } -int wslay_event_recv(wslay_event_context_ptr ctx) -{ +int wslay_event_recv(wslay_event_context_ptr ctx) { struct wslay_frame_iocb iocb; ssize_t r; - while(ctx->read_enabled) { + while (ctx->read_enabled) { memset(&iocb, 0, sizeof(iocb)); r = wslay_frame_recv(ctx->frame_ctx, &iocb); - if(r >= 0) { + if (r >= 0) { int new_frame = 0; /* 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; + 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 (int)r; } break; } - if(ctx->imsg->opcode == 0xffu) { - if(iocb.opcode == WSLAY_TEXT_FRAME || - iocb.opcode == WSLAY_BINARY_FRAME || - iocb.opcode == WSLAY_CONNECTION_CLOSE || - iocb.opcode == WSLAY_PING || - iocb.opcode == WSLAY_PONG) { + if (ctx->imsg->opcode == 0xffu) { + if (iocb.opcode == WSLAY_TEXT_FRAME || + iocb.opcode == WSLAY_BINARY_FRAME || + iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) { wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); new_frame = 1; } else { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } - } else if(ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { - if(iocb.opcode == WSLAY_CONTINUATION_FRAME) { + } else if (ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { + if (iocb.opcode == WSLAY_CONTINUATION_FRAME) { ctx->imsg->fin = iocb.fin; - } else if(iocb.opcode == WSLAY_CONNECTION_CLOSE || - iocb.opcode == WSLAY_PING || - iocb.opcode == WSLAY_PONG) { + } else if (iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) { ctx->imsg = &ctx->imsgs[1]; wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); } else { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } new_frame = 1; } - if(new_frame) { - if(ctx->imsg->msg_length+iocb.payload_length > - ctx->max_recv_msg_length) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { - return r; + if (new_frame) { + if (ctx->imsg->msg_length + iocb.payload_length > + ctx->max_recv_msg_length) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { + return (int)r; } break; } ctx->ipayloadlen = iocb.payload_length; wslay_event_call_on_frame_recv_start_callback(ctx, &iocb); - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { - if((r = wslay_event_imsg_append_chunk(ctx->imsg, - iocb.payload_length)) != 0) { + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + if ((r = wslay_event_imsg_append_chunk(ctx->imsg, + iocb.payload_length)) != 0) { ctx->read_enabled = 0; - return r; + return (int)r; } } } /* 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) { + 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) { + if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { i = 2; } else { i = 0; } - for(; i < iocb.data_length; ++i) { + for (; i < iocb.data_length; ++i) { uint32_t codep; - if(decode(&ctx->imsg->utf8state, &codep, - iocb.data[i]) == UTF8_REJECT) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { - return r; + if (decode(&ctx->imsg->utf8state, &codep, iocb.data[i]) == + UTF8_REJECT) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != + 0) { + return (int)r; } break; } } } - if(ctx->imsg->utf8state == UTF8_REJECT) { + if (ctx->imsg->utf8state == UTF8_REJECT) { break; } wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb); - if(iocb.data_length > 0) { - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { + if (iocb.data_length > 0) { + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { struct wslay_event_byte_chunk *chunk; - chunk = wslay_queue_tail(ctx->imsg->chunks); - wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, - iocb.data, iocb.data_length); + chunk = wslay_struct_of(wslay_queue_tail(&ctx->imsg->chunks), + struct wslay_event_byte_chunk, qe); + wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, iocb.data, + iocb.data_length); } ctx->ipayloadoff += iocb.data_length; } - if(ctx->ipayloadoff == ctx->ipayloadlen) { - if(ctx->imsg->fin && - (ctx->imsg->opcode == WSLAY_TEXT_FRAME || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && - ctx->imsg->utf8state != UTF8_ACCEPT) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { - return r; + if (ctx->ipayloadoff == ctx->ipayloadlen) { + if (ctx->imsg->fin && + (ctx->imsg->opcode == WSLAY_TEXT_FRAME || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && + ctx->imsg->utf8state != UTF8_ACCEPT) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return (int)r; } break; } wslay_event_call_on_frame_recv_end_callback(ctx); - if(ctx->imsg->fin) { - if(ctx->callbacks.on_msg_recv_callback || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || - ctx->imsg->opcode == WSLAY_PING) { + if (ctx->imsg->fin) { + if (ctx->callbacks.on_msg_recv_callback || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || + ctx->imsg->opcode == WSLAY_PING) { struct wslay_event_on_msg_recv_arg arg; uint16_t status_code = 0; uint8_t *msg = NULL; size_t msg_length = 0; - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { - msg = wslay_event_flatten_queue(ctx->imsg->chunks, + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + msg = wslay_event_flatten_queue(&ctx->imsg->chunks, ctx->imsg->msg_length); - if(ctx->imsg->msg_length && !msg) { + if (ctx->imsg->msg_length && !msg) { ctx->read_enabled = 0; return WSLAY_ERR_NOMEM; } msg_length = ctx->imsg->msg_length; } - if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { const uint8_t *reason; size_t reason_length; - if(ctx->imsg->msg_length >= 2) { + if (ctx->imsg->msg_length >= 2) { memcpy(&status_code, msg, 2); status_code = ntohs(status_code); - if(!wslay_event_is_valid_status_code(status_code)) { + if (!wslay_event_is_valid_status_code(status_code)) { free(msg); - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } - reason = msg+2; - reason_length = ctx->imsg->msg_length-2; + reason = msg + 2; + reason_length = ctx->imsg->msg_length - 2; } else { reason = NULL; reason_length = 0; } ctx->close_status |= WSLAY_CLOSE_RECEIVED; ctx->status_code_recv = - status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; - if((r = wslay_event_queue_close_wrapper - (ctx, status_code, reason, reason_length)) != 0) { + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + if ((r = wslay_event_queue_close_wrapper(ctx, status_code, reason, + reason_length)) != 0) { free(msg); - return r; + return (int)r; } - } else if(ctx->imsg->opcode == WSLAY_PING) { + } else if (ctx->imsg->opcode == WSLAY_PING) { struct wslay_event_msg pong_arg; pong_arg.opcode = WSLAY_PONG; pong_arg.msg = msg; pong_arg.msg_length = ctx->imsg->msg_length; - if((r = wslay_event_queue_msg(ctx, &pong_arg)) && - r != WSLAY_ERR_NO_MORE_MSG) { + if ((r = wslay_event_queue_msg(ctx, &pong_arg)) && + r != WSLAY_ERR_NO_MORE_MSG) { ctx->read_enabled = 0; free(msg); - return r; + return (int)r; } } - if(ctx->callbacks.on_msg_recv_callback) { + if (ctx->callbacks.on_msg_recv_callback) { arg.rsv = ctx->imsg->rsv; arg.opcode = ctx->imsg->opcode; arg.msg = msg; @@ -753,17 +686,17 @@ int wslay_event_recv(wslay_event_context_ptr ctx) free(msg); } wslay_event_imsg_reset(ctx->imsg); - if(ctx->imsg == &ctx->imsgs[1]) { + if (ctx->imsg == &ctx->imsgs[1]) { ctx->imsg = &ctx->imsgs[0]; } } ctx->ipayloadlen = ctx->ipayloadoff = 0; } } else { - if(r != WSLAY_ERR_WANT_READ || - (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { - if((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { - return r; + if (r != WSLAY_ERR_WANT_READ || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if ((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { + return (int)r; } return WSLAY_ERR_CALLBACK_FAILURE; } @@ -773,26 +706,25 @@ int wslay_event_recv(wslay_event_context_ptr ctx) return 0; } -static void wslay_event_on_non_fragmented_msg_popped -(wslay_event_context_ptr ctx) -{ +static void +wslay_event_on_non_fragmented_msg_popped(wslay_event_context_ptr ctx) { ctx->omsg->fin = 1; ctx->opayloadlen = ctx->omsg->data_length; ctx->opayloadoff = 0; } -static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop -(wslay_event_context_ptr ctx) -{ +static struct wslay_event_omsg * +wslay_event_send_ctrl_queue_pop(wslay_event_context_ptr ctx) { /* * If Close control frame is queued, we don't send any control frame * other than Close. */ - if(ctx->close_status & WSLAY_CLOSE_QUEUED) { - while(!wslay_queue_empty(ctx->send_ctrl_queue)) { - struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); - wslay_queue_pop(ctx->send_ctrl_queue); - if(msg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->close_status & WSLAY_CLOSE_QUEUED) { + while (!wslay_queue_empty(&ctx->send_ctrl_queue)) { + struct wslay_event_omsg *msg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); + if (msg->opcode == WSLAY_CONNECTION_CLOSE) { return msg; } else { wslay_event_omsg_free(msg); @@ -800,71 +732,73 @@ static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop } return NULL; } else { - struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); - wslay_queue_pop(ctx->send_ctrl_queue); + struct wslay_event_omsg *msg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); return msg; } } -int wslay_event_send(wslay_event_context_ptr ctx) -{ +int wslay_event_send(wslay_event_context_ptr ctx) { struct wslay_frame_iocb iocb; ssize_t r; - while(ctx->write_enabled && - (!wslay_queue_empty(ctx->send_queue) || - !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg)) { - if(!ctx->omsg) { - if(wslay_queue_empty(ctx->send_ctrl_queue)) { - ctx->omsg = wslay_queue_top(ctx->send_queue); - wslay_queue_pop(ctx->send_queue); + while (ctx->write_enabled && + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) { + if (!ctx->omsg) { + if (wslay_queue_empty(&ctx->send_ctrl_queue)) { + ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue), + struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); } else { ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); - if(ctx->omsg == NULL) { + if (ctx->omsg == NULL) { break; } } - if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { wslay_event_on_non_fragmented_msg_popped(ctx); } - } else if(!wslay_is_ctrl_frame(ctx->omsg->opcode) && - ctx->frame_ctx->ostate == PREP_HEADER && - !wslay_queue_empty(ctx->send_ctrl_queue)) { - if((r = wslay_queue_push_front(ctx->send_queue, ctx->omsg)) != 0) { - ctx->write_enabled = 0; - return r; - } + } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(&ctx->send_ctrl_queue)) { + wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe); ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); - if(ctx->omsg == NULL) { + if (ctx->omsg == NULL) { break; } /* ctrl message has WSLAY_NON_FRAGMENTED */ wslay_event_on_non_fragmented_msg_popped(ctx); } - if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { 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; + iocb.mask = ctx->server ^ 1; + iocb.data = ctx->omsg->data; + iocb.data_length = ctx->opayloadlen; + if (ctx->opayloadoff) { + iocb.data += ctx->opayloadoff; + iocb.data_length -= ctx->opayloadoff; + } iocb.payload_length = ctx->opayloadlen; r = wslay_frame_send(ctx->frame_ctx, &iocb); - if(r >= 0) { - ctx->opayloadoff += r; - if(ctx->opayloadoff == ctx->opayloadlen) { + if (r >= 0) { + ctx->opayloadoff += (uint64_t)r; + if (ctx->opayloadoff == ctx->opayloadlen) { --ctx->queued_msg_count; ctx->queued_msg_length -= ctx->omsg->data_length; - if(ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { uint16_t status_code = 0; ctx->write_enabled = 0; ctx->close_status |= WSLAY_CLOSE_SENT; - if(ctx->omsg->data_length >= 2) { + if (ctx->omsg->data_length >= 2) { memcpy(&status_code, ctx->omsg->data, 2); status_code = ntohs(status_code); } ctx->status_code_sent = - status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; } wslay_event_omsg_free(ctx->omsg); ctx->omsg = NULL; @@ -872,30 +806,29 @@ int wslay_event_send(wslay_event_context_ptr ctx) break; } } else { - if(r != WSLAY_ERR_WANT_WRITE || - (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if (r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } break; } } else { - if(ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { int eof = 0; r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), - &ctx->omsg->source, - &eof, ctx->user_data); - if(r == 0 && eof == 0) { + &ctx->omsg->source, &eof, ctx->user_data); + if (r == 0 && eof == 0) { break; - } else if(r < 0) { + } else if (r < 0) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } - ctx->obuflimit = ctx->obuf+r; - if(eof) { + ctx->obuflimit = ctx->obuf + r; + if (eof) { ctx->omsg->fin = 1; } - ctx->opayloadlen = r; + ctx->opayloadlen = (uint64_t)r; ctx->opayloadoff = 0; } memset(&iocb, 0, sizeof(iocb)); @@ -904,29 +837,28 @@ int wslay_event_send(wslay_event_context_ptr ctx) iocb.rsv = ctx->omsg->rsv; iocb.mask = ctx->server ? 0 : 1; iocb.data = ctx->obufmark; - iocb.data_length = ctx->obuflimit-ctx->obufmark; + iocb.data_length = (size_t)(ctx->obuflimit - ctx->obufmark); iocb.payload_length = ctx->opayloadlen; r = wslay_frame_send(ctx->frame_ctx, &iocb); - if(r >= 0) { + if (r >= 0) { ctx->obufmark += r; - if(ctx->obufmark == ctx->obuflimit) { + if (ctx->obufmark == ctx->obuflimit) { ctx->obufmark = ctx->obuflimit = ctx->obuf; - if(ctx->omsg->fin) { + if (ctx->omsg->fin) { --ctx->queued_msg_count; wslay_event_omsg_free(ctx->omsg); 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; + ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT); } } else { break; } } else { - if(r != WSLAY_ERR_WANT_WRITE || - (ctx->error != WSLAY_ERR_WOULDBLOCK && - ctx->error != 0)) { + if (r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } @@ -937,91 +869,214 @@ int wslay_event_send(wslay_event_context_ptr ctx) return 0; } -void wslay_event_set_error(wslay_event_context_ptr ctx, int val) -{ +ssize_t wslay_event_write(wslay_event_context_ptr ctx, uint8_t *buf, + size_t buflen) { + struct wslay_frame_iocb iocb; + ssize_t r; + uint8_t *buf_last = buf; + size_t wpayloadlen; + while (ctx->write_enabled && + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) { + if (!ctx->omsg) { + if (wslay_queue_empty(&ctx->send_ctrl_queue)) { + ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue), + struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); + } else { + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if (ctx->omsg == NULL) { + break; + } + } + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + wslay_event_on_non_fragmented_msg_popped(ctx); + } + } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(&ctx->send_ctrl_queue)) { + wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe); + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if (ctx->omsg == NULL) { + break; + } + /* ctrl message has WSLAY_NON_FRAGMENTED */ + wslay_event_on_non_fragmented_msg_popped(ctx); + } + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + 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; + iocb.data_length = ctx->opayloadlen; + if (ctx->opayloadoff) { + iocb.data += ctx->opayloadoff; + iocb.data_length -= ctx->opayloadoff; + } + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen, + &wpayloadlen); + if (r > 0) { + assert((size_t)r <= buflen); + + buf_last += r; + buflen -= (size_t)r; + + ctx->opayloadoff += wpayloadlen; + if (ctx->opayloadoff == ctx->opayloadlen) { + --ctx->queued_msg_count; + ctx->queued_msg_length -= ctx->omsg->data_length; + if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + uint16_t status_code = 0; + ctx->write_enabled = 0; + ctx->close_status |= WSLAY_CLOSE_SENT; + if (ctx->omsg->data_length >= 2) { + memcpy(&status_code, ctx->omsg->data, 2); + status_code = ntohs(status_code); + } + ctx->status_code_sent = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + } + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + break; + } + } else if (r == 0) { + return buf_last - buf; + } else { + return WSLAY_ERR_CALLBACK_FAILURE; + } + } else { + if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + int eof = 0; + r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), + &ctx->omsg->source, &eof, ctx->user_data); + if (r == 0 && eof == 0) { + break; + } else if (r < 0) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + ctx->obuflimit = ctx->obuf + r; + if (eof) { + ctx->omsg->fin = 1; + } + ctx->opayloadlen = (uint64_t)r; + ctx->opayloadoff = 0; + } + 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 = (size_t)(ctx->obuflimit - ctx->obufmark); + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen, + &wpayloadlen); + if (r > 0) { + assert((size_t)r <= buflen); + + buf_last += r; + buflen -= (size_t)r; + + ctx->obufmark += wpayloadlen; + if (ctx->obufmark == ctx->obuflimit) { + ctx->obufmark = ctx->obuflimit = ctx->obuf; + if (ctx->omsg->fin) { + --ctx->queued_msg_count; + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; + /* RSV1 is not set on continuation frames */ + ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT); + } + } else { + break; + } + } else if (r == 0) { + return buf_last - buf; + } else { + return WSLAY_ERR_CALLBACK_FAILURE; + } + } + } + return buf_last - buf; +} + +void wslay_event_set_error(wslay_event_context_ptr ctx, int val) { ctx->error = val; } -int wslay_event_want_read(wslay_event_context_ptr ctx) -{ +int wslay_event_want_read(wslay_event_context_ptr ctx) { return ctx->read_enabled; } -int wslay_event_want_write(wslay_event_context_ptr ctx) -{ +int wslay_event_want_write(wslay_event_context_ptr ctx) { return ctx->write_enabled && - (!wslay_queue_empty(ctx->send_queue) || - !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg); + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg); } -void wslay_event_shutdown_read(wslay_event_context_ptr ctx) -{ +void wslay_event_shutdown_read(wslay_event_context_ptr ctx) { ctx->read_enabled = 0; } -void wslay_event_shutdown_write(wslay_event_context_ptr ctx) -{ +void wslay_event_shutdown_write(wslay_event_context_ptr ctx) { ctx->write_enabled = 0; } -int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) -{ +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) { return ctx->read_enabled; } -int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) -{ +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) { return ctx->write_enabled; } -int wslay_event_get_close_received(wslay_event_context_ptr ctx) -{ +int wslay_event_get_close_received(wslay_event_context_ptr ctx) { return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0; } -int wslay_event_get_close_sent(wslay_event_context_ptr ctx) -{ +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) -{ + 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) { +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) { + if (val) { ctx->config |= WSLAY_CONFIG_NO_BUFFERING; } else { - ctx->config &= ~WSLAY_CONFIG_NO_BUFFERING; + ctx->config &= (uint32_t)~WSLAY_CONFIG_NO_BUFFERING; } } void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, - uint64_t val) -{ + uint64_t val) { ctx->max_recv_msg_length = val; } -uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) -{ +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) { return ctx->status_code_recv; } -uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) -{ +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) { return ctx->status_code_sent; } -size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) -{ +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) { return ctx->queued_msg_count; } -size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) -{ +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) { return ctx->queued_msg_length; } |