diff options
-rw-r--r-- | modules/websocket/SCsub | 3 | ||||
-rw-r--r-- | thirdparty/README.md | 12 | ||||
-rw-r--r-- | thirdparty/wslay/config.h (renamed from thirdparty/wslay/includes/config.h) | 2 | ||||
-rw-r--r-- | thirdparty/wslay/patches/msvcfix.diff (renamed from thirdparty/wslay/msvcfix.diff) | 7 | ||||
-rw-r--r-- | thirdparty/wslay/wslay/wslay.h (renamed from thirdparty/wslay/includes/wslay/wslay.h) | 140 | ||||
-rw-r--r-- | thirdparty/wslay/wslay/wslayver.h (renamed from thirdparty/wslay/includes/wslay/wslayver.h) | 0 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_event.c | 887 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_event.h | 20 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_frame.c | 306 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_frame.h | 1 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_macro.h (renamed from thirdparty/wslay/wslay_stack.h) | 25 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_net.c | 5 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_queue.c | 98 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_queue.h | 22 | ||||
-rw-r--r-- | thirdparty/wslay/wslay_stack.c | 86 |
15 files changed, 851 insertions, 763 deletions
diff --git a/modules/websocket/SCsub b/modules/websocket/SCsub index 4c022c43cf..63c941c4a8 100644 --- a/modules/websocket/SCsub +++ b/modules/websocket/SCsub @@ -18,12 +18,11 @@ elif env["builtin_wslay"]: "wslay_net.c", "wslay_event.c", "wslay_queue.c", - "wslay_stack.c", "wslay_frame.c", ] thirdparty_sources = [thirdparty_dir + s for s in thirdparty_sources] - env_ws.Prepend(CPPPATH=[thirdparty_dir + "includes/"]) + env_ws.Prepend(CPPPATH=[thirdparty_dir]) env_ws.Append(CPPDEFINES=["HAVE_CONFIG_H"]) if env["platform"] == "windows" or env["platform"] == "uwp": diff --git a/thirdparty/README.md b/thirdparty/README.md index 25d2e1cfe3..3e2f966f1d 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -670,14 +670,18 @@ Patches in the `patches` directory should be re-applied after updates. ## wslay - Upstream: https://github.com/tatsuhiro-t/wslay -- Version: 1.1.1 (c9a84aa6df8512584c77c8cd15be9536b89c35aa, 2020) +- Version: 1.1.1+git (45d22583b488f79d5a4e598cc7675c191c5ab53f, 2021) - License: MIT File extracted from upstream release tarball: -- All `*.c` and `*.h` in `lib/` and `lib/includes/` -- `wslay.h` has a small Godot addition to fix MSVC build. - See `thirdparty/wslay/msvcfix.diff` +- Run `cmake .` to generate `config.h` and `wslayver.h`. + Contents might need tweaking for Godot, review diff. +- All `*.c` and `*.h` files from `lib/` +- All `*.h` in `lib/includes/wslay/` as `wslay/` +- `wslay/wslay.h` has a small Godot addition to fix MSVC build. + See `patches/msvcfix.diff` +- `COPYING` ## xatlas diff --git a/thirdparty/wslay/includes/config.h b/thirdparty/wslay/config.h index 771ad12528..f291801ba1 100644 --- a/thirdparty/wslay/includes/config.h +++ b/thirdparty/wslay/config.h @@ -1,8 +1,10 @@ #ifndef CONFIG_H #define CONFIG_H +// -- GODOT start -- #ifdef BIG_ENDIAN_ENABLED #define WORDS_BIGENDIAN #endif +// -- GODOT end -- #endif /* CONFIG_H */ diff --git a/thirdparty/wslay/msvcfix.diff b/thirdparty/wslay/patches/msvcfix.diff index 28721844f4..f58b6d44f0 100644 --- a/thirdparty/wslay/msvcfix.diff +++ b/thirdparty/wslay/patches/msvcfix.diff @@ -1,8 +1,8 @@ diff --git a/thirdparty/wslay/includes/wslay/wslay.h b/thirdparty/wslay/includes/wslay/wslay.h -index 2fde81a4e..9c751b05b 100644 +index 77a4e8253f..ac6873613f 100644 --- a/thirdparty/wslay/includes/wslay/wslay.h +++ b/thirdparty/wslay/includes/wslay/wslay.h -@@ -33,6 +33,12 @@ extern "C" { +@@ -33,6 +33,13 @@ extern "C" { #include <stdlib.h> #include <sys/types.h> @@ -12,6 +12,7 @@ index 2fde81a4e..9c751b05b 100644 +typedef SSIZE_T ssize_t; +#endif +/* GODOT END */ - ++ /* * wslay/wslayver.h is generated from wslay/wslayver.h.in by + * configure. The projects which do not use autotools can set diff --git a/thirdparty/wslay/includes/wslay/wslay.h b/thirdparty/wslay/wslay/wslay.h index 9c751b05b7..ac6873613f 100644 --- a/thirdparty/wslay/includes/wslay/wslay.h +++ b/thirdparty/wslay/wslay/wslay.h @@ -25,7 +25,7 @@ #ifndef WSLAY_H #define WSLAY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -155,10 +155,10 @@ enum wslay_opcode { * 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_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) @@ -172,7 +172,7 @@ struct wslay_frame_iocb { * RFC6455 requires 0 unless extensions are negotiated. */ uint8_t rsv; - /* 4 bit opcode */ + /* 4 bit opcode */ uint8_t opcode; /* payload length [0, 2**63-1] */ uint64_t payload_length; @@ -229,6 +229,33 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, struct wslay_frame_iocb *iocb); /* + * Write WebSocket frame specified in iocb to buf of length + * buflen. ctx must be initialized using wslay_frame_context_init() + * function. iocb->fin must be 1 if this is a fin frame, otherwise 0. + * iocb->rsv is reserved bits. iocb->opcode must be the opcode of + * this frame. iocb->mask must be 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. Unlike + * wslay_frame_send, this function does not call send_callback + * function. This function calls gen_mask_callback function if it + * needs new mask key. This function returns the number of bytes + * written to a buffer. Unlike wslay_frame_send, it includes the + * number of header bytes. Instead, the number of payload bytes + * written is assigned to *pwpayloadlen if this function succeeds. If + * there is not enough space left in a buffer, it returns 0. If the + * library detects error in iocb, this function returns + * WSLAY_ERR_INVALID_ARGUMENT. If callback functions report a + * failure, this function returns WSLAY_ERR_INVALID_CALLBACK. This + * function does not always send all given data in iocb. If there are + * remaining data to be sent, adjust data and data_length in iocb + * accordingly and call this function again. + */ +ssize_t wslay_frame_write(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb, uint8_t *buf, + size_t buflen, size_t *pwpayloadlen); + +/* * Receives WebSocket frame and stores it in iocb. This function * returns the number of payload bytes received. This does not * include header bytes. In this case, iocb will be populated as @@ -276,9 +303,9 @@ struct wslay_event_on_msg_recv_arg { * Callback function invoked by wslay_event_recv() when a message is * completely received. */ -typedef void (*wslay_event_on_msg_recv_callback) -(wslay_event_context_ptr ctx, - const struct wslay_event_on_msg_recv_arg *arg, void *user_data); +typedef void (*wslay_event_on_msg_recv_callback)( + wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, + void *user_data); struct wslay_event_on_frame_recv_start_arg { /* fin bit; 1 for final frame, or 0. */ @@ -296,9 +323,9 @@ struct wslay_event_on_frame_recv_start_arg { * starts to be received. This callback function is only invoked once * for each frame. */ -typedef void (*wslay_event_on_frame_recv_start_callback) -(wslay_event_context_ptr ctx, - const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data); +typedef void (*wslay_event_on_frame_recv_start_callback)( + wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data); struct wslay_event_on_frame_recv_chunk_arg { /* chunk of payload data */ @@ -311,16 +338,16 @@ struct wslay_event_on_frame_recv_chunk_arg { * Callback function invoked by wslay_event_recv() when a chunk of * frame payload is received. */ -typedef void (*wslay_event_on_frame_recv_chunk_callback) -(wslay_event_context_ptr ctx, - const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data); +typedef void (*wslay_event_on_frame_recv_chunk_callback)( + wslay_event_context_ptr ctx, + const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data); /* * Callback function invoked by wslay_event_recv() when a frame is * completely received. */ -typedef void (*wslay_event_on_frame_recv_end_callback) -(wslay_event_context_ptr ctx, void *user_data); +typedef void (*wslay_event_on_frame_recv_end_callback)( + wslay_event_context_ptr ctx, void *user_data); /* * Callback function invoked by wslay_event_recv() when it wants to @@ -394,9 +421,9 @@ struct wslay_event_callbacks { * WSLAY_ERR_NOMEM * Out of memory. */ -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); /* * Initializes ctx as WebSocket client. user_data is an arbitrary @@ -409,9 +436,9 @@ int wslay_event_context_server_init * WSLAY_ERR_NOMEM * Out of memory. */ -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); /* * Releases allocated resources for ctx. @@ -462,8 +489,8 @@ void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, * or wslay_event_context_server_init() or * wslay_event_context_client_init() are replaced with callbacks. */ -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); /* * Receives messages from peer. When receiving @@ -538,6 +565,50 @@ int wslay_event_recv(wslay_event_context_ptr ctx); */ int wslay_event_send(wslay_event_context_ptr ctx); +/* + * Writes queued messages to a buffer. Unlike wslay_event_send(), this + * function writes messages into the given buffer. It does not use + * wslay_event_send_callback function. Single call of + * wslay_event_write() writes multiple messages until there is not + * enough space left in a buffer. + * + * If ctx is initialized for WebSocket client use, wslay_event_write() + * uses wslay_event_genmask_callback to get new mask key. + * + * buf is a pointer to buffer and its capacity is given in buflen. It + * should have at least 14 bytes. + * + * When a message queued using wslay_event_queue_fragmented_msg() is + * sent, wslay_event_write() invokes + * wslay_event_fragmented_msg_callback for that message. + * + * After close control frame is sent, this function calls + * wslay_event_set_write_enabled() with second argument 0 to disable + * further transmission to peer. + * + * If there are any pending messages, wslay_event_want_write() returns + * 1, otherwise returns 0. + * + * In case of a fatal errror which leads to negative return code, this + * function calls wslay_event_set_write_enabled() with second argument + * 0 to disable further transmission to peer. + * + * wslay_event_write() returns the number of bytes written to a buffer + * if it succeeds, or one of the following negative error codes: + * + * WSLAY_ERR_CALLBACK_FAILURE + * User defined callback function is failed. + * + * WSLAY_ERR_NOMEM + * Out of memory. + * + * When negative error code is returned, application must not make any + * further call of wslay_event_write() and must close WebSocket + * connection. + */ +ssize_t wslay_event_write(wslay_event_context_ptr ctx, uint8_t *buf, + size_t buflen); + struct wslay_event_msg { uint8_t opcode; const uint8_t *msg; @@ -594,10 +665,9 @@ union wslay_event_msg_source { * moment, return 0. If there is an error, return -1 and set error * code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). */ -typedef ssize_t (*wslay_event_fragmented_msg_callback) -(wslay_event_context_ptr ctx, - uint8_t *buf, size_t len, const union wslay_event_msg_source *source, - int *eof, void *user_data); +typedef ssize_t (*wslay_event_fragmented_msg_callback)( + wslay_event_context_ptr ctx, uint8_t *buf, size_t len, + const union wslay_event_msg_source *source, int *eof, void *user_data); struct wslay_event_fragmented_msg { /* opcode */ @@ -631,15 +701,16 @@ struct wslay_event_fragmented_msg { * WSLAY_ERR_NOMEM * Out of memory. */ -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); /* * 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); +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 @@ -669,8 +740,7 @@ int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, * WSLAY_ERR_NOMEM * Out of memory. */ -int wslay_event_queue_close(wslay_event_context_ptr ctx, - uint16_t status_code, +int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, const uint8_t *reason, size_t reason_length); /* diff --git a/thirdparty/wslay/includes/wslay/wslayver.h b/thirdparty/wslay/wslay/wslayver.h index 28f2018039..28f2018039 100644 --- a/thirdparty/wslay/includes/wslay/wslayver.h +++ b/thirdparty/wslay/wslay/wslayver.h 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; } diff --git a/thirdparty/wslay/wslay_event.h b/thirdparty/wslay/wslay_event.h index 36feb9036d..e30c3d1940 100644 --- a/thirdparty/wslay/wslay_event.h +++ b/thirdparty/wslay/wslay_event.h @@ -31,10 +31,10 @@ #include <wslay/wslay.h> -struct wslay_stack; -struct wslay_queue; +#include "wslay_queue.h" struct wslay_event_byte_chunk { + struct wslay_queue_entry qe; uint8_t *data; size_t data_length; }; @@ -44,16 +44,14 @@ struct wslay_event_imsg { uint8_t rsv; uint8_t opcode; uint32_t utf8state; - struct wslay_queue *chunks; + struct wslay_queue chunks; size_t msg_length; }; -enum wslay_event_msg_type { - WSLAY_NON_FRAGMENTED, - WSLAY_FRAGMENTED -}; +enum wslay_event_msg_type { WSLAY_NON_FRAGMENTED, WSLAY_FRAGMENTED }; struct wslay_event_omsg { + struct wslay_queue_entry qe; uint8_t fin; uint8_t opcode; uint8_t rsv; @@ -77,9 +75,7 @@ enum wslay_event_close_status { WSLAY_CLOSE_SENT = 1 << 2 }; -enum wslay_event_config { - WSLAY_CONFIG_NO_BUFFERING = 1 << 0 -}; +enum wslay_event_config { WSLAY_CONFIG_NO_BUFFERING = 1 << 0 }; struct wslay_event_context { /* config status, bitwise OR of enum wslay_event_config values*/ @@ -118,9 +114,9 @@ struct wslay_event_context { is currently sent. */ struct wslay_event_omsg *omsg; /* Queue for non-control frames */ - struct wslay_queue/*<wslay_omsg*>*/ *send_queue; + struct wslay_queue /*<wslay_omsg*>*/ send_queue; /* Queue for control frames */ - struct wslay_queue/*<wslay_omsg*>*/ *send_ctrl_queue; + struct wslay_queue /*<wslay_omsg*>*/ send_ctrl_queue; /* Size of send_queue + size of send_ctrl_queue */ size_t queued_msg_count; /* The sum of message length in send_queue */ diff --git a/thirdparty/wslay/wslay_frame.c b/thirdparty/wslay/wslay_frame.c index 445e750ca5..435044a3f4 100644 --- a/thirdparty/wslay/wslay_frame.c +++ b/thirdparty/wslay/wslay_frame.c @@ -34,10 +34,9 @@ int wslay_frame_context_init(wslay_frame_context_ptr *ctx, const struct wslay_frame_callbacks *callbacks, - void *user_data) -{ - *ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context)); - if(*ctx == NULL) { + void *user_data) { + *ctx = malloc(sizeof(struct wslay_frame_context)); + if (*ctx == NULL) { return -1; } memset(*ctx, 0, sizeof(struct wslay_frame_context)); @@ -50,38 +49,35 @@ int wslay_frame_context_init(wslay_frame_context_ptr *ctx, return 0; } -void wslay_frame_context_free(wslay_frame_context_ptr ctx) -{ - free(ctx); -} +void wslay_frame_context_free(wslay_frame_context_ptr ctx) { free(ctx); } ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, - struct wslay_frame_iocb *iocb) -{ - if(iocb->data_length > iocb->payload_length) { + struct wslay_frame_iocb *iocb) { + if (iocb->data_length > iocb->payload_length) { return WSLAY_ERR_INVALID_ARGUMENT; } - if(ctx->ostate == PREP_HEADER) { + if (ctx->ostate == PREP_HEADER) { uint8_t *hdptr = ctx->oheader; memset(ctx->oheader, 0, sizeof(ctx->oheader)); - *hdptr |= (iocb->fin << 7) & 0x80u; - *hdptr |= (iocb->rsv << 4) & 0x70u; - *hdptr |= iocb->opcode & 0xfu; + *hdptr |= (uint8_t)((uint8_t)(iocb->fin << 7) & 0x80u); + *hdptr |= (uint8_t)((uint8_t)(iocb->rsv << 4) & 0x70u); + /* Suppress stubborn gcc-10 warning */ + *hdptr |= (uint8_t)((uint8_t)(iocb->opcode << 0) & 0xfu); ++hdptr; - *hdptr |= (iocb->mask << 7) & 0x80u; - if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + *hdptr |= (uint8_t)((uint8_t)(iocb->mask << 7) & 0x80u); + if (wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { return WSLAY_ERR_INVALID_ARGUMENT; } - if(iocb->payload_length < 126) { - *hdptr |= iocb->payload_length; + if (iocb->payload_length < 126) { + *hdptr |= (uint8_t)iocb->payload_length; ++hdptr; - } else if(iocb->payload_length < (1 << 16)) { - uint16_t len = htons(iocb->payload_length); + } else if (iocb->payload_length < (1 << 16)) { + uint16_t len = htons((uint16_t)iocb->payload_length); *hdptr |= 126; ++hdptr; memcpy(hdptr, &len, 2); hdptr += 2; - } else if(iocb->payload_length < (1ull << 63)) { + } else if (iocb->payload_length < (1ull << 63)) { uint64_t len = hton64(iocb->payload_length); *hdptr |= 127; ++hdptr; @@ -91,9 +87,9 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, /* Too large payload length */ return WSLAY_ERR_INVALID_ARGUMENT; } - if(iocb->mask) { - if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4, - ctx->user_data) != 0) { + if (iocb->mask) { + if (ctx->callbacks.genmask_callback(ctx->omaskkey, 4, ctx->user_data) != + 0) { return WSLAY_ERR_INVALID_CALLBACK; } else { ctx->omask = 1; @@ -107,21 +103,21 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, ctx->opayloadlen = iocb->payload_length; ctx->opayloadoff = 0; } - if(ctx->ostate == SEND_HEADER) { - ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark; + if (ctx->ostate == SEND_HEADER) { + ptrdiff_t len = ctx->oheaderlimit - ctx->oheadermark; ssize_t r; int flags = 0; - if(iocb->data_length > 0) { + if (iocb->data_length > 0) { flags |= WSLAY_MSG_MORE; }; - r = ctx->callbacks.send_callback(ctx->oheadermark, len, flags, + r = ctx->callbacks.send_callback(ctx->oheadermark, (size_t)len, flags, ctx->user_data); - if(r > 0) { - if(r > len) { + if (r > 0) { + if (r > len) { return WSLAY_ERR_INVALID_CALLBACK; } else { ctx->oheadermark += r; - if(ctx->oheadermark == ctx->oheaderlimit) { + if (ctx->oheadermark == ctx->oheaderlimit) { ctx->ostate = SEND_PAYLOAD; } else { return WSLAY_ERR_WANT_WRITE; @@ -131,34 +127,34 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, return WSLAY_ERR_WANT_WRITE; } } - if(ctx->ostate == SEND_PAYLOAD) { + if (ctx->ostate == SEND_PAYLOAD) { size_t totallen = 0; - if(iocb->data_length > 0) { - if(ctx->omask) { + if (iocb->data_length > 0) { + if (ctx->omask) { uint8_t temp[4096]; const uint8_t *datamark = iocb->data, - *datalimit = iocb->data+iocb->data_length; - while(datamark < datalimit) { - size_t datalen = datalimit - datamark; - const uint8_t *writelimit = datamark+ - wslay_min(sizeof(temp), datalen); - size_t writelen = writelimit-datamark; + *datalimit = iocb->data + iocb->data_length; + while (datamark < datalimit) { + size_t datalen = (size_t)(datalimit - datamark); + const uint8_t *writelimit = + datamark + wslay_min(sizeof(temp), datalen); + size_t writelen = (size_t)(writelimit - datamark); ssize_t r; size_t i; - for(i = 0; i < writelen; ++i) { - temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4]; + for (i = 0; i < writelen; ++i) { + temp[i] = datamark[i] ^ ctx->omaskkey[(ctx->opayloadoff + i) % 4]; } r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data); - if(r > 0) { - if((size_t)r > writelen) { + if (r > 0) { + if ((size_t)r > writelen) { return WSLAY_ERR_INVALID_CALLBACK; } else { datamark += r; - ctx->opayloadoff += r; - totallen += r; + ctx->opayloadoff += (uint64_t)r; + totallen += (size_t)r; } } else { - if(totallen > 0) { + if (totallen > 0) { break; } else { return WSLAY_ERR_WANT_WRITE; @@ -169,44 +165,148 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, ssize_t r; r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0, ctx->user_data); - if(r > 0) { - if((size_t)r > iocb->data_length) { + if (r > 0) { + if ((size_t)r > iocb->data_length) { return WSLAY_ERR_INVALID_CALLBACK; } else { - ctx->opayloadoff += r; - totallen = r; + ctx->opayloadoff += (uint64_t)r; + totallen = (size_t)r; } } else { return WSLAY_ERR_WANT_WRITE; } } } - if(ctx->opayloadoff == ctx->opayloadlen) { + if (ctx->opayloadoff == ctx->opayloadlen) { ctx->ostate = PREP_HEADER; } - return totallen; + return (ssize_t)totallen; } return WSLAY_ERR_INVALID_ARGUMENT; } -static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) -{ - ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark; - memmove(ctx->ibuf, ctx->ibufmark, len); - ctx->ibuflimit = ctx->ibuf+len; +ssize_t wslay_frame_write(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb, uint8_t *buf, + size_t buflen, size_t *pwpayloadlen) { + uint8_t *buf_last = buf; + size_t i; + size_t hdlen; + + *pwpayloadlen = 0; + + if (iocb->data_length > iocb->payload_length) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + + switch (ctx->ostate) { + case PREP_HEADER: + case PREP_HEADER_NOBUF: + hdlen = 2; + if (iocb->payload_length < 126) { + /* nothing to do */ + } else if (iocb->payload_length < (1 << 16)) { + hdlen += 2; + } else if (iocb->payload_length < (1ull << 63)) { + hdlen += 8; + } + if (iocb->mask) { + hdlen += 4; + } + + if (buflen < hdlen) { + ctx->ostate = PREP_HEADER_NOBUF; + return 0; + } + + memset(buf_last, 0, hdlen); + *buf_last |= (uint8_t)((uint8_t)(iocb->fin << 7) & 0x80u); + *buf_last |= (uint8_t)((uint8_t)(iocb->rsv << 4) & 0x70u); + /* Suppress stubborn gcc-10 warning */ + *buf_last |= (uint8_t)((uint8_t)(iocb->opcode << 0) & 0xfu); + ++buf_last; + *buf_last |= (uint8_t)((uint8_t)(iocb->mask << 7) & 0x80u); + if (wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if (iocb->payload_length < 126) { + *buf_last |= (uint8_t)iocb->payload_length; + ++buf_last; + } else if (iocb->payload_length < (1 << 16)) { + uint16_t len = htons((uint16_t)iocb->payload_length); + *buf_last |= 126; + ++buf_last; + memcpy(buf_last, &len, 2); + buf_last += 2; + } else if (iocb->payload_length < (1ull << 63)) { + uint64_t len = hton64(iocb->payload_length); + *buf_last |= 127; + ++buf_last; + memcpy(buf_last, &len, 8); + buf_last += 8; + } else { + /* Too large payload length */ + return WSLAY_ERR_INVALID_ARGUMENT; + } + if (iocb->mask) { + if (ctx->callbacks.genmask_callback(ctx->omaskkey, 4, ctx->user_data) != + 0) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->omask = 1; + memcpy(buf_last, ctx->omaskkey, 4); + buf_last += 4; + } + } + ctx->ostate = SEND_PAYLOAD; + ctx->opayloadlen = iocb->payload_length; + ctx->opayloadoff = 0; + + buflen -= (size_t)(buf_last - buf); + /* fall through */ + case SEND_PAYLOAD: + if (iocb->data_length > 0) { + size_t writelen = wslay_min(buflen, iocb->data_length); + + if (ctx->omask) { + for (i = 0; i < writelen; ++i) { + *buf_last++ = + iocb->data[i] ^ ctx->omaskkey[(ctx->opayloadoff + i) % 4]; + } + } else { + memcpy(buf_last, iocb->data, writelen); + buf_last += writelen; + } + + ctx->opayloadoff += writelen; + *pwpayloadlen = writelen; + } + + if (ctx->opayloadoff == ctx->opayloadlen) { + ctx->ostate = PREP_HEADER; + } + + return buf_last - buf; + default: + return WSLAY_ERR_INVALID_ARGUMENT; + } +} + +static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) { + ptrdiff_t len = ctx->ibuflimit - ctx->ibufmark; + memmove(ctx->ibuf, ctx->ibufmark, (size_t)len); + ctx->ibuflimit = ctx->ibuf + len; ctx->ibufmark = ctx->ibuf; } -static ssize_t wslay_recv(wslay_frame_context_ptr ctx) -{ +static ssize_t wslay_recv(wslay_frame_context_ptr ctx) { ssize_t r; - if(ctx->ibufmark != ctx->ibuf) { + if (ctx->ibufmark != ctx->ibuf) { wslay_shift_ibuf(ctx); } - r = ctx->callbacks.recv_callback - (ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit, - 0, ctx->user_data); - if(r > 0) { + r = ctx->callbacks.recv_callback( + ctx->ibuflimit, (size_t)(ctx->ibuf + sizeof(ctx->ibuf) - ctx->ibuflimit), + 0, ctx->user_data); + if (r > 0) { ctx->ibuflimit += r; } else { r = WSLAY_ERR_WANT_READ; @@ -217,17 +317,16 @@ static ssize_t wslay_recv(wslay_frame_context_ptr ctx) #define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark)) ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, - struct wslay_frame_iocb *iocb) -{ + struct wslay_frame_iocb *iocb) { ssize_t r; - if(ctx->istate == RECV_HEADER1) { + if (ctx->istate == RECV_HEADER1) { uint8_t fin, opcode, rsv, payloadlen; - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } fin = (ctx->ibufmark[0] >> 7) & 1; @@ -240,19 +339,19 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, ctx->imask = (ctx->ibufmark[0] >> 7) & 1; payloadlen = ctx->ibufmark[0] & 0x7fu; ++ctx->ibufmark; - if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { + if (wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { return WSLAY_ERR_PROTO; } - if(payloadlen == 126) { + if (payloadlen == 126) { ctx->istate = RECV_EXT_PAYLOADLEN; ctx->ireqread = 2; - } else if(payloadlen == 127) { + } else if (payloadlen == 127) { ctx->istate = RECV_EXT_PAYLOADLEN; ctx->ireqread = 8; } else { ctx->ipayloadlen = payloadlen; ctx->ipayloadoff = 0; - if(ctx->imask) { + if (ctx->imask) { ctx->istate = RECV_MASKKEY; ctx->ireqread = 4; } else { @@ -260,42 +359,41 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, } } } - if(ctx->istate == RECV_EXT_PAYLOADLEN) { - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (ctx->istate == RECV_EXT_PAYLOADLEN) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } } ctx->ipayloadlen = 0; ctx->ipayloadoff = 0; - memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread), - ctx->ibufmark, ctx->ireqread); + memcpy((uint8_t *)&ctx->ipayloadlen + (8 - ctx->ireqread), ctx->ibufmark, + ctx->ireqread); ctx->ipayloadlen = ntoh64(ctx->ipayloadlen); ctx->ibufmark += ctx->ireqread; - if(ctx->ireqread == 8) { - if(ctx->ipayloadlen < (1 << 16) || - ctx->ipayloadlen & (1ull << 63)) { + if (ctx->ireqread == 8) { + if (ctx->ipayloadlen < (1 << 16) || ctx->ipayloadlen & (1ull << 63)) { return WSLAY_ERR_PROTO; } - } else if(ctx->ipayloadlen < 126) { + } else if (ctx->ipayloadlen < 126) { return WSLAY_ERR_PROTO; } - if(ctx->imask) { + if (ctx->imask) { ctx->istate = RECV_MASKKEY; ctx->ireqread = 4; } else { ctx->istate = RECV_PAYLOAD; } } - if(ctx->istate == RECV_MASKKEY) { - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (ctx->istate == RECV_MASKKEY) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } } @@ -303,25 +401,25 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, ctx->ibufmark += 4; ctx->istate = RECV_PAYLOAD; } - if(ctx->istate == RECV_PAYLOAD) { + if (ctx->istate == RECV_PAYLOAD) { uint8_t *readlimit, *readmark; - uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff; - if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { - if((r = wslay_recv(ctx)) <= 0) { + uint64_t rempayloadlen = ctx->ipayloadlen - ctx->ipayloadoff; + if (WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } } readmark = ctx->ibufmark; - readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ? - ctx->ibuflimit : ctx->ibufmark+rempayloadlen; - if(ctx->imask) { - for(; ctx->ibufmark != readlimit; - ++ctx->ibufmark, ++ctx->ipayloadoff) { + readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen + ? ctx->ibuflimit + : ctx->ibufmark + rempayloadlen; + if (ctx->imask) { + for (; ctx->ibufmark != readlimit; ++ctx->ibufmark, ++ctx->ipayloadoff) { ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4]; } } else { ctx->ibufmark = readlimit; - ctx->ipayloadoff += readlimit-readmark; + ctx->ipayloadoff += (uint64_t)(readlimit - readmark); } iocb->fin = ctx->iom.fin; iocb->rsv = ctx->iom.rsv; @@ -329,12 +427,12 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, iocb->payload_length = ctx->ipayloadlen; iocb->mask = ctx->imask; iocb->data = readmark; - iocb->data_length = ctx->ibufmark-readmark; - if(ctx->ipayloadlen == ctx->ipayloadoff) { + iocb->data_length = (size_t)(ctx->ibufmark - readmark); + if (ctx->ipayloadlen == ctx->ipayloadoff) { ctx->istate = RECV_HEADER1; ctx->ireqread = 2; } - return iocb->data_length; + return (ssize_t)iocb->data_length; } return WSLAY_ERR_INVALID_ARGUMENT; } diff --git a/thirdparty/wslay/wslay_frame.h b/thirdparty/wslay/wslay_frame.h index 6a75858cc7..3ac98112b5 100644 --- a/thirdparty/wslay/wslay_frame.h +++ b/thirdparty/wslay/wslay_frame.h @@ -33,6 +33,7 @@ enum wslay_frame_state { PREP_HEADER, + PREP_HEADER_NOBUF, SEND_HEADER, SEND_PAYLOAD, RECV_HEADER1, diff --git a/thirdparty/wslay/wslay_stack.h b/thirdparty/wslay/wslay_macro.h index 16e4e968eb..a06cff98e1 100644 --- a/thirdparty/wslay/wslay_stack.h +++ b/thirdparty/wslay/wslay_macro.h @@ -1,7 +1,7 @@ /* * Wslay - The WebSocket Library * - * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa + * Copyright (c) 2020 Tatsuhiro Tsujikawa * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef WSLAY_STACK_H -#define WSLAY_STACK_H +#ifndef WSLAY_MACRO_H +#define WSLAY_MACRO_H #ifdef HAVE_CONFIG_H # include "config.h" @@ -31,20 +31,9 @@ #include <wslay/wslay.h> -struct wslay_stack_cell { - void *data; - struct wslay_stack_cell *next; -}; +#include <stddef.h> -struct wslay_stack { - struct wslay_stack_cell *top; -}; +#define wslay_struct_of(ptr, type, member) \ + ((type *)(void *)((char *)(ptr)-offsetof(type, member))) -struct wslay_stack* wslay_stack_new(); -void wslay_stack_free(struct wslay_stack *stack); -int wslay_stack_push(struct wslay_stack *stack, void *data); -void wslay_stack_pop(struct wslay_stack *stack); -void* wslay_stack_top(struct wslay_stack *stack); -int wslay_stack_empty(struct wslay_stack *stack); - -#endif /* WSLAY_STACK_H */ +#endif /* WSLAY_MACRO_H */ diff --git a/thirdparty/wslay/wslay_net.c b/thirdparty/wslay/wslay_net.c index d3867c21fb..e256158b4c 100644 --- a/thirdparty/wslay/wslay_net.c +++ b/thirdparty/wslay/wslay_net.c @@ -26,10 +26,9 @@ #ifndef WORDS_BIGENDIAN -uint64_t wslay_byteswap64(uint64_t x) -{ +uint64_t wslay_byteswap64(uint64_t x) { uint64_t u = ntohl(x & 0xffffffffllu); - uint64_t l = ntohl(x >> 32); + uint64_t l = ntohl((uint32_t)(x >> 32)); return (u << 32) | l; } diff --git a/thirdparty/wslay/wslay_queue.c b/thirdparty/wslay/wslay_queue.c index 8d2669687d..ebde3ba83d 100644 --- a/thirdparty/wslay/wslay_queue.c +++ b/thirdparty/wslay/wslay_queue.c @@ -27,91 +27,51 @@ #include <string.h> #include <assert.h> -struct wslay_queue* wslay_queue_new(void) -{ - struct wslay_queue *queue = (struct wslay_queue*)malloc - (sizeof(struct wslay_queue)); - if(!queue) { - return NULL; - } - queue->top = queue->tail = NULL; - return queue; -} +#include "wslay_macro.h" -void wslay_queue_free(struct wslay_queue *queue) -{ - if(!queue) { - return; - } else { - struct wslay_queue_cell *p = queue->top; - while(p) { - struct wslay_queue_cell *next = p->next; - free(p); - p = next; - } - free(queue); - } +void wslay_queue_init(struct wslay_queue *queue) { + queue->top = NULL; + queue->tail = &queue->top; } -int wslay_queue_push(struct wslay_queue *queue, void *data) -{ - struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc - (sizeof(struct wslay_queue_cell)); - if(!new_cell) { - return WSLAY_ERR_NOMEM; - } - new_cell->data = data; - new_cell->next = NULL; - if(queue->tail) { - queue->tail->next = new_cell; - queue->tail = new_cell; +void wslay_queue_deinit(struct wslay_queue *queue) { (void)queue; } - } else { - queue->top = queue->tail = new_cell; - } - return 0; +void wslay_queue_push(struct wslay_queue *queue, + struct wslay_queue_entry *ent) { + ent->next = NULL; + *queue->tail = ent; + queue->tail = &ent->next; } -int wslay_queue_push_front(struct wslay_queue *queue, void *data) -{ - struct wslay_queue_cell *new_cell = (struct wslay_queue_cell*)malloc - (sizeof(struct wslay_queue_cell)); - if(!new_cell) { - return WSLAY_ERR_NOMEM; - } - new_cell->data = data; - new_cell->next = queue->top; - queue->top = new_cell; - if(!queue->tail) { - queue->tail = queue->top; +void wslay_queue_push_front(struct wslay_queue *queue, + struct wslay_queue_entry *ent) { + ent->next = queue->top; + queue->top = ent; + + if (ent->next == NULL) { + queue->tail = &ent->next; } - return 0; } -void wslay_queue_pop(struct wslay_queue *queue) -{ - struct wslay_queue_cell *top = queue->top; - assert(top); - queue->top = top->next; - if(top == queue->tail) { - queue->tail = NULL; +void wslay_queue_pop(struct wslay_queue *queue) { + assert(queue->top); + queue->top = queue->top->next; + if (queue->top == NULL) { + queue->tail = &queue->top; } - free(top); } -void* wslay_queue_top(struct wslay_queue *queue) -{ +struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue) { assert(queue->top); - return queue->top->data; + return queue->top; } -void* wslay_queue_tail(struct wslay_queue *queue) -{ - assert(queue->tail); - return queue->tail->data; +struct wslay_queue_entry *wslay_queue_tail(struct wslay_queue *queue) { + assert(queue->top); + return wslay_struct_of(queue->tail, struct wslay_queue_entry, next); } -int wslay_queue_empty(struct wslay_queue *queue) -{ +int wslay_queue_empty(struct wslay_queue *queue) { + assert(queue->top || queue->tail == &queue->top); return queue->top == NULL; } diff --git a/thirdparty/wslay/wslay_queue.h b/thirdparty/wslay/wslay_queue.h index 55e78a042e..fa16aea489 100644 --- a/thirdparty/wslay/wslay_queue.h +++ b/thirdparty/wslay/wslay_queue.h @@ -31,23 +31,23 @@ #include <wslay/wslay.h> -struct wslay_queue_cell { - void *data; - struct wslay_queue_cell *next; +struct wslay_queue_entry { + struct wslay_queue_entry *next; }; struct wslay_queue { - struct wslay_queue_cell *top; - struct wslay_queue_cell *tail; + struct wslay_queue_entry *top; + struct wslay_queue_entry **tail; }; -struct wslay_queue* wslay_queue_new(void); -void wslay_queue_free(struct wslay_queue *queue); -int wslay_queue_push(struct wslay_queue *queue, void *data); -int wslay_queue_push_front(struct wslay_queue *queue, void *data); +void wslay_queue_init(struct wslay_queue *queue); +void wslay_queue_deinit(struct wslay_queue *queue); +void wslay_queue_push(struct wslay_queue *queue, struct wslay_queue_entry *ent); +void wslay_queue_push_front(struct wslay_queue *queue, + struct wslay_queue_entry *ent); void wslay_queue_pop(struct wslay_queue *queue); -void* wslay_queue_top(struct wslay_queue *queue); -void* wslay_queue_tail(struct wslay_queue *queue); +struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue); +struct wslay_queue_entry *wslay_queue_tail(struct wslay_queue *queue); int wslay_queue_empty(struct wslay_queue *queue); #endif /* WSLAY_QUEUE_H */ diff --git a/thirdparty/wslay/wslay_stack.c b/thirdparty/wslay/wslay_stack.c deleted file mode 100644 index 0e05d74031..0000000000 --- a/thirdparty/wslay/wslay_stack.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Wslay - The WebSocket Library - * - * Copyright (c) 2011, 2012 Tatsuhiro Tsujikawa - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "wslay_stack.h" - -#include <string.h> -#include <assert.h> - -struct wslay_stack* wslay_stack_new() -{ - struct wslay_stack *stack = (struct wslay_stack*)malloc - (sizeof(struct wslay_stack)); - if(!stack) { - return NULL; - } - stack->top = NULL; - return stack; -} - -void wslay_stack_free(struct wslay_stack *stack) -{ - struct wslay_stack_cell *p; - if(!stack) { - return; - } - p = stack->top; - while(p) { - struct wslay_stack_cell *next = p->next; - free(p); - p = next; - } - free(stack); -} - -int wslay_stack_push(struct wslay_stack *stack, void *data) -{ - struct wslay_stack_cell *new_cell = (struct wslay_stack_cell*)malloc - (sizeof(struct wslay_stack_cell)); - if(!new_cell) { - return WSLAY_ERR_NOMEM; - } - new_cell->data = data; - new_cell->next = stack->top; - stack->top = new_cell; - return 0; -} - -void wslay_stack_pop(struct wslay_stack *stack) -{ - struct wslay_stack_cell *top = stack->top; - assert(top); - stack->top = top->next; - free(top); -} - -void* wslay_stack_top(struct wslay_stack *stack) -{ - assert(stack->top); - return stack->top->data; -} - -int wslay_stack_empty(struct wslay_stack *stack) -{ - return stack->top == NULL; -} |