소스 검색

wslay: Sync with upstream 45d22583b

https://github.com/tatsuhiro-t/wslay/commit/45d22583b488f79d5a4e598cc7675c191c5ab53f

Mostly style changes, a couple new methods and fixes.
Tweak file structure a bit.
Rémi Verschelde 3 년 전
부모
커밋
a706ef3272

+ 1 - 2
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":

+ 8 - 4
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

+ 2 - 0
thirdparty/wslay/includes/config.h → 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 */

+ 4 - 3
thirdparty/wslay/msvcfix.diff → 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

+ 105 - 35
thirdparty/wslay/includes/wslay/wslay.h → 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;
@@ -228,6 +228,33 @@ void wslay_frame_context_free(wslay_frame_context_ptr ctx);
 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
@@ -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);
 
 /*

+ 0 - 0
thirdparty/wslay/includes/wslay/wslayver.h → thirdparty/wslay/wslay/wslayver.h


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 296 - 362
thirdparty/wslay/wslay_event.c


+ 8 - 12
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 */

+ 202 - 104
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;
 }

+ 1 - 0
thirdparty/wslay/wslay_frame.h

@@ -33,6 +33,7 @@
 
 enum wslay_frame_state {
   PREP_HEADER,
+  PREP_HEADER_NOBUF,
   SEND_HEADER,
   SEND_PAYLOAD,
   RECV_HEADER1,

+ 7 - 18
thirdparty/wslay/wslay_stack.h → 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 */

+ 2 - 3
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;
 }
 

+ 29 - 69
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;
 }

+ 11 - 11
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 */

+ 0 - 86
thirdparty/wslay/wslay_stack.c

@@ -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;
-}

이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.