Merge pull request #55126 from akien-mga/wslay-45d22583b
This commit is contained in:
commit
bf18965a51
|
@ -18,12 +18,11 @@ elif env["builtin_wslay"]:
|
||||||
"wslay_net.c",
|
"wslay_net.c",
|
||||||
"wslay_event.c",
|
"wslay_event.c",
|
||||||
"wslay_queue.c",
|
"wslay_queue.c",
|
||||||
"wslay_stack.c",
|
|
||||||
"wslay_frame.c",
|
"wslay_frame.c",
|
||||||
]
|
]
|
||||||
thirdparty_sources = [thirdparty_dir + s for s in thirdparty_sources]
|
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"])
|
env_ws.Append(CPPDEFINES=["HAVE_CONFIG_H"])
|
||||||
|
|
||||||
if env["platform"] == "windows" or env["platform"] == "uwp":
|
if env["platform"] == "windows" or env["platform"] == "uwp":
|
||||||
|
|
|
@ -670,14 +670,18 @@ Patches in the `patches` directory should be re-applied after updates.
|
||||||
## wslay
|
## wslay
|
||||||
|
|
||||||
- Upstream: https://github.com/tatsuhiro-t/wslay
|
- Upstream: https://github.com/tatsuhiro-t/wslay
|
||||||
- Version: 1.1.1 (c9a84aa6df8512584c77c8cd15be9536b89c35aa, 2020)
|
- Version: 1.1.1+git (45d22583b488f79d5a4e598cc7675c191c5ab53f, 2021)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
|
|
||||||
File extracted from upstream release tarball:
|
File extracted from upstream release tarball:
|
||||||
|
|
||||||
- All `*.c` and `*.h` in `lib/` and `lib/includes/`
|
- Run `cmake .` to generate `config.h` and `wslayver.h`.
|
||||||
- `wslay.h` has a small Godot addition to fix MSVC build.
|
Contents might need tweaking for Godot, review diff.
|
||||||
See `thirdparty/wslay/msvcfix.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
|
## xatlas
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
|
// -- GODOT start --
|
||||||
#ifdef BIG_ENDIAN_ENABLED
|
#ifdef BIG_ENDIAN_ENABLED
|
||||||
#define WORDS_BIGENDIAN
|
#define WORDS_BIGENDIAN
|
||||||
#endif
|
#endif
|
||||||
|
// -- GODOT end --
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
#endif /* CONFIG_H */
|
|
@ -1,8 +1,8 @@
|
||||||
diff --git a/thirdparty/wslay/includes/wslay/wslay.h b/thirdparty/wslay/includes/wslay/wslay.h
|
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
|
--- a/thirdparty/wslay/includes/wslay/wslay.h
|
||||||
+++ b/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 <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ index 2fde81a4e..9c751b05b 100644
|
||||||
+typedef SSIZE_T ssize_t;
|
+typedef SSIZE_T ssize_t;
|
||||||
+#endif
|
+#endif
|
||||||
+/* GODOT END */
|
+/* GODOT END */
|
||||||
|
+
|
||||||
/*
|
/*
|
||||||
* wslay/wslayver.h is generated from wslay/wslayver.h.in by
|
* wslay/wslayver.h is generated from wslay/wslayver.h.in by
|
||||||
|
* configure. The projects which do not use autotools can set
|
|
@ -25,7 +25,7 @@
|
||||||
#ifndef WSLAY_H
|
#ifndef WSLAY_H
|
||||||
#define WSLAY_H
|
#define WSLAY_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -155,10 +155,10 @@ enum wslay_opcode {
|
||||||
* These macros assume that rsv is constructed by ((RSV1 << 2) |
|
* These macros assume that rsv is constructed by ((RSV1 << 2) |
|
||||||
* (RSV2 << 1) | RSV3)
|
* (RSV2 << 1) | RSV3)
|
||||||
*/
|
*/
|
||||||
#define WSLAY_RSV_NONE ((uint8_t) 0)
|
#define WSLAY_RSV_NONE ((uint8_t)0)
|
||||||
#define WSLAY_RSV1_BIT (((uint8_t) 1) << 2)
|
#define WSLAY_RSV1_BIT (((uint8_t)1) << 2)
|
||||||
#define WSLAY_RSV2_BIT (((uint8_t) 1) << 1)
|
#define WSLAY_RSV2_BIT (((uint8_t)1) << 1)
|
||||||
#define WSLAY_RSV3_BIT (((uint8_t) 1) << 0)
|
#define WSLAY_RSV3_BIT (((uint8_t)1) << 0)
|
||||||
|
|
||||||
#define wslay_get_rsv1(rsv) ((rsv >> 2) & 1)
|
#define wslay_get_rsv1(rsv) ((rsv >> 2) & 1)
|
||||||
#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1)
|
#define wslay_get_rsv2(rsv) ((rsv >> 1) & 1)
|
||||||
|
@ -172,7 +172,7 @@ struct wslay_frame_iocb {
|
||||||
* RFC6455 requires 0 unless extensions are negotiated.
|
* RFC6455 requires 0 unless extensions are negotiated.
|
||||||
*/
|
*/
|
||||||
uint8_t rsv;
|
uint8_t rsv;
|
||||||
/* 4 bit opcode */
|
/* 4 bit opcode */
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
/* payload length [0, 2**63-1] */
|
/* payload length [0, 2**63-1] */
|
||||||
uint64_t payload_length;
|
uint64_t payload_length;
|
||||||
|
@ -228,6 +228,33 @@ void wslay_frame_context_free(wslay_frame_context_ptr ctx);
|
||||||
ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
struct wslay_frame_iocb *iocb);
|
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
|
* Receives WebSocket frame and stores it in iocb. This function
|
||||||
* returns the number of payload bytes received. This does not
|
* returns the number of payload bytes received. This does not
|
||||||
|
@ -276,9 +303,9 @@ struct wslay_event_on_msg_recv_arg {
|
||||||
* Callback function invoked by wslay_event_recv() when a message is
|
* Callback function invoked by wslay_event_recv() when a message is
|
||||||
* completely received.
|
* completely received.
|
||||||
*/
|
*/
|
||||||
typedef void (*wslay_event_on_msg_recv_callback)
|
typedef void (*wslay_event_on_msg_recv_callback)(
|
||||||
(wslay_event_context_ptr ctx,
|
wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg,
|
||||||
const struct wslay_event_on_msg_recv_arg *arg, void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
struct wslay_event_on_frame_recv_start_arg {
|
struct wslay_event_on_frame_recv_start_arg {
|
||||||
/* fin bit; 1 for final frame, or 0. */
|
/* 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
|
* starts to be received. This callback function is only invoked once
|
||||||
* for each frame.
|
* for each frame.
|
||||||
*/
|
*/
|
||||||
typedef void (*wslay_event_on_frame_recv_start_callback)
|
typedef void (*wslay_event_on_frame_recv_start_callback)(
|
||||||
(wslay_event_context_ptr ctx,
|
wslay_event_context_ptr ctx,
|
||||||
const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data);
|
const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data);
|
||||||
|
|
||||||
struct wslay_event_on_frame_recv_chunk_arg {
|
struct wslay_event_on_frame_recv_chunk_arg {
|
||||||
/* chunk of payload data */
|
/* 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
|
* Callback function invoked by wslay_event_recv() when a chunk of
|
||||||
* frame payload is received.
|
* frame payload is received.
|
||||||
*/
|
*/
|
||||||
typedef void (*wslay_event_on_frame_recv_chunk_callback)
|
typedef void (*wslay_event_on_frame_recv_chunk_callback)(
|
||||||
(wslay_event_context_ptr ctx,
|
wslay_event_context_ptr ctx,
|
||||||
const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data);
|
const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback function invoked by wslay_event_recv() when a frame is
|
* Callback function invoked by wslay_event_recv() when a frame is
|
||||||
* completely received.
|
* completely received.
|
||||||
*/
|
*/
|
||||||
typedef void (*wslay_event_on_frame_recv_end_callback)
|
typedef void (*wslay_event_on_frame_recv_end_callback)(
|
||||||
(wslay_event_context_ptr ctx, void *user_data);
|
wslay_event_context_ptr ctx, void *user_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback function invoked by wslay_event_recv() when it wants to
|
* Callback function invoked by wslay_event_recv() when it wants to
|
||||||
|
@ -394,9 +421,9 @@ struct wslay_event_callbacks {
|
||||||
* WSLAY_ERR_NOMEM
|
* WSLAY_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
int wslay_event_context_server_init
|
int wslay_event_context_server_init(
|
||||||
(wslay_event_context_ptr *ctx,
|
wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks,
|
||||||
const struct wslay_event_callbacks *callbacks, void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes ctx as WebSocket client. user_data is an arbitrary
|
* Initializes ctx as WebSocket client. user_data is an arbitrary
|
||||||
|
@ -409,9 +436,9 @@ int wslay_event_context_server_init
|
||||||
* WSLAY_ERR_NOMEM
|
* WSLAY_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
int wslay_event_context_client_init
|
int wslay_event_context_client_init(
|
||||||
(wslay_event_context_ptr *ctx,
|
wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks,
|
||||||
const struct wslay_event_callbacks *callbacks, void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Releases allocated resources for ctx.
|
* 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
|
* or wslay_event_context_server_init() or
|
||||||
* wslay_event_context_client_init() are replaced with callbacks.
|
* wslay_event_context_client_init() are replaced with callbacks.
|
||||||
*/
|
*/
|
||||||
void wslay_event_config_set_callbacks
|
void wslay_event_config_set_callbacks(
|
||||||
(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks);
|
wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receives messages from peer. When receiving
|
* 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);
|
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 {
|
struct wslay_event_msg {
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
const uint8_t *msg;
|
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
|
* moment, return 0. If there is an error, return -1 and set error
|
||||||
* code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error().
|
* code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error().
|
||||||
*/
|
*/
|
||||||
typedef ssize_t (*wslay_event_fragmented_msg_callback)
|
typedef ssize_t (*wslay_event_fragmented_msg_callback)(
|
||||||
(wslay_event_context_ptr ctx,
|
wslay_event_context_ptr ctx, uint8_t *buf, size_t len,
|
||||||
uint8_t *buf, size_t len, const union wslay_event_msg_source *source,
|
const union wslay_event_msg_source *source, int *eof, void *user_data);
|
||||||
int *eof, void *user_data);
|
|
||||||
|
|
||||||
struct wslay_event_fragmented_msg {
|
struct wslay_event_fragmented_msg {
|
||||||
/* opcode */
|
/* opcode */
|
||||||
|
@ -631,15 +701,16 @@ struct wslay_event_fragmented_msg {
|
||||||
* WSLAY_ERR_NOMEM
|
* WSLAY_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
int wslay_event_queue_fragmented_msg
|
int wslay_event_queue_fragmented_msg(
|
||||||
(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg);
|
wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extended version of wslay_event_queue_fragmented_msg which allows to set
|
* Extended version of wslay_event_queue_fragmented_msg which allows to set
|
||||||
* reserved bits.
|
* reserved bits.
|
||||||
*/
|
*/
|
||||||
int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx,
|
int wslay_event_queue_fragmented_msg_ex(
|
||||||
const struct wslay_event_fragmented_msg *arg, uint8_t rsv);
|
wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg,
|
||||||
|
uint8_t rsv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queues close control frame. This function is provided just for
|
* Queues close control frame. This function is provided just for
|
||||||
|
@ -669,8 +740,7 @@ int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx,
|
||||||
* WSLAY_ERR_NOMEM
|
* WSLAY_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
int wslay_event_queue_close(wslay_event_context_ptr ctx,
|
int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code,
|
||||||
uint16_t status_code,
|
|
||||||
const uint8_t *reason, size_t reason_length);
|
const uint8_t *reason, size_t reason_length);
|
||||||
|
|
||||||
/*
|
/*
|
File diff suppressed because it is too large
Load Diff
|
@ -31,10 +31,10 @@
|
||||||
|
|
||||||
#include <wslay/wslay.h>
|
#include <wslay/wslay.h>
|
||||||
|
|
||||||
struct wslay_stack;
|
#include "wslay_queue.h"
|
||||||
struct wslay_queue;
|
|
||||||
|
|
||||||
struct wslay_event_byte_chunk {
|
struct wslay_event_byte_chunk {
|
||||||
|
struct wslay_queue_entry qe;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_length;
|
size_t data_length;
|
||||||
};
|
};
|
||||||
|
@ -44,16 +44,14 @@ struct wslay_event_imsg {
|
||||||
uint8_t rsv;
|
uint8_t rsv;
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
uint32_t utf8state;
|
uint32_t utf8state;
|
||||||
struct wslay_queue *chunks;
|
struct wslay_queue chunks;
|
||||||
size_t msg_length;
|
size_t msg_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wslay_event_msg_type {
|
enum wslay_event_msg_type { WSLAY_NON_FRAGMENTED, WSLAY_FRAGMENTED };
|
||||||
WSLAY_NON_FRAGMENTED,
|
|
||||||
WSLAY_FRAGMENTED
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wslay_event_omsg {
|
struct wslay_event_omsg {
|
||||||
|
struct wslay_queue_entry qe;
|
||||||
uint8_t fin;
|
uint8_t fin;
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
uint8_t rsv;
|
uint8_t rsv;
|
||||||
|
@ -77,9 +75,7 @@ enum wslay_event_close_status {
|
||||||
WSLAY_CLOSE_SENT = 1 << 2
|
WSLAY_CLOSE_SENT = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wslay_event_config {
|
enum wslay_event_config { WSLAY_CONFIG_NO_BUFFERING = 1 << 0 };
|
||||||
WSLAY_CONFIG_NO_BUFFERING = 1 << 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wslay_event_context {
|
struct wslay_event_context {
|
||||||
/* config status, bitwise OR of enum wslay_event_config values*/
|
/* config status, bitwise OR of enum wslay_event_config values*/
|
||||||
|
@ -118,9 +114,9 @@ struct wslay_event_context {
|
||||||
is currently sent. */
|
is currently sent. */
|
||||||
struct wslay_event_omsg *omsg;
|
struct wslay_event_omsg *omsg;
|
||||||
/* Queue for non-control frames */
|
/* Queue for non-control frames */
|
||||||
struct wslay_queue/*<wslay_omsg*>*/ *send_queue;
|
struct wslay_queue /*<wslay_omsg*>*/ send_queue;
|
||||||
/* Queue for control frames */
|
/* 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 of send_queue + size of send_ctrl_queue */
|
||||||
size_t queued_msg_count;
|
size_t queued_msg_count;
|
||||||
/* The sum of message length in send_queue */
|
/* The sum of message length in send_queue */
|
||||||
|
|
|
@ -34,10 +34,9 @@
|
||||||
|
|
||||||
int wslay_frame_context_init(wslay_frame_context_ptr *ctx,
|
int wslay_frame_context_init(wslay_frame_context_ptr *ctx,
|
||||||
const struct wslay_frame_callbacks *callbacks,
|
const struct wslay_frame_callbacks *callbacks,
|
||||||
void *user_data)
|
void *user_data) {
|
||||||
{
|
*ctx = malloc(sizeof(struct wslay_frame_context));
|
||||||
*ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context));
|
if (*ctx == NULL) {
|
||||||
if(*ctx == NULL) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memset(*ctx, 0, sizeof(struct wslay_frame_context));
|
memset(*ctx, 0, sizeof(struct wslay_frame_context));
|
||||||
|
@ -50,38 +49,35 @@ int wslay_frame_context_init(wslay_frame_context_ptr *ctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wslay_frame_context_free(wslay_frame_context_ptr ctx)
|
void wslay_frame_context_free(wslay_frame_context_ptr ctx) { free(ctx); }
|
||||||
{
|
|
||||||
free(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
struct wslay_frame_iocb *iocb)
|
struct wslay_frame_iocb *iocb) {
|
||||||
{
|
if (iocb->data_length > iocb->payload_length) {
|
||||||
if(iocb->data_length > iocb->payload_length) {
|
|
||||||
return WSLAY_ERR_INVALID_ARGUMENT;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if(ctx->ostate == PREP_HEADER) {
|
if (ctx->ostate == PREP_HEADER) {
|
||||||
uint8_t *hdptr = ctx->oheader;
|
uint8_t *hdptr = ctx->oheader;
|
||||||
memset(ctx->oheader, 0, sizeof(ctx->oheader));
|
memset(ctx->oheader, 0, sizeof(ctx->oheader));
|
||||||
*hdptr |= (iocb->fin << 7) & 0x80u;
|
*hdptr |= (uint8_t)((uint8_t)(iocb->fin << 7) & 0x80u);
|
||||||
*hdptr |= (iocb->rsv << 4) & 0x70u;
|
*hdptr |= (uint8_t)((uint8_t)(iocb->rsv << 4) & 0x70u);
|
||||||
*hdptr |= iocb->opcode & 0xfu;
|
/* Suppress stubborn gcc-10 warning */
|
||||||
|
*hdptr |= (uint8_t)((uint8_t)(iocb->opcode << 0) & 0xfu);
|
||||||
++hdptr;
|
++hdptr;
|
||||||
*hdptr |= (iocb->mask << 7) & 0x80u;
|
*hdptr |= (uint8_t)((uint8_t)(iocb->mask << 7) & 0x80u);
|
||||||
if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) {
|
if (wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) {
|
||||||
return WSLAY_ERR_INVALID_ARGUMENT;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if(iocb->payload_length < 126) {
|
if (iocb->payload_length < 126) {
|
||||||
*hdptr |= iocb->payload_length;
|
*hdptr |= (uint8_t)iocb->payload_length;
|
||||||
++hdptr;
|
++hdptr;
|
||||||
} else if(iocb->payload_length < (1 << 16)) {
|
} else if (iocb->payload_length < (1 << 16)) {
|
||||||
uint16_t len = htons(iocb->payload_length);
|
uint16_t len = htons((uint16_t)iocb->payload_length);
|
||||||
*hdptr |= 126;
|
*hdptr |= 126;
|
||||||
++hdptr;
|
++hdptr;
|
||||||
memcpy(hdptr, &len, 2);
|
memcpy(hdptr, &len, 2);
|
||||||
hdptr += 2;
|
hdptr += 2;
|
||||||
} else if(iocb->payload_length < (1ull << 63)) {
|
} else if (iocb->payload_length < (1ull << 63)) {
|
||||||
uint64_t len = hton64(iocb->payload_length);
|
uint64_t len = hton64(iocb->payload_length);
|
||||||
*hdptr |= 127;
|
*hdptr |= 127;
|
||||||
++hdptr;
|
++hdptr;
|
||||||
|
@ -91,9 +87,9 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
/* Too large payload length */
|
/* Too large payload length */
|
||||||
return WSLAY_ERR_INVALID_ARGUMENT;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
if(iocb->mask) {
|
if (iocb->mask) {
|
||||||
if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4,
|
if (ctx->callbacks.genmask_callback(ctx->omaskkey, 4, ctx->user_data) !=
|
||||||
ctx->user_data) != 0) {
|
0) {
|
||||||
return WSLAY_ERR_INVALID_CALLBACK;
|
return WSLAY_ERR_INVALID_CALLBACK;
|
||||||
} else {
|
} else {
|
||||||
ctx->omask = 1;
|
ctx->omask = 1;
|
||||||
|
@ -107,21 +103,21 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
ctx->opayloadlen = iocb->payload_length;
|
ctx->opayloadlen = iocb->payload_length;
|
||||||
ctx->opayloadoff = 0;
|
ctx->opayloadoff = 0;
|
||||||
}
|
}
|
||||||
if(ctx->ostate == SEND_HEADER) {
|
if (ctx->ostate == SEND_HEADER) {
|
||||||
ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark;
|
ptrdiff_t len = ctx->oheaderlimit - ctx->oheadermark;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if(iocb->data_length > 0) {
|
if (iocb->data_length > 0) {
|
||||||
flags |= WSLAY_MSG_MORE;
|
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);
|
ctx->user_data);
|
||||||
if(r > 0) {
|
if (r > 0) {
|
||||||
if(r > len) {
|
if (r > len) {
|
||||||
return WSLAY_ERR_INVALID_CALLBACK;
|
return WSLAY_ERR_INVALID_CALLBACK;
|
||||||
} else {
|
} else {
|
||||||
ctx->oheadermark += r;
|
ctx->oheadermark += r;
|
||||||
if(ctx->oheadermark == ctx->oheaderlimit) {
|
if (ctx->oheadermark == ctx->oheaderlimit) {
|
||||||
ctx->ostate = SEND_PAYLOAD;
|
ctx->ostate = SEND_PAYLOAD;
|
||||||
} else {
|
} else {
|
||||||
return WSLAY_ERR_WANT_WRITE;
|
return WSLAY_ERR_WANT_WRITE;
|
||||||
|
@ -131,34 +127,34 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
return WSLAY_ERR_WANT_WRITE;
|
return WSLAY_ERR_WANT_WRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ctx->ostate == SEND_PAYLOAD) {
|
if (ctx->ostate == SEND_PAYLOAD) {
|
||||||
size_t totallen = 0;
|
size_t totallen = 0;
|
||||||
if(iocb->data_length > 0) {
|
if (iocb->data_length > 0) {
|
||||||
if(ctx->omask) {
|
if (ctx->omask) {
|
||||||
uint8_t temp[4096];
|
uint8_t temp[4096];
|
||||||
const uint8_t *datamark = iocb->data,
|
const uint8_t *datamark = iocb->data,
|
||||||
*datalimit = iocb->data+iocb->data_length;
|
*datalimit = iocb->data + iocb->data_length;
|
||||||
while(datamark < datalimit) {
|
while (datamark < datalimit) {
|
||||||
size_t datalen = datalimit - datamark;
|
size_t datalen = (size_t)(datalimit - datamark);
|
||||||
const uint8_t *writelimit = datamark+
|
const uint8_t *writelimit =
|
||||||
wslay_min(sizeof(temp), datalen);
|
datamark + wslay_min(sizeof(temp), datalen);
|
||||||
size_t writelen = writelimit-datamark;
|
size_t writelen = (size_t)(writelimit - datamark);
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
size_t i;
|
size_t i;
|
||||||
for(i = 0; i < writelen; ++i) {
|
for (i = 0; i < writelen; ++i) {
|
||||||
temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4];
|
temp[i] = datamark[i] ^ ctx->omaskkey[(ctx->opayloadoff + i) % 4];
|
||||||
}
|
}
|
||||||
r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data);
|
r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data);
|
||||||
if(r > 0) {
|
if (r > 0) {
|
||||||
if((size_t)r > writelen) {
|
if ((size_t)r > writelen) {
|
||||||
return WSLAY_ERR_INVALID_CALLBACK;
|
return WSLAY_ERR_INVALID_CALLBACK;
|
||||||
} else {
|
} else {
|
||||||
datamark += r;
|
datamark += r;
|
||||||
ctx->opayloadoff += r;
|
ctx->opayloadoff += (uint64_t)r;
|
||||||
totallen += r;
|
totallen += (size_t)r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(totallen > 0) {
|
if (totallen > 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return WSLAY_ERR_WANT_WRITE;
|
return WSLAY_ERR_WANT_WRITE;
|
||||||
|
@ -169,44 +165,148 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx,
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0,
|
r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0,
|
||||||
ctx->user_data);
|
ctx->user_data);
|
||||||
if(r > 0) {
|
if (r > 0) {
|
||||||
if((size_t)r > iocb->data_length) {
|
if ((size_t)r > iocb->data_length) {
|
||||||
return WSLAY_ERR_INVALID_CALLBACK;
|
return WSLAY_ERR_INVALID_CALLBACK;
|
||||||
} else {
|
} else {
|
||||||
ctx->opayloadoff += r;
|
ctx->opayloadoff += (uint64_t)r;
|
||||||
totallen = r;
|
totallen = (size_t)r;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return WSLAY_ERR_WANT_WRITE;
|
return WSLAY_ERR_WANT_WRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ctx->opayloadoff == ctx->opayloadlen) {
|
if (ctx->opayloadoff == ctx->opayloadlen) {
|
||||||
ctx->ostate = PREP_HEADER;
|
ctx->ostate = PREP_HEADER;
|
||||||
}
|
}
|
||||||
return totallen;
|
return (ssize_t)totallen;
|
||||||
}
|
}
|
||||||
return WSLAY_ERR_INVALID_ARGUMENT;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wslay_shift_ibuf(wslay_frame_context_ptr ctx)
|
ssize_t wslay_frame_write(wslay_frame_context_ptr ctx,
|
||||||
{
|
struct wslay_frame_iocb *iocb, uint8_t *buf,
|
||||||
ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark;
|
size_t buflen, size_t *pwpayloadlen) {
|
||||||
memmove(ctx->ibuf, ctx->ibufmark, len);
|
uint8_t *buf_last = buf;
|
||||||
ctx->ibuflimit = ctx->ibuf+len;
|
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;
|
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;
|
ssize_t r;
|
||||||
if(ctx->ibufmark != ctx->ibuf) {
|
if (ctx->ibufmark != ctx->ibuf) {
|
||||||
wslay_shift_ibuf(ctx);
|
wslay_shift_ibuf(ctx);
|
||||||
}
|
}
|
||||||
r = ctx->callbacks.recv_callback
|
r = ctx->callbacks.recv_callback(
|
||||||
(ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit,
|
ctx->ibuflimit, (size_t)(ctx->ibuf + sizeof(ctx->ibuf) - ctx->ibuflimit),
|
||||||
0, ctx->user_data);
|
0, ctx->user_data);
|
||||||
if(r > 0) {
|
if (r > 0) {
|
||||||
ctx->ibuflimit += r;
|
ctx->ibuflimit += r;
|
||||||
} else {
|
} else {
|
||||||
r = WSLAY_ERR_WANT_READ;
|
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))
|
#define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark))
|
||||||
|
|
||||||
ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
|
ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
|
||||||
struct wslay_frame_iocb *iocb)
|
struct wslay_frame_iocb *iocb) {
|
||||||
{
|
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
if(ctx->istate == RECV_HEADER1) {
|
if (ctx->istate == RECV_HEADER1) {
|
||||||
uint8_t fin, opcode, rsv, payloadlen;
|
uint8_t fin, opcode, rsv, payloadlen;
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
if((r = wslay_recv(ctx)) <= 0) {
|
if ((r = wslay_recv(ctx)) <= 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
return WSLAY_ERR_WANT_READ;
|
return WSLAY_ERR_WANT_READ;
|
||||||
}
|
}
|
||||||
fin = (ctx->ibufmark[0] >> 7) & 1;
|
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;
|
ctx->imask = (ctx->ibufmark[0] >> 7) & 1;
|
||||||
payloadlen = ctx->ibufmark[0] & 0x7fu;
|
payloadlen = ctx->ibufmark[0] & 0x7fu;
|
||||||
++ctx->ibufmark;
|
++ctx->ibufmark;
|
||||||
if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) {
|
if (wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) {
|
||||||
return WSLAY_ERR_PROTO;
|
return WSLAY_ERR_PROTO;
|
||||||
}
|
}
|
||||||
if(payloadlen == 126) {
|
if (payloadlen == 126) {
|
||||||
ctx->istate = RECV_EXT_PAYLOADLEN;
|
ctx->istate = RECV_EXT_PAYLOADLEN;
|
||||||
ctx->ireqread = 2;
|
ctx->ireqread = 2;
|
||||||
} else if(payloadlen == 127) {
|
} else if (payloadlen == 127) {
|
||||||
ctx->istate = RECV_EXT_PAYLOADLEN;
|
ctx->istate = RECV_EXT_PAYLOADLEN;
|
||||||
ctx->ireqread = 8;
|
ctx->ireqread = 8;
|
||||||
} else {
|
} else {
|
||||||
ctx->ipayloadlen = payloadlen;
|
ctx->ipayloadlen = payloadlen;
|
||||||
ctx->ipayloadoff = 0;
|
ctx->ipayloadoff = 0;
|
||||||
if(ctx->imask) {
|
if (ctx->imask) {
|
||||||
ctx->istate = RECV_MASKKEY;
|
ctx->istate = RECV_MASKKEY;
|
||||||
ctx->ireqread = 4;
|
ctx->ireqread = 4;
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,42 +359,41 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ctx->istate == RECV_EXT_PAYLOADLEN) {
|
if (ctx->istate == RECV_EXT_PAYLOADLEN) {
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
if((r = wslay_recv(ctx)) <= 0) {
|
if ((r = wslay_recv(ctx)) <= 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
return WSLAY_ERR_WANT_READ;
|
return WSLAY_ERR_WANT_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx->ipayloadlen = 0;
|
ctx->ipayloadlen = 0;
|
||||||
ctx->ipayloadoff = 0;
|
ctx->ipayloadoff = 0;
|
||||||
memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread),
|
memcpy((uint8_t *)&ctx->ipayloadlen + (8 - ctx->ireqread), ctx->ibufmark,
|
||||||
ctx->ibufmark, ctx->ireqread);
|
ctx->ireqread);
|
||||||
ctx->ipayloadlen = ntoh64(ctx->ipayloadlen);
|
ctx->ipayloadlen = ntoh64(ctx->ipayloadlen);
|
||||||
ctx->ibufmark += ctx->ireqread;
|
ctx->ibufmark += ctx->ireqread;
|
||||||
if(ctx->ireqread == 8) {
|
if (ctx->ireqread == 8) {
|
||||||
if(ctx->ipayloadlen < (1 << 16) ||
|
if (ctx->ipayloadlen < (1 << 16) || ctx->ipayloadlen & (1ull << 63)) {
|
||||||
ctx->ipayloadlen & (1ull << 63)) {
|
|
||||||
return WSLAY_ERR_PROTO;
|
return WSLAY_ERR_PROTO;
|
||||||
}
|
}
|
||||||
} else if(ctx->ipayloadlen < 126) {
|
} else if (ctx->ipayloadlen < 126) {
|
||||||
return WSLAY_ERR_PROTO;
|
return WSLAY_ERR_PROTO;
|
||||||
}
|
}
|
||||||
if(ctx->imask) {
|
if (ctx->imask) {
|
||||||
ctx->istate = RECV_MASKKEY;
|
ctx->istate = RECV_MASKKEY;
|
||||||
ctx->ireqread = 4;
|
ctx->ireqread = 4;
|
||||||
} else {
|
} else {
|
||||||
ctx->istate = RECV_PAYLOAD;
|
ctx->istate = RECV_PAYLOAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(ctx->istate == RECV_MASKKEY) {
|
if (ctx->istate == RECV_MASKKEY) {
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
if((r = wslay_recv(ctx)) <= 0) {
|
if ((r = wslay_recv(ctx)) <= 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) {
|
||||||
return WSLAY_ERR_WANT_READ;
|
return WSLAY_ERR_WANT_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,25 +401,25 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx,
|
||||||
ctx->ibufmark += 4;
|
ctx->ibufmark += 4;
|
||||||
ctx->istate = RECV_PAYLOAD;
|
ctx->istate = RECV_PAYLOAD;
|
||||||
}
|
}
|
||||||
if(ctx->istate == RECV_PAYLOAD) {
|
if (ctx->istate == RECV_PAYLOAD) {
|
||||||
uint8_t *readlimit, *readmark;
|
uint8_t *readlimit, *readmark;
|
||||||
uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff;
|
uint64_t rempayloadlen = ctx->ipayloadlen - ctx->ipayloadoff;
|
||||||
if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) {
|
if (WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) {
|
||||||
if((r = wslay_recv(ctx)) <= 0) {
|
if ((r = wslay_recv(ctx)) <= 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readmark = ctx->ibufmark;
|
readmark = ctx->ibufmark;
|
||||||
readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ?
|
readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen
|
||||||
ctx->ibuflimit : ctx->ibufmark+rempayloadlen;
|
? ctx->ibuflimit
|
||||||
if(ctx->imask) {
|
: ctx->ibufmark + rempayloadlen;
|
||||||
for(; ctx->ibufmark != readlimit;
|
if (ctx->imask) {
|
||||||
++ctx->ibufmark, ++ctx->ipayloadoff) {
|
for (; ctx->ibufmark != readlimit; ++ctx->ibufmark, ++ctx->ipayloadoff) {
|
||||||
ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4];
|
ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ctx->ibufmark = readlimit;
|
ctx->ibufmark = readlimit;
|
||||||
ctx->ipayloadoff += readlimit-readmark;
|
ctx->ipayloadoff += (uint64_t)(readlimit - readmark);
|
||||||
}
|
}
|
||||||
iocb->fin = ctx->iom.fin;
|
iocb->fin = ctx->iom.fin;
|
||||||
iocb->rsv = ctx->iom.rsv;
|
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->payload_length = ctx->ipayloadlen;
|
||||||
iocb->mask = ctx->imask;
|
iocb->mask = ctx->imask;
|
||||||
iocb->data = readmark;
|
iocb->data = readmark;
|
||||||
iocb->data_length = ctx->ibufmark-readmark;
|
iocb->data_length = (size_t)(ctx->ibufmark - readmark);
|
||||||
if(ctx->ipayloadlen == ctx->ipayloadoff) {
|
if (ctx->ipayloadlen == ctx->ipayloadoff) {
|
||||||
ctx->istate = RECV_HEADER1;
|
ctx->istate = RECV_HEADER1;
|
||||||
ctx->ireqread = 2;
|
ctx->ireqread = 2;
|
||||||
}
|
}
|
||||||
return iocb->data_length;
|
return (ssize_t)iocb->data_length;
|
||||||
}
|
}
|
||||||
return WSLAY_ERR_INVALID_ARGUMENT;
|
return WSLAY_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
enum wslay_frame_state {
|
enum wslay_frame_state {
|
||||||
PREP_HEADER,
|
PREP_HEADER,
|
||||||
|
PREP_HEADER_NOBUF,
|
||||||
SEND_HEADER,
|
SEND_HEADER,
|
||||||
SEND_PAYLOAD,
|
SEND_PAYLOAD,
|
||||||
RECV_HEADER1,
|
RECV_HEADER1,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Wslay - The WebSocket Library
|
* 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
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* 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
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifndef WSLAY_STACK_H
|
#ifndef WSLAY_MACRO_H
|
||||||
#define WSLAY_STACK_H
|
#define WSLAY_MACRO_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
@ -31,20 +31,9 @@
|
||||||
|
|
||||||
#include <wslay/wslay.h>
|
#include <wslay/wslay.h>
|
||||||
|
|
||||||
struct wslay_stack_cell {
|
#include <stddef.h>
|
||||||
void *data;
|
|
||||||
struct wslay_stack_cell *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wslay_stack {
|
#define wslay_struct_of(ptr, type, member) \
|
||||||
struct wslay_stack_cell *top;
|
((type *)(void *)((char *)(ptr)-offsetof(type, member)))
|
||||||
};
|
|
||||||
|
|
||||||
struct wslay_stack* wslay_stack_new();
|
#endif /* WSLAY_MACRO_H */
|
||||||
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 */
|
|
|
@ -26,10 +26,9 @@
|
||||||
|
|
||||||
#ifndef WORDS_BIGENDIAN
|
#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 u = ntohl(x & 0xffffffffllu);
|
||||||
uint64_t l = ntohl(x >> 32);
|
uint64_t l = ntohl((uint32_t)(x >> 32));
|
||||||
return (u << 32) | l;
|
return (u << 32) | l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,91 +27,51 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
struct wslay_queue* wslay_queue_new(void)
|
#include "wslay_macro.h"
|
||||||
{
|
|
||||||
struct wslay_queue *queue = (struct wslay_queue*)malloc
|
void wslay_queue_init(struct wslay_queue *queue) {
|
||||||
(sizeof(struct wslay_queue));
|
queue->top = NULL;
|
||||||
if(!queue) {
|
queue->tail = &queue->top;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
queue->top = queue->tail = NULL;
|
|
||||||
return queue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wslay_queue_free(struct wslay_queue *queue)
|
void wslay_queue_deinit(struct wslay_queue *queue) { (void)queue; }
|
||||||
{
|
|
||||||
if(!queue) {
|
void wslay_queue_push(struct wslay_queue *queue,
|
||||||
return;
|
struct wslay_queue_entry *ent) {
|
||||||
} else {
|
ent->next = NULL;
|
||||||
struct wslay_queue_cell *p = queue->top;
|
*queue->tail = ent;
|
||||||
while(p) {
|
queue->tail = &ent->next;
|
||||||
struct wslay_queue_cell *next = p->next;
|
}
|
||||||
free(p);
|
|
||||||
p = next;
|
void wslay_queue_push_front(struct wslay_queue *queue,
|
||||||
}
|
struct wslay_queue_entry *ent) {
|
||||||
free(queue);
|
ent->next = queue->top;
|
||||||
|
queue->top = ent;
|
||||||
|
|
||||||
|
if (ent->next == NULL) {
|
||||||
|
queue->tail = &ent->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int wslay_queue_push(struct wslay_queue *queue, void *data)
|
void wslay_queue_pop(struct wslay_queue *queue) {
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
queue->top = queue->tail = new_cell;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
free(top);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* wslay_queue_top(struct wslay_queue *queue)
|
|
||||||
{
|
|
||||||
assert(queue->top);
|
assert(queue->top);
|
||||||
return queue->top->data;
|
queue->top = queue->top->next;
|
||||||
|
if (queue->top == NULL) {
|
||||||
|
queue->tail = &queue->top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* wslay_queue_tail(struct wslay_queue *queue)
|
struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue) {
|
||||||
{
|
assert(queue->top);
|
||||||
assert(queue->tail);
|
return queue->top;
|
||||||
return queue->tail->data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wslay_queue_empty(struct wslay_queue *queue)
|
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) {
|
||||||
|
assert(queue->top || queue->tail == &queue->top);
|
||||||
return queue->top == NULL;
|
return queue->top == NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,23 +31,23 @@
|
||||||
|
|
||||||
#include <wslay/wslay.h>
|
#include <wslay/wslay.h>
|
||||||
|
|
||||||
struct wslay_queue_cell {
|
struct wslay_queue_entry {
|
||||||
void *data;
|
struct wslay_queue_entry *next;
|
||||||
struct wslay_queue_cell *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wslay_queue {
|
struct wslay_queue {
|
||||||
struct wslay_queue_cell *top;
|
struct wslay_queue_entry *top;
|
||||||
struct wslay_queue_cell *tail;
|
struct wslay_queue_entry **tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wslay_queue* wslay_queue_new(void);
|
void wslay_queue_init(struct wslay_queue *queue);
|
||||||
void wslay_queue_free(struct wslay_queue *queue);
|
void wslay_queue_deinit(struct wslay_queue *queue);
|
||||||
int wslay_queue_push(struct wslay_queue *queue, void *data);
|
void wslay_queue_push(struct wslay_queue *queue, struct wslay_queue_entry *ent);
|
||||||
int wslay_queue_push_front(struct wslay_queue *queue, void *data);
|
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_pop(struct wslay_queue *queue);
|
||||||
void* wslay_queue_top(struct wslay_queue *queue);
|
struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue);
|
||||||
void* wslay_queue_tail(struct wslay_queue *queue);
|
struct wslay_queue_entry *wslay_queue_tail(struct wslay_queue *queue);
|
||||||
int wslay_queue_empty(struct wslay_queue *queue);
|
int wslay_queue_empty(struct wslay_queue *queue);
|
||||||
|
|
||||||
#endif /* WSLAY_QUEUE_H */
|
#endif /* WSLAY_QUEUE_H */
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue