diff --git a/deps/wslay/NEWS b/deps/wslay/NEWS index 550f980e..efcabf63 100644 --- a/deps/wslay/NEWS +++ b/deps/wslay/NEWS @@ -1,47 +1,82 @@ -wslay 1.0.0 +wslay 1.1.1 =========== Release Note ------------ -This release fixes several build issues. Most changes were introduced -by contributors. Thank you for all the contributions in this project. -Because wslay is very stable since the previous release (more than 2 -years ago), we mark this release 1.0.0. +This release fixes the bug that eof is not evaluated after the +invocation of read_callback. Changes ------- -* Fix NULL check in wslay_frame_context_init. +* Check for eof when read_callback returns 0 (GH-47) - Patch from Witchakorn Kamolpornwijit + Patch from Robert Bragg -* the examples uses epoll and thus only be built on linux + - Patch from Kazuho Oku +wslay 1.1.0 +=========== -* build: allow one to build out-of-tree documentation +Release Note +------------ - Patch from Vincent Bernat +This release adds CMake build support and the ability to set and +verify reserved bits. Build issue with nettle >= 3.4 was fixed. -* build: fix `./configure` when nettle is not present +Changes +------- - `PKG_CHECK_MODULES` will fail unless we give it an action to execute - on failure. When nettle is not available, we set `have_nettle` to - `no`. +* Fix compilation of examples - Patch from Vincent Bernat + Since 3.4 nettle defines base64_encode_raw like this: -* Adds the ability to override the version header include with a - define. This enables projects to set the build version from the - compile environment and avoid the need to generate the version - header. + void base64_encode_raw(char *dst, size_t length, const uint8_t *src); - Patch from Ben Vanik + So examples have to be adjusted. More read at + https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.4_release_20171119/NEWS#L49-53 -* Improve http_handshake in fork-echoserver. + Patch from Sergey Avseyev - Patch from Gurjeet Singh +* check for 0 length before memcpy: -* Don't send any pending control frame other than Close control frame - after Close is queued. + .../wslay/lib/wslay_event.c:304:7: runtime error: null pointer passed as argument 2, which is declared to never be null + + Patch from Anders Bakken + +* Skip UTF-8 validation for PMCE fragments + + If the message was marked with rsv1 on the initial frame then we + should skip utf-8 validation on subsequent continuation frames as + well. + + Added test for this case. + + Found by autobahn wstest tool. + + Patch from Isaac Boukris + +* Allow RSV1 bit in event-based API for PMCE - RFC 7692 + + Add a new function wslay_event_set_allowed_rsv_bits which only accpet + RSV1 for now (or 0 to disable). + + Skip UTF-8 validation on frames with RSV1 set as it is too early for that. + + Add extended versions of wslay_event_queue_msg functions which also + take the reserved bits to set for this message. + + Patch from Isaac Boukris + +* fixed missing malloc guard + + Patch from Jakub Piskorz + +* Fix argc check. + + Patch from Anders Bakken + +* CMake support + + Patch from wonder-mice diff --git a/deps/wslay/README.rst b/deps/wslay/README.rst index 446539dc..9f0d8140 100644 --- a/deps/wslay/README.rst +++ b/deps/wslay/README.rst @@ -1,7 +1,7 @@ Wslay - The WebSocket library ============================= -Project Web: https://github.com/tatsuhiro-t/wslay +Project Web: https://tatsuhiro-t.github.io/wslay/ Wslay is a WebSocket library written in C. It implements the protocol version 13 described in diff --git a/deps/wslay/configure.ac b/deps/wslay/configure.ac index fc5ccdbb..2942b7a6 100644 --- a/deps/wslay/configure.ac +++ b/deps/wslay/configure.ac @@ -21,15 +21,15 @@ dnl LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION dnl OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION dnl WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AC_PREREQ(2.61) -AC_INIT([wslay], [1.0.1-DEV], [t-tujikawa@users.sourceforge.net]) +AC_INIT([wslay], [1.1.1], [t-tujikawa@users.sourceforge.net]) LT_PREREQ([2.2.6]) LT_INIT() AC_CONFIG_AUX_DIR([.]) dnl See versioning rule: dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html -AC_SUBST(LT_CURRENT, 0) +AC_SUBST(LT_CURRENT, 1) AC_SUBST(LT_REVISION, 1) -AC_SUBST(LT_AGE, 0) +AC_SUBST(LT_AGE, 1) AC_CANONICAL_BUILD AC_CANONICAL_HOST @@ -40,6 +40,14 @@ AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE() AC_CONFIG_HEADERS([config.h]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Checks for command-line options +AC_ARG_ENABLE([werror], + [AS_HELP_STRING([--enable-werror], + [Turn on compile time warnings])], + [werror=$enableval], [werror=no]) + dnl Checks for programs AC_PROG_CC AC_PROG_CXX diff --git a/deps/wslay/examples/echoserv.cc b/deps/wslay/examples/echoserv.cc index 961feaff..48e5d3f1 100644 --- a/deps/wslay/examples/echoserv.cc +++ b/deps/wslay/examples/echoserv.cc @@ -53,8 +53,7 @@ #include #include -int create_listen_socket(const char *service) -{ +int create_listen_socket(const char *service) { struct addrinfo hints; int sfd = -1; int r; @@ -64,27 +63,27 @@ int create_listen_socket(const char *service) hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; struct addrinfo *res; r = getaddrinfo(0, service, &hints, &res); - if(r != 0) { + if (r != 0) { std::cerr << "getaddrinfo: " << gai_strerror(r) << std::endl; return -1; } - for(struct addrinfo *rp = res; rp; rp = rp->ai_next) { + for (struct addrinfo *rp = res; rp; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if(sfd == -1) { + if (sfd == -1) { continue; } int val = 1; - if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, - static_cast(sizeof(val))) == -1) { + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, + static_cast(sizeof(val))) == -1) { continue; } - if(bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { + if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { break; } close(sfd); } freeaddrinfo(res); - if(listen(sfd, 16) == -1) { + if (listen(sfd, 16) == -1) { perror("listen"); close(sfd); return -1; @@ -92,46 +91,45 @@ int create_listen_socket(const char *service) return sfd; } -int make_non_block(int fd) -{ +int make_non_block(int fd) { int flags, r; - while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); - if(flags == -1) { + while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR) + ; + if (flags == -1) { return -1; } - while((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); - if(r == -1) { + while ((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR) + ; + if (r == -1) { return -1; } return 0; } -std::string sha1(const std::string& src) -{ +std::string sha1(const std::string &src) { sha1_ctx ctx; sha1_init(&ctx); - sha1_update(&ctx, src.size(), reinterpret_cast(src.c_str())); + sha1_update(&ctx, src.size(), reinterpret_cast(src.c_str())); uint8_t temp[SHA1_DIGEST_SIZE]; sha1_digest(&ctx, SHA1_DIGEST_SIZE, temp); std::string res(&temp[0], &temp[SHA1_DIGEST_SIZE]); return res; } -std::string base64(const std::string& src) -{ +std::string base64(const std::string &src) { base64_encode_ctx ctx; base64_encode_init(&ctx); int dstlen = BASE64_ENCODE_RAW_LENGTH(src.size()); - uint8_t *dst = new uint8_t[dstlen]; - base64_encode_raw(dst, src.size(), reinterpret_cast(src.c_str())); + char *dst = new char[dstlen]; + base64_encode_raw(dst, src.size(), + reinterpret_cast(src.c_str())); std::string res(&dst[0], &dst[dstlen]); - delete [] dst; + delete[] dst; return res; } -std::string create_acceptkey(const std::string& clientkey) -{ - std::string s = clientkey+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +std::string create_acceptkey(const std::string &clientkey) { + std::string s = clientkey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; return base64(sha1(s)); } @@ -144,12 +142,11 @@ public: virtual bool want_write() = 0; virtual int fd() const = 0; virtual bool finish() = 0; - virtual EventHandler* next() = 0; + virtual EventHandler *next() = 0; }; -ssize_t send_callback(wslay_event_context_ptr ctx, - const uint8_t *data, size_t len, int flags, - void *user_data); +ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, + size_t len, int flags, void *user_data); ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, void *user_data); void on_msg_recv_callback(wslay_event_context_ptr ctx, @@ -158,93 +155,71 @@ void on_msg_recv_callback(wslay_event_context_ptr ctx, class EchoWebSocketHandler : public EventHandler { public: - EchoWebSocketHandler(int fd) - : fd_(fd) - { + EchoWebSocketHandler(int fd) : fd_(fd) { struct wslay_event_callbacks callbacks = { - recv_callback, - send_callback, - NULL, /* genmask_callback */ - NULL, /* on_frame_recv_start_callback */ - NULL, /* on_frame_recv_callback */ - NULL, /* on_frame_recv_end_callback */ - on_msg_recv_callback - }; + recv_callback, + send_callback, + NULL, /* genmask_callback */ + NULL, /* on_frame_recv_start_callback */ + NULL, /* on_frame_recv_callback */ + NULL, /* on_frame_recv_end_callback */ + on_msg_recv_callback}; wslay_event_context_server_init(&ctx_, &callbacks, this); } - virtual ~EchoWebSocketHandler() - { + virtual ~EchoWebSocketHandler() { wslay_event_context_free(ctx_); shutdown(fd_, SHUT_WR); close(fd_); } - virtual int on_read_event() - { - if(wslay_event_recv(ctx_) == 0) { + virtual int on_read_event() { + if (wslay_event_recv(ctx_) == 0) { return 0; } else { return -1; } } - virtual int on_write_event() - { - if(wslay_event_send(ctx_) == 0) { + virtual int on_write_event() { + if (wslay_event_send(ctx_) == 0) { return 0; } else { return -1; } } - ssize_t send_data(const uint8_t *data, size_t len, int flags) - { + ssize_t send_data(const uint8_t *data, size_t len, int flags) { ssize_t r; int sflags = 0; #ifdef MSG_MORE - if(flags & WSLAY_MSG_MORE) { + if (flags & WSLAY_MSG_MORE) { sflags |= MSG_MORE; } #endif // MSG_MORE - while((r = send(fd_, data, len, sflags)) == -1 && errno == EINTR); + while ((r = send(fd_, data, len, sflags)) == -1 && errno == EINTR) + ; return r; } - ssize_t recv_data(uint8_t *data, size_t len, int flags) - { + ssize_t recv_data(uint8_t *data, size_t len, int flags) { ssize_t r; - while((r = recv(fd_, data, len, 0)) == -1 && errno == EINTR); + while ((r = recv(fd_, data, len, 0)) == -1 && errno == EINTR) + ; return r; } - virtual bool want_read() - { - return wslay_event_want_read(ctx_); - } - virtual bool want_write() - { - return wslay_event_want_write(ctx_); - } - virtual int fd() const - { - return fd_; - } - virtual bool finish() - { - return !want_read() && !want_write(); - } - virtual EventHandler* next() - { - return 0; - } + virtual bool want_read() { return wslay_event_want_read(ctx_); } + virtual bool want_write() { return wslay_event_want_write(ctx_); } + virtual int fd() const { return fd_; } + virtual bool finish() { return !want_read() && !want_write(); } + virtual EventHandler *next() { return 0; } + private: int fd_; wslay_event_context_ptr ctx_; }; -ssize_t send_callback(wslay_event_context_ptr ctx, - const uint8_t *data, size_t len, int flags, - void *user_data) -{ - EchoWebSocketHandler *sv = (EchoWebSocketHandler*)user_data; +ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, + size_t len, int flags, void *user_data) { + EchoWebSocketHandler *sv = (EchoWebSocketHandler *)user_data; ssize_t r = sv->send_data(data, len, flags); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); @@ -254,17 +229,16 @@ ssize_t send_callback(wslay_event_context_ptr ctx, } ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, - int flags, void *user_data) -{ - EchoWebSocketHandler *sv = (EchoWebSocketHandler*)user_data; + int flags, void *user_data) { + EchoWebSocketHandler *sv = (EchoWebSocketHandler *)user_data; ssize_t r = sv->recv_data(data, len, flags); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); } - } else if(r == 0) { + } else if (r == 0) { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); r = -1; } @@ -273,50 +247,44 @@ ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, void on_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ - if(!wslay_is_ctrl_frame(arg->opcode)) { - struct wslay_event_msg msgarg = { - arg->opcode, arg->msg, arg->msg_length - }; + void *user_data) { + if (!wslay_is_ctrl_frame(arg->opcode)) { + struct wslay_event_msg msgarg = {arg->opcode, arg->msg, arg->msg_length}; wslay_event_queue_msg(ctx, &msgarg); } } class HttpHandshakeSendHandler : public EventHandler { public: - HttpHandshakeSendHandler(int fd, const std::string& accept_key) - : fd_(fd), - resheaders_("HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: "+accept_key+"\r\n" - "\r\n"), - off_(0) - {} - virtual ~HttpHandshakeSendHandler() - { - if(fd_ != -1) { + HttpHandshakeSendHandler(int fd, const std::string &accept_key) + : fd_(fd), + resheaders_("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + + accept_key + + "\r\n" + "\r\n"), + off_(0) {} + virtual ~HttpHandshakeSendHandler() { + if (fd_ != -1) { shutdown(fd_, SHUT_WR); close(fd_); } } - virtual int on_read_event() - { - return 0; - } - virtual int on_write_event() - { - while(1) { - size_t len = resheaders_.size()-off_; - if(len == 0) { + virtual int on_read_event() { return 0; } + virtual int on_write_event() { + while (1) { + size_t len = resheaders_.size() - off_; + if (len == 0) { break; } ssize_t r; - while((r = write(fd_, resheaders_.c_str()+off_, len)) == -1 && - errno == EINTR); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + while ((r = write(fd_, resheaders_.c_str() + off_, len)) == -1 && + errno == EINTR) + ; + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { break; } else { perror("write"); @@ -328,25 +296,12 @@ public: } return 0; } - virtual bool want_read() - { - return false; - } - virtual bool want_write() - { - return true; - } - virtual int fd() const - { - return fd_; - } - virtual bool finish() - { - return off_ == resheaders_.size(); - } - virtual EventHandler* next() - { - if(finish()) { + virtual bool want_read() { return false; } + virtual bool want_write() { return true; } + virtual int fd() const { return fd_; } + virtual bool finish() { return off_ == resheaders_.size(); } + virtual EventHandler *next() { + if (finish()) { int fd = fd_; fd_ = -1; return new EchoWebSocketHandler(fd); @@ -354,6 +309,7 @@ public: return 0; } } + private: int fd_; std::string headers_; @@ -363,79 +319,60 @@ private: class HttpHandshakeRecvHandler : public EventHandler { public: - HttpHandshakeRecvHandler(int fd) - : fd_(fd) - {} - virtual ~HttpHandshakeRecvHandler() - { - if(fd_ != -1) { + HttpHandshakeRecvHandler(int fd) : fd_(fd) {} + virtual ~HttpHandshakeRecvHandler() { + if (fd_ != -1) { close(fd_); } } - virtual int on_read_event() - { + virtual int on_read_event() { char buf[4096]; ssize_t r; std::string client_key; - while(1) { - while((r = read(fd_, buf, sizeof(buf))) == -1 && errno == EINTR); - if(r == -1) { - if(errno == EWOULDBLOCK || errno == EAGAIN) { + while (1) { + while ((r = read(fd_, buf, sizeof(buf))) == -1 && errno == EINTR) + ; + if (r == -1) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { break; } else { perror("read"); return -1; } - } else if(r == 0) { + } else if (r == 0) { std::cerr << "http_upgrade: Got EOF" << std::endl; return -1; } else { - headers_.append(buf, buf+r); - if(headers_.size() > 8192) { + headers_.append(buf, buf + r); + if (headers_.size() > 8192) { std::cerr << "Too large http header" << std::endl; return -1; } } } - if(headers_.find("\r\n\r\n") != std::string::npos) { + if (headers_.find("\r\n\r\n") != std::string::npos) { std::string::size_type keyhdstart; - if(headers_.find("Upgrade: websocket\r\n") == std::string::npos || - headers_.find("Connection: Upgrade\r\n") == std::string::npos || - (keyhdstart = headers_.find("Sec-WebSocket-Key: ")) == - std::string::npos) { + if (headers_.find("Upgrade: websocket\r\n") == std::string::npos || + headers_.find("Connection: Upgrade\r\n") == std::string::npos || + (keyhdstart = headers_.find("Sec-WebSocket-Key: ")) == + std::string::npos) { std::cerr << "http_upgrade: missing required headers" << std::endl; return -1; } keyhdstart += 19; std::string::size_type keyhdend = headers_.find("\r\n", keyhdstart); - client_key = headers_.substr(keyhdstart, keyhdend-keyhdstart); + client_key = headers_.substr(keyhdstart, keyhdend - keyhdstart); accept_key_ = create_acceptkey(client_key); } return 0; } - virtual int on_write_event() - { - return 0; - } - virtual bool want_read() - { - return true; - } - virtual bool want_write() - { - return false; - } - virtual int fd() const - { - return fd_; - } - virtual bool finish() - { - return !accept_key_.empty(); - } - virtual EventHandler* next() - { - if(finish()) { + virtual int on_write_event() { return 0; } + virtual bool want_read() { return true; } + virtual bool want_write() { return false; } + virtual int fd() const { return fd_; } + virtual bool finish() { return !accept_key_.empty(); } + virtual EventHandler *next() { + if (finish()) { int fd = fd_; fd_ = -1; return new HttpHandshakeSendHandler(fd, accept_key_); @@ -443,6 +380,7 @@ public: return 0; } } + private: int fd_; std::string headers_; @@ -451,54 +389,35 @@ private: class ListenEventHandler : public EventHandler { public: - ListenEventHandler(int fd) - : fd_(fd), cfd_(-1) - {} - virtual ~ListenEventHandler() - { + ListenEventHandler(int fd) : fd_(fd), cfd_(-1) {} + virtual ~ListenEventHandler() { close(fd_); close(cfd_); } - virtual int on_read_event() - { - if(cfd_ != -1) { + virtual int on_read_event() { + if (cfd_ != -1) { close(cfd_); } - while((cfd_ = accept(fd_, 0, 0)) == -1 && errno == EINTR); - if(cfd_ == -1) { + while ((cfd_ = accept(fd_, 0, 0)) == -1 && errno == EINTR) + ; + if (cfd_ == -1) { perror("accept"); } return 0; } - virtual int on_write_event() - { - return 0; - } - virtual bool want_read() - { - return true; - } - virtual bool want_write() - { - return false; - } - virtual int fd() const - { - return fd_; - } - virtual bool finish() - { - return false; - } - virtual EventHandler* next() - { - if(cfd_ != -1) { + virtual int on_write_event() { return 0; } + virtual bool want_read() { return true; } + virtual bool want_write() { return false; } + virtual int fd() const { return fd_; } + virtual bool finish() { return false; } + virtual EventHandler *next() { + if (cfd_ != -1) { int val = 1; int fd = cfd_; cfd_ = -1; - if(make_non_block(fd) == -1 || - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) - == -1) { + if (make_non_block(fd) == -1 || + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, + (socklen_t)sizeof(val)) == -1) { close(fd); return 0; } @@ -507,20 +426,20 @@ public: return 0; } } + private: int fd_; int cfd_; }; -int ctl_epollev(int epollfd, int op, EventHandler *handler) -{ +int ctl_epollev(int epollfd, int op, EventHandler *handler) { epoll_event ev; memset(&ev, 0, sizeof(ev)); int events = 0; - if(handler->want_read()) { + if (handler->want_read()) { events |= EPOLLIN; } - if(handler->want_write()) { + if (handler->want_write()) { events |= EPOLLOUT; } ev.events = events; @@ -528,42 +447,41 @@ int ctl_epollev(int epollfd, int op, EventHandler *handler) return epoll_ctl(epollfd, op, handler->fd(), &ev); } -void reactor(int sfd) -{ - std::set handlers; - ListenEventHandler* listen_handler = new ListenEventHandler(sfd); +void reactor(int sfd) { + std::set handlers; + ListenEventHandler *listen_handler = new ListenEventHandler(sfd); handlers.insert(listen_handler); int epollfd = epoll_create(16); - if(epollfd == -1) { + if (epollfd == -1) { perror("epoll_create"); exit(EXIT_FAILURE); } - if(ctl_epollev(epollfd, EPOLL_CTL_ADD, listen_handler) == -1) { + if (ctl_epollev(epollfd, EPOLL_CTL_ADD, listen_handler) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } static const size_t MAX_EVENTS = 64; epoll_event events[MAX_EVENTS]; - while(1) { + while (1) { int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); - if(nfds == -1) { + if (nfds == -1) { perror("epoll_wait"); return; } - for(int n = 0; n < nfds; ++n) { - EventHandler* eh = (EventHandler*)events[n].data.ptr; - if(((events[n].events & EPOLLIN) && eh->on_read_event() == -1) || - ((events[n].events & EPOLLOUT) && eh->on_write_event() == -1) || - (events[n].events & (EPOLLERR | EPOLLHUP))) { + for (int n = 0; n < nfds; ++n) { + EventHandler *eh = (EventHandler *)events[n].data.ptr; + if (((events[n].events & EPOLLIN) && eh->on_read_event() == -1) || + ((events[n].events & EPOLLOUT) && eh->on_write_event() == -1) || + (events[n].events & (EPOLLERR | EPOLLHUP))) { handlers.erase(eh); delete eh; } else { - EventHandler* next = eh->next(); - if(next) { + EventHandler *next = eh->next(); + if (next) { handlers.insert(next); - if(ctl_epollev(epollfd, EPOLL_CTL_ADD, next) == -1) { - if(errno == EEXIST) { - if(ctl_epollev(epollfd, EPOLL_CTL_MOD, next) == -1) { + if (ctl_epollev(epollfd, EPOLL_CTL_ADD, next) == -1) { + if (errno == EEXIST) { + if (ctl_epollev(epollfd, EPOLL_CTL_MOD, next) == -1) { perror("epoll_ctl"); delete next; } @@ -573,11 +491,11 @@ void reactor(int sfd) } } } - if(eh->finish()) { + if (eh->finish()) { handlers.erase(eh); delete eh; } else { - if(ctl_epollev(epollfd, EPOLL_CTL_MOD, eh) == -1) { + if (ctl_epollev(epollfd, EPOLL_CTL_MOD, eh) == -1) { perror("epoll_ctl"); } } @@ -586,9 +504,8 @@ void reactor(int sfd) } } -int main(int argc, char **argv) -{ - if(argc < 2) { +int main(int argc, char **argv) { + if (argc < 2) { std::cerr << "Usage: " << argv[0] << " PORT" << std::endl; exit(EXIT_FAILURE); } @@ -597,7 +514,7 @@ int main(int argc, char **argv) act.sa_handler = SIG_IGN; sigaction(SIGPIPE, &act, 0); int sfd = create_listen_socket(argv[1]); - if(sfd == -1) { + if (sfd == -1) { std::cerr << "Failed to create server socket" << std::endl; exit(EXIT_FAILURE); } diff --git a/deps/wslay/examples/fork-echoserv.c b/deps/wslay/examples/fork-echoserv.c index 0ef5da6d..3f2b2a00 100644 --- a/deps/wslay/examples/fork-echoserv.c +++ b/deps/wslay/examples/fork-echoserv.c @@ -60,8 +60,7 @@ * Create server socket, listen on *service*. This function returns * file descriptor of server socket if it succeeds, or returns -1. */ -int create_listen_socket(const char *service) -{ +static int create_listen_socket(const char *service) { struct addrinfo hints, *res, *rp; int sfd = -1; int r; @@ -70,27 +69,27 @@ int create_listen_socket(const char *service) hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; r = getaddrinfo(0, service, &hints, &res); - if(r != 0) { + if (r != 0) { fprintf(stderr, "getaddrinfo: %s", gai_strerror(r)); return -1; } - for(rp = res; rp; rp = rp->ai_next) { + for (rp = res; rp; rp = rp->ai_next) { int val = 1; sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if(sfd == -1) { + if (sfd == -1) { continue; } - if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, - (socklen_t)sizeof(val)) == -1) { + if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &val, + (socklen_t)sizeof(val)) == -1) { continue; } - if(bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { + if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0) { break; } close(sfd); } freeaddrinfo(res); - if(listen(sfd, 16) == -1) { + if (listen(sfd, 16) == -1) { perror("listen"); close(sfd); return -1; @@ -102,16 +101,17 @@ int create_listen_socket(const char *service) * Makes file descriptor *fd* non-blocking mode. * This function returns 0, or returns -1. */ -int make_non_block(int fd) -{ +static int make_non_block(int fd) { int flags, r; - while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); - if(flags == -1) { + while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR) + ; + if (flags == -1) { perror("fcntl"); return -1; } - while((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); - if(r == -1) { + while ((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR) + ; + if (r == -1) { perror("fcntl"); return -1; } @@ -122,8 +122,7 @@ int make_non_block(int fd) * Calculates SHA-1 hash of *src*. The size of *src* is *src_length* bytes. * *dst* must be at least SHA1_DIGEST_SIZE. */ -void sha1(uint8_t *dst, const uint8_t *src, size_t src_length) -{ +static void sha1(uint8_t *dst, const uint8_t *src, size_t src_length) { struct sha1_ctx ctx; sha1_init(&ctx); sha1_update(&ctx, src_length, src); @@ -135,11 +134,10 @@ void sha1(uint8_t *dst, const uint8_t *src, size_t src_length) * The size of *src* is *src_length*. * *dst* must be at least BASE64_ENCODE_RAW_LENGTH(src_length). */ -void base64(uint8_t *dst, const uint8_t *src, size_t src_length) -{ +static void base64(uint8_t *dst, const uint8_t *src, size_t src_length) { struct base64_encode_ctx ctx; base64_encode_init(&ctx); - base64_encode_raw(dst, src_length, src); + base64_encode_raw((char *)dst, src_length, src); } #define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" @@ -150,13 +148,12 @@ void base64(uint8_t *dst, const uint8_t *src, size_t src_length) * client's handshake and it must be length of 24. * *dst* must be at least BASE64_ENCODE_RAW_LENGTH(20)+1. */ -void create_accept_key(char *dst, const char *client_key) -{ +static void create_accept_key(char *dst, const char *client_key) { uint8_t sha1buf[20], key_src[60]; memcpy(key_src, client_key, 24); - memcpy(key_src+24, WS_GUID, 36); + memcpy(key_src + 24, WS_GUID, 36); sha1(sha1buf, key_src, sizeof(key_src)); - base64((uint8_t*)dst, sha1buf, 20); + base64((uint8_t *)dst, sha1buf, 20); dst[BASE64_ENCODE_RAW_LENGTH(20)] = '\0'; } @@ -166,69 +163,59 @@ void create_accept_key(char *dst, const char *client_key) * If the caller is looking for a specific value, we return a pointer to the * start of that value, else we simply return the start of values list. */ -static char* -http_header_find_field_value(char *header, char *field_name, char *value) -{ - char *header_end, - *field_start, - *field_end, - *next_crlf, - *value_start; +static const char *http_header_find_field_value(const char *header, + const char *field_name, + const char *value) { + const char *header_end, *field_start, *field_end, *next_crlf, *value_start; int field_name_len; /* Pointer to the last character in the header */ header_end = header + strlen(header) - 1; - field_name_len = strlen(field_name); + field_name_len = (int)strlen(field_name); field_start = header; - do{ - field_start = strstr(field_start+1, field_name); + do { + field_start = strstr(field_start + 1, field_name); field_end = field_start + field_name_len - 1; - if(field_start != NULL - && field_start - header >= 2 - && field_start[-2] == '\r' - && field_start[-1] == '\n' - && header_end - field_end >= 1 - && field_end[1] == ':') - { + if (field_start != NULL && field_start - header >= 2 && + field_start[-2] == '\r' && field_start[-1] == '\n' && + header_end - field_end >= 1 && field_end[1] == ':') { break; /* Found the field */ - } - else - { + } else { continue; /* This is not the one; keep looking. */ } - } while(field_start != NULL); + } while (field_start != NULL); - if(field_start == NULL) + if (field_start == NULL) return NULL; /* Find the field terminator */ next_crlf = strstr(field_start, "\r\n"); /* A field is expected to end with \r\n */ - if(next_crlf == NULL) + if (next_crlf == NULL) return NULL; /* Malformed HTTP header! */ /* If not looking for a value, then return a pointer to the start of values string */ - if(value == NULL) - return field_end+2; + if (value == NULL) + return field_end + 2; value_start = strstr(field_start, value); /* Value not found */ - if(value_start == NULL) + if (value_start == NULL) return NULL; /* Found the value we're looking for */ - if(value_start > next_crlf) + if (value_start > next_crlf) return NULL; /* ... but after the CRLF terminator of the field. */ /* The value we found should be properly delineated from the other tokens */ - if(isalnum(value_start[-1]) || isalnum(value_start[strlen(value)])) + if (isalnum(value_start[-1]) || isalnum(value_start[strlen(value)])) return NULL; return value_start; @@ -239,48 +226,53 @@ http_header_find_field_value(char *header, char *field_name, char *value) * connection to the client. This function returns 0 if it succeeds, * or returns -1. */ -int http_handshake(int fd) -{ +static int http_handshake(int fd) { /* * Note: The implementation of HTTP handshake in this function is * written for just a example of how to use of wslay library and is * not meant to be used in production code. In practice, you need * to do more strict verification of the client's handshake. */ - char header[16384], accept_key[29], *keyhdstart, *keyhdend, res_header[256]; + char header[16384], accept_key[29], res_header[256]; + const char *keyhdstart, *keyhdend; size_t header_length = 0, res_header_sent = 0, res_header_length; ssize_t r; - while(1) { - while((r = read(fd, header+header_length, - sizeof(header)-header_length)) == -1 && errno == EINTR); - if(r == -1) { + while (1) { + while ((r = read(fd, header + header_length, + sizeof(header) - header_length)) == -1 && + errno == EINTR) + ; + if (r == -1) { perror("read"); return -1; - } else if(r == 0) { + } else if (r == 0) { fprintf(stderr, "HTTP Handshake: Got EOF"); return -1; } else { - header_length += r; - if(header_length >= 4 && - memcmp(header+header_length-4, "\r\n\r\n", 4) == 0) { + header_length += (size_t)r; + if (header_length >= 4 && + memcmp(header + header_length - 4, "\r\n\r\n", 4) == 0) { break; - } else if(header_length == sizeof(header)) { + } else if (header_length == sizeof(header)) { fprintf(stderr, "HTTP Handshake: Too large HTTP headers"); return -1; } } } - if(http_header_find_field_value(header, "Upgrade", "websocket") == NULL || - http_header_find_field_value(header, "Connection", "Upgrade") == NULL || - (keyhdstart = http_header_find_field_value(header, "Sec-WebSocket-Key", NULL)) == NULL) { + if (http_header_find_field_value(header, "Upgrade", "websocket") == NULL || + http_header_find_field_value(header, "Connection", "Upgrade") == NULL || + (keyhdstart = http_header_find_field_value(header, "Sec-WebSocket-Key", + NULL)) == NULL) { fprintf(stderr, "HTTP Handshake: Missing required header fields"); return -1; } - for(; *keyhdstart == ' '; ++keyhdstart); + for (; *keyhdstart == ' '; ++keyhdstart) + ; keyhdend = keyhdstart; - for(; *keyhdend != '\r' && *keyhdend != ' '; ++keyhdend); - if(keyhdend-keyhdstart != 24) { + for (; *keyhdend != '\r' && *keyhdend != ' '; ++keyhdend) + ; + if (keyhdend - keyhdstart != 24) { printf("%s\n", keyhdstart); fprintf(stderr, "HTTP Handshake: Invalid value in Sec-WebSocket-Key"); return -1; @@ -291,17 +283,19 @@ int http_handshake(int fd) "Upgrade: websocket\r\n" "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: %s\r\n" - "\r\n", accept_key); + "\r\n", + accept_key); res_header_length = strlen(res_header); - while(res_header_sent < res_header_length) { - while((r = write(fd, res_header+res_header_sent, - res_header_length-res_header_sent)) == -1 && - errno == EINTR); - if(r == -1) { + while (res_header_sent < res_header_length) { + while ((r = write(fd, res_header + res_header_sent, + res_header_length - res_header_sent)) == -1 && + errno == EINTR) + ; + if (r == -1) { perror("write"); return -1; } else { - res_header_sent += r; + res_header_sent += (size_t)r; } } return 0; @@ -315,21 +309,20 @@ struct Session { int fd; }; -ssize_t send_callback(wslay_event_context_ptr ctx, - const uint8_t *data, size_t len, int flags, - void *user_data) -{ - struct Session *session = (struct Session*)user_data; +static ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, + size_t len, int flags, void *user_data) { + struct Session *session = (struct Session *)user_data; ssize_t r; int sflags = 0; #ifdef MSG_MORE - if(flags & WSLAY_MSG_MORE) { + if (flags & WSLAY_MSG_MORE) { sflags |= MSG_MORE; } #endif // MSG_MORE - while((r = send(session->fd, data, len, sflags)) == -1 && errno == EINTR); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + while ((r = send(session->fd, data, len, sflags)) == -1 && errno == EINTR) + ; + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); @@ -338,19 +331,20 @@ ssize_t send_callback(wslay_event_context_ptr ctx, return r; } -ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, - int flags, void *user_data) -{ - struct Session *session = (struct Session*)user_data; +static ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, + size_t len, int flags, void *user_data) { + struct Session *session = (struct Session *)user_data; ssize_t r; - while((r = recv(session->fd, buf, len, 0)) == -1 && errno == EINTR); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + (void)flags; + while ((r = recv(session->fd, buf, len, 0)) == -1 && errno == EINTR) + ; + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); } - } else if(r == 0) { + } else if (r == 0) { /* Unexpected EOF is also treated as an error */ wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); r = -1; @@ -358,15 +352,13 @@ ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, return r; } -void on_msg_recv_callback(wslay_event_context_ptr ctx, - const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ +static void on_msg_recv_callback(wslay_event_context_ptr ctx, + const struct wslay_event_on_msg_recv_arg *arg, + void *user_data) { + (void)user_data; /* Echo back non-control message */ - if(!wslay_is_ctrl_frame(arg->opcode)) { - struct wslay_event_msg msgarg = { - arg->opcode, arg->msg, arg->msg_length - }; + if (!wslay_is_ctrl_frame(arg->opcode)) { + struct wslay_event_msg msgarg = {arg->opcode, arg->msg, arg->msg_length}; wslay_event_queue_msg(ctx, &msgarg); } } @@ -377,31 +369,24 @@ void on_msg_recv_callback(wslay_event_context_ptr ctx, * error occurs. *fd* is the file descriptor of the connection to the * client. This function returns 0 if it succeeds, or returns 0. */ -int communicate(int fd) -{ +static int communicate(int fd) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks = { - recv_callback, - send_callback, - NULL, - NULL, - NULL, - NULL, - on_msg_recv_callback - }; - struct Session session = { fd }; + recv_callback, send_callback, NULL, NULL, NULL, + NULL, on_msg_recv_callback}; + struct Session session = {fd}; int val = 1; struct pollfd event; int res = 0; - if(http_handshake(fd) == -1) { + if (http_handshake(fd) == -1) { return -1; } - if(make_non_block(fd) == -1) { + if (make_non_block(fd) == -1) { return -1; } - if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) - == -1) { + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) == + -1) { perror("setsockopt: TCP_NODELAY"); return -1; } @@ -413,17 +398,18 @@ int communicate(int fd) * Event loop: basically loop until both wslay_event_want_read(ctx) * and wslay_event_want_write(ctx) return 0. */ - while(wslay_event_want_read(ctx) || wslay_event_want_write(ctx)) { + while (wslay_event_want_read(ctx) || wslay_event_want_write(ctx)) { int r; - while((r = poll(&event, 1, -1)) == -1 && errno == EINTR); - if(r == -1) { + while ((r = poll(&event, 1, -1)) == -1 && errno == EINTR) + ; + if (r == -1) { perror("poll"); res = -1; break; } - if(((event.revents & POLLIN) && wslay_event_recv(ctx) != 0) || - ((event.revents & POLLOUT) && wslay_event_send(ctx) != 0) || - (event.revents & (POLLERR | POLLHUP | POLLNVAL))) { + if (((event.revents & POLLIN) && wslay_event_recv(ctx) != 0) || + ((event.revents & POLLOUT) && wslay_event_send(ctx) != 0) || + (event.revents & (POLLERR | POLLHUP | POLLNVAL))) { /* * If either wslay_event_recv() or wslay_event_send() return * non-zero value, it means serious error which prevents wslay @@ -434,10 +420,10 @@ int communicate(int fd) break; } event.events = 0; - if(wslay_event_want_read(ctx)) { + if (wslay_event_want_read(ctx)) { event.events |= POLLIN; } - if(wslay_event_want_write(ctx)) { + if (wslay_event_want_write(ctx)) { event.events |= POLLOUT; } } @@ -451,23 +437,23 @@ int communicate(int fd) * process communicates with client. The parent process goes back to * the loop and can accept another client. */ -void serve(int sfd) -{ - while(1) { +static void __attribute__((noreturn)) serve(int sfd) { + while (1) { int fd; - while((fd = accept(sfd, NULL, NULL)) == -1 && errno == EINTR); - if(fd == -1) { + while ((fd = accept(sfd, NULL, NULL)) == -1 && errno == EINTR) + ; + if (fd == -1) { perror("accept"); } else { int r = fork(); - if(r == -1) { + if (r == -1) { perror("fork"); close(fd); - } else if(r == 0) { - int r = communicate(fd); + } else if (r == 0) { + r = communicate(fd); shutdown(fd, SHUT_WR); close(fd); - if(r == 0) { + if (r == 0) { exit(EXIT_SUCCESS); } else { exit(EXIT_FAILURE); @@ -477,11 +463,10 @@ void serve(int sfd) } } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { struct sigaction act; int sfd; - if(argc < 2) { + if (argc < 2) { fprintf(stderr, "Usage: %s PORT\n", argv[0]); exit(EXIT_FAILURE); } @@ -491,7 +476,7 @@ int main(int argc, char **argv) sigaction(SIGCHLD, &act, NULL); sfd = create_listen_socket(argv[1]); - if(sfd == -1) { + if (sfd == -1) { fprintf(stderr, "Failed to create server socket\n"); exit(EXIT_FAILURE); } diff --git a/deps/wslay/examples/testclient.cc b/deps/wslay/examples/testclient.cc index acfb4298..03ce0240 100644 --- a/deps/wslay/examples/testclient.cc +++ b/deps/wslay/examples/testclient.cc @@ -52,8 +52,7 @@ #include #include -int connect_to(const char *host, const char *service) -{ +int connect_to(const char *host, const char *service) { struct addrinfo hints; int fd = -1; int r; @@ -62,18 +61,19 @@ int connect_to(const char *host, const char *service) hints.ai_socktype = SOCK_STREAM; struct addrinfo *res; r = getaddrinfo(host, service, &hints, &res); - if(r != 0) { + if (r != 0) { std::cerr << "getaddrinfo: " << gai_strerror(r) << std::endl; return -1; } - for(struct addrinfo *rp = res; rp; rp = rp->ai_next) { + for (struct addrinfo *rp = res; rp; rp = rp->ai_next) { fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if(fd == -1) { + if (fd == -1) { continue; } - while((r = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 && - errno == EINTR); - if(r == 0) { + while ((r = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 && + errno == EINTR) + ; + if (r == 0) { break; } close(fd); @@ -83,91 +83,77 @@ int connect_to(const char *host, const char *service) return fd; } -int make_non_block(int fd) -{ +int make_non_block(int fd) { int flags, r; - while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR); - if(flags == -1) { + while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR) + ; + if (flags == -1) { return -1; } - while((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR); - if(r == -1) { + while ((r = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR) + ; + if (r == -1) { return -1; } return 0; } -std::string sha1(const std::string& src) -{ +std::string sha1(const std::string &src) { sha1_ctx ctx; sha1_init(&ctx); - sha1_update(&ctx, src.size(), reinterpret_cast(src.c_str())); + sha1_update(&ctx, src.size(), reinterpret_cast(src.c_str())); uint8_t temp[SHA1_DIGEST_SIZE]; sha1_digest(&ctx, SHA1_DIGEST_SIZE, temp); std::string res(&temp[0], &temp[SHA1_DIGEST_SIZE]); return res; } -std::string base64(const std::string& src) -{ +std::string base64(const std::string &src) { base64_encode_ctx ctx; base64_encode_init(&ctx); int dstlen = BASE64_ENCODE_RAW_LENGTH(src.size()); - uint8_t *dst = new uint8_t[dstlen]; + char *dst = new char[dstlen]; base64_encode_raw(dst, src.size(), - reinterpret_cast(src.c_str())); + reinterpret_cast(src.c_str())); std::string res(&dst[0], &dst[dstlen]); - delete [] dst; + delete[] dst; return res; } -std::string create_acceptkey(const std::string& clientkey) -{ - std::string s = clientkey+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +std::string create_acceptkey(const std::string &clientkey) { + std::string s = clientkey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; return base64(sha1(s)); } class WebSocketClient { public: WebSocketClient(int fd, struct wslay_event_callbacks *callbacks, - const std::string& body) - : fd_(fd), - body_(body), - body_off_(0), - dev_urand_("/dev/urandom") - { + const std::string &body) + : fd_(fd), body_(body), body_off_(0), dev_urand_("/dev/urandom") { wslay_event_context_client_init(&ctx_, callbacks, this); } - ~WebSocketClient() - { + ~WebSocketClient() { wslay_event_context_free(ctx_); shutdown(fd_, SHUT_WR); close(fd_); } - int on_read_event() - { - return wslay_event_recv(ctx_); - } - int on_write_event() - { - return wslay_event_send(ctx_); - } - ssize_t send_data(const uint8_t *data, size_t len, int flags) - { + int on_read_event() { return wslay_event_recv(ctx_); } + int on_write_event() { return wslay_event_send(ctx_); } + ssize_t send_data(const uint8_t *data, size_t len, int flags) { ssize_t r; int sflags = 0; #ifdef MSG_MORE - if(flags & WSLAY_MSG_MORE) { + if (flags & WSLAY_MSG_MORE) { sflags |= MSG_MORE; } #endif // MSG_MORE - while((r = send(fd_, data, len, sflags)) == -1 && errno == EINTR); + while ((r = send(fd_, data, len, sflags)) == -1 && errno == EINTR) + ; return r; } - ssize_t feed_body(uint8_t *data, size_t len) - { - if(body_off_ < body_.size()) { - size_t wlen = std::min(len, body_.size()-body_off_); + ssize_t feed_body(uint8_t *data, size_t len) { + if (body_off_ < body_.size()) { + size_t wlen = std::min(len, body_.size() - body_off_); memcpy(data, body_.c_str(), wlen); body_off_ += wlen; return wlen; @@ -175,32 +161,22 @@ public: return 0; } } - ssize_t recv_data(uint8_t *data, size_t len, int flags) - { + ssize_t recv_data(uint8_t *data, size_t len, int flags) { ssize_t r; - while((r = recv(fd_, data, len, 0)) == -1 && errno == EINTR); + while ((r = recv(fd_, data, len, 0)) == -1 && errno == EINTR) + ; return r; } - bool want_read() - { - return wslay_event_want_read(ctx_); + bool want_read() { return wslay_event_want_read(ctx_); } + bool want_write() { return wslay_event_want_write(ctx_); } + int fd() const { return fd_; } + void get_random(uint8_t *buf, size_t len) { + dev_urand_.read((char *)buf, len); } - bool want_write() - { - return wslay_event_want_write(ctx_); - } - int fd() const - { - return fd_; - } - void get_random(uint8_t *buf, size_t len) - { - dev_urand_.read((char*)buf, len); - } - void set_callbacks(const struct wslay_event_callbacks *callbacks) - { + void set_callbacks(const struct wslay_event_callbacks *callbacks) { wslay_event_config_set_callbacks(ctx_, callbacks); } + private: int fd_; wslay_event_context_ptr ctx_; @@ -209,14 +185,12 @@ private: std::fstream dev_urand_; }; -ssize_t send_callback(wslay_event_context_ptr ctx, - const uint8_t *data, size_t len, int flags, - void *user_data) -{ - WebSocketClient *ws = (WebSocketClient*)user_data; +ssize_t send_callback(wslay_event_context_ptr ctx, const uint8_t *data, + size_t len, int flags, void *user_data) { + WebSocketClient *ws = (WebSocketClient *)user_data; ssize_t r = ws->send_data(data, len, flags); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); @@ -226,71 +200,63 @@ ssize_t send_callback(wslay_event_context_ptr ctx, } ssize_t recv_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, - int flags, void *user_data) -{ - WebSocketClient *ws = (WebSocketClient*)user_data; + int flags, void *user_data) { + WebSocketClient *ws = (WebSocketClient *)user_data; ssize_t r = ws->recv_data(data, len, flags); - if(r == -1) { - if(errno == EAGAIN || errno == EWOULDBLOCK) { + if (r == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { wslay_event_set_error(ctx, WSLAY_ERR_WOULDBLOCK); } else { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); } - } else if(r == 0) { + } else if (r == 0) { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); r = -1; } return r; } -ssize_t feed_body_callback -(wslay_event_context_ptr ctx, uint8_t *data, size_t len, int flags, - void *user_data) -{ - WebSocketClient *ws = (WebSocketClient*)user_data; +ssize_t feed_body_callback(wslay_event_context_ptr ctx, uint8_t *data, + size_t len, int flags, void *user_data) { + WebSocketClient *ws = (WebSocketClient *)user_data; return ws->feed_body(data, len); } int genmask_callback(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, - void *user_data) -{ - WebSocketClient *ws = (WebSocketClient*)user_data; + void *user_data) { + WebSocketClient *ws = (WebSocketClient *)user_data; ws->get_random(buf, len); return 0; } void on_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ - if(!wslay_is_ctrl_frame(arg->opcode)) { - struct wslay_event_msg msgarg = { - arg->opcode, arg->msg, arg->msg_length - }; + void *user_data) { + if (!wslay_is_ctrl_frame(arg->opcode)) { + struct wslay_event_msg msgarg = {arg->opcode, arg->msg, arg->msg_length}; wslay_event_queue_msg(ctx, &msgarg); } } std::string casecntjson; -void get_casecnt_on_msg_recv_callback -(wslay_event_context_ptr ctx, - const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ - if(arg->opcode == WSLAY_TEXT_FRAME) { - casecntjson.assign(arg->msg, arg->msg+arg->msg_length); +void get_casecnt_on_msg_recv_callback( + wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, + void *user_data) { + if (arg->opcode == WSLAY_TEXT_FRAME) { + casecntjson.assign(arg->msg, arg->msg + arg->msg_length); } } -int send_http_handshake(int fd, const std::string& reqheader) -{ +int send_http_handshake(int fd, const std::string &reqheader) { size_t off = 0; - while(off < reqheader.size()) { + while (off < reqheader.size()) { ssize_t r; - size_t len = reqheader.size()-off; - while((r = write(fd, reqheader.c_str()+off, len)) == -1 && errno == EINTR); - if(r == -1) { + size_t len = reqheader.size() - off; + while ((r = write(fd, reqheader.c_str() + off, len)) == -1 && + errno == EINTR) + ; + if (r == -1) { perror("write"); return -1; } @@ -299,20 +265,20 @@ int send_http_handshake(int fd, const std::string& reqheader) return 0; } -int recv_http_handshake(int fd, std::string& resheader) -{ +int recv_http_handshake(int fd, std::string &resheader) { char buf[4096]; - while(1) { + while (1) { ssize_t r; - while((r = read(fd, buf, sizeof(buf))) == -1 && errno == EINTR); - if(r <= 0) { + while ((r = read(fd, buf, sizeof(buf))) == -1 && errno == EINTR) + ; + if (r <= 0) { return -1; } - resheader.append(buf, buf+r); - if(resheader.find("\r\n\r\n") != std::string::npos) { + resheader.append(buf, buf + r); + if (resheader.find("\r\n\r\n") != std::string::npos) { break; } - if(resheader.size() > 8192) { + if (resheader.size() > 8192) { std::cerr << "Too big response header" << std::endl; return -1; } @@ -320,17 +286,15 @@ int recv_http_handshake(int fd, std::string& resheader) return 0; } -std::string get_random16() -{ +std::string get_random16() { char buf[16]; std::fstream f("/dev/urandom"); f.read(buf, 16); - return std::string(buf, buf+16); + return std::string(buf, buf + 16); } int http_handshake(int fd, const char *host, const char *service, - const char *path, std::string& body) -{ + const char *path, std::string &body) { char buf[4096]; std::string client_key = base64(get_random16()); snprintf(buf, sizeof(buf), @@ -343,77 +307,75 @@ int http_handshake(int fd, const char *host, const char *service, "\r\n", path, host, service, client_key.c_str()); std::string reqheader = buf; - if(send_http_handshake(fd, reqheader) == -1) { + if (send_http_handshake(fd, reqheader) == -1) { return -1; } std::string resheader; - if(recv_http_handshake(fd, resheader) == -1) { + if (recv_http_handshake(fd, resheader) == -1) { return -1; } std::string::size_type keyhdstart; - if((keyhdstart = resheader.find("Sec-WebSocket-Accept: ")) == - std::string::npos) { + if ((keyhdstart = resheader.find("Sec-WebSocket-Accept: ")) == + std::string::npos) { std::cerr << "http_upgrade: missing required headers" << std::endl; return -1; } keyhdstart += 22; std::string::size_type keyhdend = resheader.find("\r\n", keyhdstart); - std::string accept_key = resheader.substr(keyhdstart, keyhdend-keyhdstart); - if(accept_key == create_acceptkey(client_key)) { - body = resheader.substr(resheader.find("\r\n\r\n")+4); + std::string accept_key = resheader.substr(keyhdstart, keyhdend - keyhdstart); + if (accept_key == create_acceptkey(client_key)) { + body = resheader.substr(resheader.find("\r\n\r\n") + 4); return 0; } else { return -1; } } -void ctl_epollev(int epollfd, int op, WebSocketClient& ws) -{ +void ctl_epollev(int epollfd, int op, WebSocketClient &ws) { epoll_event ev; memset(&ev, 0, sizeof(ev)); - if(ws.want_read()) { + if (ws.want_read()) { ev.events |= EPOLLIN; } - if(ws.want_write()) { + if (ws.want_write()) { ev.events |= EPOLLOUT; } - if(epoll_ctl(epollfd, op, ws.fd(), &ev) == -1) { + if (epoll_ctl(epollfd, op, ws.fd(), &ev) == -1) { perror("epoll_ctl"); exit(EXIT_FAILURE); } } int communicate(const char *host, const char *service, const char *path, - const struct wslay_event_callbacks *callbacks) -{ + const struct wslay_event_callbacks *callbacks) { struct wslay_event_callbacks cb = *callbacks; cb.recv_callback = feed_body_callback; int fd = connect_to(host, service); - if(fd == -1) { + if (fd == -1) { std::cerr << "Could not connect to the host" << std::endl; return -1; } std::string body; - if(http_handshake(fd, host, service, path, body) == -1) { + if (http_handshake(fd, host, service, path, body) == -1) { std::cerr << "Failed handshake" << std::endl; close(fd); return -1; } make_non_block(fd); int val = 1; - if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) - == -1) { + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val)) == + -1) { perror("setsockopt: TCP_NODELAY"); return -1; } WebSocketClient ws(fd, &cb, body); - if(ws.on_read_event() == -1) { + if (ws.on_read_event() == -1) { return -1; } cb.recv_callback = callbacks->recv_callback; ws.set_callbacks(&cb); int epollfd = epoll_create(1); - if(epollfd == -1) { + if (epollfd == -1) { perror("epoll_create"); return -1; } @@ -421,20 +383,20 @@ int communicate(const char *host, const char *service, const char *path, static const size_t MAX_EVENTS = 1; epoll_event events[MAX_EVENTS]; bool ok = true; - while(ws.want_read() || ws.want_write()) { + while (ws.want_read() || ws.want_write()) { int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); - if(nfds == -1) { + if (nfds == -1) { perror("epoll_wait"); return -1; } - for(int n = 0; n < nfds; ++n) { - if(((events[n].events & EPOLLIN) && ws.on_read_event() != 0) || - ((events[n].events & EPOLLOUT) && ws.on_write_event() != 0)) { + for (int n = 0; n < nfds; ++n) { + if (((events[n].events & EPOLLIN) && ws.on_read_event() != 0) || + ((events[n].events & EPOLLOUT) && ws.on_write_event() != 0)) { ok = false; break; } } - if(!ok) { + if (!ok) { break; } ctl_epollev(epollfd, EPOLL_CTL_MOD, ws); @@ -442,61 +404,53 @@ int communicate(const char *host, const char *service, const char *path, return ok ? 0 : -1; } -int get_casecnt(const char *host, const char *service) -{ +int get_casecnt(const char *host, const char *service) { struct wslay_event_callbacks callbacks = { - recv_callback, - send_callback, - genmask_callback, - NULL, /* on_frame_recv_start_callback */ - NULL, /* on_frame_recv_callback */ - NULL, /* on_frame_recv_end_callback */ - get_casecnt_on_msg_recv_callback - }; - if(communicate(host, service, "/getCaseCount", &callbacks) == -1) { + recv_callback, + send_callback, + genmask_callback, + NULL, /* on_frame_recv_start_callback */ + NULL, /* on_frame_recv_callback */ + NULL, /* on_frame_recv_end_callback */ + get_casecnt_on_msg_recv_callback}; + if (communicate(host, service, "/getCaseCount", &callbacks) == -1) { return -1; } errno = 0; int casecnt = strtol(casecntjson.c_str(), 0, 10); - if(errno == ERANGE) { + if (errno == ERANGE) { return -1; } else { return casecnt; } } -int run_testcase(const char *host, const char *service, int casenum) -{ +int run_testcase(const char *host, const char *service, int casenum) { struct wslay_event_callbacks callbacks = { - recv_callback, - send_callback, - genmask_callback, - NULL, /* on_frame_recv_start_callback */ - NULL, /* on_frame_recv_callback */ - NULL, /* on_frame_recv_end_callback */ - on_msg_recv_callback - }; + recv_callback, + send_callback, + genmask_callback, + NULL, /* on_frame_recv_start_callback */ + NULL, /* on_frame_recv_callback */ + NULL, /* on_frame_recv_end_callback */ + on_msg_recv_callback}; char buf[1024]; snprintf(buf, sizeof(buf), "/runCase?case=%d&agent=wslay", casenum); return communicate(host, service, buf, &callbacks); } -int update_reports(const char *host, const char *service) -{ +int update_reports(const char *host, const char *service) { struct wslay_event_callbacks callbacks = { - recv_callback, - send_callback, - genmask_callback, - NULL, /* on_frame_recv_start_callback */ - NULL, /* on_frame_recv_callback */ - NULL, /* on_frame_recv_end_callback */ - NULL, /* on_msg_recv_callback */ + recv_callback, send_callback, genmask_callback, + NULL, /* on_frame_recv_start_callback */ + NULL, /* on_frame_recv_callback */ + NULL, /* on_frame_recv_end_callback */ + NULL, /* on_msg_recv_callback */ }; return communicate(host, service, "/updateReports?&agent=wslay", &callbacks); } -int main(int argc, char **argv) -{ - if(argc < 3) { +int main(int argc, char **argv) { + if (argc < 3) { std::cerr << "Usage: " << argv[0] << " HOST SERV" << std::endl; exit(EXIT_FAILURE); } @@ -507,17 +461,17 @@ int main(int argc, char **argv) const char *host = argv[1]; const char *service = argv[2]; int casecnt = get_casecnt(host, service); - if(casecnt == -1) { + if (casecnt == -1) { std::cerr << "Failed to get case count." << std::endl; exit(EXIT_FAILURE); } - for(int i = 1; i <= casecnt; ++i) { + for (int i = 1; i <= casecnt; ++i) { std::cout << "Running test case " << i << std::endl; - if(run_testcase(host, service, i) == -1) { + if (run_testcase(host, service, i) == -1) { std::cout << "Detected error during test" << std::endl; } } - if(update_reports(host, service) == -1) { + if (update_reports(host, service) == -1) { std::cerr << "Failed to update reports." << std::endl; exit(EXIT_FAILURE); } diff --git a/deps/wslay/lib/Makefile.am b/deps/wslay/lib/Makefile.am index 2155ac56..8cf441b0 100644 --- a/deps/wslay/lib/Makefile.am +++ b/deps/wslay/lib/Makefile.am @@ -33,7 +33,7 @@ OBJECTS = wslay_frame.c wslay_event.c\ wslay_queue.c wslay_net.c HFILES = wslay_frame.h wslay_event.h\ - wslay_queue.h wslay_net.h + wslay_queue.h wslay_net.h wslay_macro.h libwslay_la_SOURCES = $(HFILES) $(OBJECTS) libwslay_la_LDFLAGS = -no-undefined \ diff --git a/deps/wslay/lib/includes/wslay/wslay.h b/deps/wslay/lib/includes/wslay/wslay.h index 2fde81a4..77a4e825 100644 --- a/deps/wslay/lib/includes/wslay/wslay.h +++ b/deps/wslay/lib/includes/wslay/wslay.h @@ -25,7 +25,7 @@ #ifndef WSLAY_H #define WSLAY_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -33,7 +33,6 @@ extern "C" { #include #include - /* * wslay/wslayver.h is generated from wslay/wslayver.h.in by * configure. The projects which do not use autotools can set @@ -149,10 +148,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) @@ -166,7 +165,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; @@ -222,6 +221,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 @@ -270,9 +296,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. */ @@ -290,9 +316,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 */ @@ -305,16 +331,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 @@ -388,9 +414,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 @@ -403,9 +429,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. @@ -456,8 +482,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 @@ -532,6 +558,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; @@ -588,10 +658,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 */ @@ -625,15 +694,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 @@ -663,8 +733,7 @@ int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, * WSLAY_ERR_NOMEM * Out of memory. */ -int wslay_event_queue_close(wslay_event_context_ptr ctx, - uint16_t status_code, +int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, const uint8_t *reason, size_t reason_length); /* diff --git a/deps/wslay/lib/wslay_event.c b/deps/wslay/lib/wslay_event.c index 57415c51..4c29fe40 100644 --- a/deps/wslay/lib/wslay_event.c +++ b/deps/wslay/lib/wslay_event.c @@ -28,9 +28,9 @@ #include #include -#include "wslay_queue.h" #include "wslay_frame.h" #include "wslay_net.h" +#include "wslay_macro.h" /* Start of utf8 dfa */ /* Copyright (c) 2008-2010 Bjoern Hoehrmann * See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. @@ -60,6 +60,7 @@ #define UTF8_ACCEPT 0 #define UTF8_REJECT 12 +/* clang-format off */ static const uint8_t utf8d[] = { /* * The first part of the table maps bytes to character classes that @@ -84,14 +85,13 @@ static const uint8_t utf8d[] = { 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,12,12,12,12,12, }; +/* clang-format on */ -static uint32_t -decode(uint32_t* state, uint32_t* codep, uint32_t byte) { +static uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte) { uint32_t type = utf8d[byte]; - *codep = (*state != UTF8_ACCEPT) ? - (byte & 0x3fu) | (*codep << 6) : - (0xff >> type) & (byte); + *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) + : (0xff >> type) & (byte); *state = utf8d[256 + *state + type]; return *state; @@ -100,117 +100,96 @@ decode(uint32_t* state, uint32_t* codep, uint32_t byte) { /* End of utf8 dfa */ static ssize_t wslay_event_frame_recv_callback(uint8_t *buf, size_t len, - int flags, void *user_data) -{ + int flags, void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.recv_callback(e->ctx, buf, len, flags, e->user_data); } static ssize_t wslay_event_frame_send_callback(const uint8_t *data, size_t len, - int flags, void *user_data) -{ + int flags, void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.send_callback(e->ctx, data, len, flags, e->user_data); } static int wslay_event_frame_genmask_callback(uint8_t *buf, size_t len, - void *user_data) -{ + void *user_data) { struct wslay_event_frame_user_data *e = - (struct wslay_event_frame_user_data*)user_data; + (struct wslay_event_frame_user_data *)user_data; return e->ctx->callbacks.genmask_callback(e->ctx, buf, len, e->user_data); } -static int wslay_event_byte_chunk_init -(struct wslay_event_byte_chunk **chunk, size_t len) -{ - *chunk = (struct wslay_event_byte_chunk*)malloc - (sizeof(struct wslay_event_byte_chunk)); - if(*chunk == NULL) { +static int wslay_event_byte_chunk_init(struct wslay_event_byte_chunk **chunk, + size_t len) { + *chunk = malloc(sizeof(struct wslay_event_byte_chunk) + len); + if (*chunk == NULL) { return WSLAY_ERR_NOMEM; } memset(*chunk, 0, sizeof(struct wslay_event_byte_chunk)); - if(len) { - (*chunk)->data = (uint8_t*)malloc(len); - if((*chunk)->data == NULL) { - free(*chunk); - return WSLAY_ERR_NOMEM; - } + if (len) { + (*chunk)->data = (uint8_t *)(*chunk) + sizeof(**chunk); (*chunk)->data_length = len; } return 0; } -static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) -{ - if(!c) { - return; - } - free(c->data); +static void wslay_event_byte_chunk_free(struct wslay_event_byte_chunk *c) { free(c); } static void wslay_event_byte_chunk_copy(struct wslay_event_byte_chunk *c, - size_t off, - const uint8_t *data, size_t data_length) -{ - memcpy(c->data+off, data, data_length); + size_t off, const uint8_t *data, + size_t data_length) { + memcpy(c->data + off, data, data_length); } -static void wslay_event_imsg_set(struct wslay_event_imsg *m, - uint8_t fin, uint8_t rsv, uint8_t opcode) -{ +static void wslay_event_imsg_set(struct wslay_event_imsg *m, uint8_t fin, + uint8_t rsv, uint8_t opcode) { m->fin = fin; m->rsv = rsv; m->opcode = opcode; m->msg_length = 0; } -static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) -{ - if(!m->chunks) { - return; - } - while(!wslay_queue_empty(m->chunks)) { - wslay_event_byte_chunk_free(wslay_queue_top(m->chunks)); - wslay_queue_pop(m->chunks); +static void wslay_event_imsg_chunks_free(struct wslay_event_imsg *m) { + while (!wslay_queue_empty(&m->chunks)) { + struct wslay_event_byte_chunk *chunk = wslay_struct_of( + wslay_queue_top(&m->chunks), struct wslay_event_byte_chunk, qe); + wslay_queue_pop(&m->chunks); + wslay_event_byte_chunk_free(chunk); } } -static void wslay_event_imsg_reset(struct wslay_event_imsg *m) -{ +static void wslay_event_imsg_reset(struct wslay_event_imsg *m) { m->opcode = 0xffu; m->utf8state = UTF8_ACCEPT; wslay_event_imsg_chunks_free(m); } -static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, size_t len) -{ - if(len == 0) { +static int wslay_event_imsg_append_chunk(struct wslay_event_imsg *m, + size_t len) { + if (len == 0) { return 0; } else { int r; struct wslay_event_byte_chunk *chunk; - if((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { - return r; - } - if((r = wslay_queue_push(m->chunks, chunk)) != 0) { + if ((r = wslay_event_byte_chunk_init(&chunk, len)) != 0) { return r; } + wslay_queue_push(&m->chunks, &chunk->qe); m->msg_length += len; return 0; } } -static int wslay_event_omsg_non_fragmented_init -(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, - const uint8_t *msg, size_t msg_length) -{ - *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); - if(!*m) { +static int wslay_event_omsg_non_fragmented_init(struct wslay_event_omsg **m, + uint8_t opcode, uint8_t rsv, + const uint8_t *msg, + size_t msg_length) { + *m = malloc(sizeof(struct wslay_event_omsg) + msg_length); + if (!*m) { return WSLAY_ERR_NOMEM; } memset(*m, 0, sizeof(struct wslay_event_omsg)); @@ -218,28 +197,22 @@ static int wslay_event_omsg_non_fragmented_init (*m)->opcode = opcode; (*m)->rsv = rsv; (*m)->type = WSLAY_NON_FRAGMENTED; - if(msg_length) { - (*m)->data = (uint8_t*)malloc(msg_length); - if(!(*m)->data) { - free(*m); - return WSLAY_ERR_NOMEM; - } + if (msg_length) { + (*m)->data = (uint8_t *)(*m) + sizeof(**m); memcpy((*m)->data, msg, msg_length); (*m)->data_length = msg_length; } return 0; } -static int wslay_event_omsg_fragmented_init -(struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, - const union wslay_event_msg_source source, - wslay_event_fragmented_msg_callback read_callback) -{ - *m = (struct wslay_event_omsg*)malloc(sizeof(struct wslay_event_omsg)); - if(!*m) { +static int wslay_event_omsg_fragmented_init( + struct wslay_event_omsg **m, uint8_t opcode, uint8_t rsv, + const union wslay_event_msg_source source, + wslay_event_fragmented_msg_callback read_callback) { + *m = calloc(1, sizeof(struct wslay_event_omsg)); + if (!*m) { return WSLAY_ERR_NOMEM; } - memset(*m, 0, sizeof(struct wslay_event_omsg)); (*m)->opcode = opcode; (*m)->rsv = rsv; (*m)->type = WSLAY_FRAGMENTED; @@ -248,31 +221,25 @@ static int wslay_event_omsg_fragmented_init return 0; } -static void wslay_event_omsg_free(struct wslay_event_omsg *m) -{ - if(!m) { - return; - } - free(m->data); - free(m); -} +static void wslay_event_omsg_free(struct wslay_event_omsg *m) { free(m); } -static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) -{ - if(len == 0) { +static uint8_t *wslay_event_flatten_queue(struct wslay_queue *queue, + size_t len) { + if (len == 0) { return NULL; } else { size_t off = 0; - uint8_t *buf = (uint8_t*)malloc(len); - if(!buf) { + uint8_t *buf = malloc(len); + if (!buf) { return NULL; } - while(!wslay_queue_empty(queue)) { - struct wslay_event_byte_chunk *chunk = wslay_queue_top(queue); - memcpy(buf+off, chunk->data, chunk->data_length); + while (!wslay_queue_empty(queue)) { + struct wslay_event_byte_chunk *chunk = wslay_struct_of( + wslay_queue_top(queue), struct wslay_event_byte_chunk, qe); + wslay_queue_pop(queue); + memcpy(buf + off, chunk->data, chunk->data_length); off += chunk->data_length; wslay_event_byte_chunk_free(chunk); - wslay_queue_pop(queue); assert(off <= len); } assert(len == off); @@ -280,17 +247,15 @@ static uint8_t* wslay_event_flatten_queue(struct wslay_queue *queue, size_t len) } } -static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) -{ +static int wslay_event_is_msg_queueable(wslay_event_context_ptr ctx) { return ctx->write_enabled && (ctx->close_status & WSLAY_CLOSE_QUEUED) == 0; } int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, - const uint8_t *reason, size_t reason_length) -{ - if(!wslay_event_is_msg_queueable(ctx)) { + const uint8_t *reason, size_t reason_length) { + if (!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; - } else if(reason_length > 123) { + } else if (reason_length > 123) { return WSLAY_ERR_INVALID_ARGUMENT; } else { uint8_t msg[128]; @@ -298,231 +263,203 @@ int wslay_event_queue_close(wslay_event_context_ptr ctx, uint16_t status_code, struct wslay_event_msg arg; uint16_t ncode; int r; - if(status_code == 0) { + if (status_code == 0) { msg_length = 0; } else { ncode = htons(status_code); memcpy(msg, &ncode, 2); - if(reason_length) { - memcpy(msg+2, reason, reason_length); + if (reason_length) { + memcpy(msg + 2, reason, reason_length); } - msg_length = reason_length+2; + msg_length = reason_length + 2; } arg.opcode = WSLAY_CONNECTION_CLOSE; arg.msg = msg; arg.msg_length = msg_length; r = wslay_event_queue_msg(ctx, &arg); - if(r == 0) { + if (r == 0) { ctx->close_status |= WSLAY_CLOSE_QUEUED; } return r; } } -static int wslay_event_queue_close_wrapper -(wslay_event_context_ptr ctx, uint16_t status_code, - const uint8_t *reason, size_t reason_length) -{ +static int wslay_event_queue_close_wrapper(wslay_event_context_ptr ctx, + uint16_t status_code, + const uint8_t *reason, + size_t reason_length) { int r; ctx->read_enabled = 0; - if((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && - r != WSLAY_ERR_NO_MORE_MSG) { + if ((r = wslay_event_queue_close(ctx, status_code, reason, reason_length)) && + r != WSLAY_ERR_NO_MORE_MSG) { return r; } return 0; } -static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, uint8_t rsv) -{ +static int wslay_event_verify_rsv_bits(wslay_event_context_ptr ctx, + uint8_t rsv) { return ((rsv & ~ctx->allowed_rsv_bits) == 0); } int wslay_event_queue_msg(wslay_event_context_ptr ctx, - const struct wslay_event_msg *arg) -{ + const struct wslay_event_msg *arg) { return wslay_event_queue_msg_ex(ctx, arg, WSLAY_RSV_NONE); } int wslay_event_queue_msg_ex(wslay_event_context_ptr ctx, - const struct wslay_event_msg *arg, uint8_t rsv) -{ + const struct wslay_event_msg *arg, uint8_t rsv) { int r; struct wslay_event_omsg *omsg; - if(!wslay_event_is_msg_queueable(ctx)) { + if (!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; } /* RSV1 is not allowed for control frames */ - if((wslay_is_ctrl_frame(arg->opcode) && - (arg->msg_length > 125 || wslay_get_rsv1(rsv))) - || !wslay_event_verify_rsv_bits(ctx, rsv)) { + if ((wslay_is_ctrl_frame(arg->opcode) && + (arg->msg_length > 125 || wslay_get_rsv1(rsv))) || + !wslay_event_verify_rsv_bits(ctx, rsv)) { return WSLAY_ERR_INVALID_ARGUMENT; } - if((r = wslay_event_omsg_non_fragmented_init - (&omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { + if ((r = wslay_event_omsg_non_fragmented_init( + &omsg, arg->opcode, rsv, arg->msg, arg->msg_length)) != 0) { return r; } - if(wslay_is_ctrl_frame(arg->opcode)) { - if((r = wslay_queue_push(ctx->send_ctrl_queue, omsg)) != 0) { - return r; - } + if (wslay_is_ctrl_frame(arg->opcode)) { + wslay_queue_push(&ctx->send_ctrl_queue, &omsg->qe); } else { - if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { - return r; - } + wslay_queue_push(&ctx->send_queue, &omsg->qe); } ++ctx->queued_msg_count; ctx->queued_msg_length += arg->msg_length; return 0; } -int wslay_event_queue_fragmented_msg -(wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) -{ +int wslay_event_queue_fragmented_msg( + wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg) { return wslay_event_queue_fragmented_msg_ex(ctx, arg, WSLAY_RSV_NONE); } -int wslay_event_queue_fragmented_msg_ex(wslay_event_context_ptr ctx, - const struct wslay_event_fragmented_msg *arg, uint8_t rsv) -{ +int wslay_event_queue_fragmented_msg_ex( + wslay_event_context_ptr ctx, const struct wslay_event_fragmented_msg *arg, + uint8_t rsv) { int r; struct wslay_event_omsg *omsg; - if(!wslay_event_is_msg_queueable(ctx)) { + if (!wslay_event_is_msg_queueable(ctx)) { return WSLAY_ERR_NO_MORE_MSG; } - if(wslay_is_ctrl_frame(arg->opcode) || - !wslay_event_verify_rsv_bits(ctx, rsv)) { + if (wslay_is_ctrl_frame(arg->opcode) || + !wslay_event_verify_rsv_bits(ctx, rsv)) { return WSLAY_ERR_INVALID_ARGUMENT; } - if((r = wslay_event_omsg_fragmented_init - (&omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { - return r; - } - if((r = wslay_queue_push(ctx->send_queue, omsg)) != 0) { + if ((r = wslay_event_omsg_fragmented_init( + &omsg, arg->opcode, rsv, arg->source, arg->read_callback)) != 0) { return r; } + wslay_queue_push(&ctx->send_queue, &omsg->qe); ++ctx->queued_msg_count; return 0; } -void wslay_event_config_set_callbacks -(wslay_event_context_ptr ctx, const struct wslay_event_callbacks *callbacks) -{ +void wslay_event_config_set_callbacks( + wslay_event_context_ptr ctx, + const struct wslay_event_callbacks *callbacks) { ctx->callbacks = *callbacks; } -static int wslay_event_context_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +static int +wslay_event_context_init(wslay_event_context_ptr *ctx, + const struct wslay_event_callbacks *callbacks, + void *user_data) { int i, r; struct wslay_frame_callbacks frame_callbacks = { - wslay_event_frame_send_callback, - wslay_event_frame_recv_callback, - wslay_event_frame_genmask_callback - }; - *ctx = (wslay_event_context_ptr)malloc(sizeof(struct wslay_event_context)); - if(!*ctx) { + wslay_event_frame_send_callback, wslay_event_frame_recv_callback, + wslay_event_frame_genmask_callback}; + *ctx = calloc(1, sizeof(struct wslay_event_context)); + if (!*ctx) { return WSLAY_ERR_NOMEM; } - memset(*ctx, 0, sizeof(struct wslay_event_context)); wslay_event_config_set_callbacks(*ctx, callbacks); (*ctx)->user_data = user_data; (*ctx)->frame_user_data.ctx = *ctx; (*ctx)->frame_user_data.user_data = user_data; - if((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, - &(*ctx)->frame_user_data)) != 0) { + if ((r = wslay_frame_context_init(&(*ctx)->frame_ctx, &frame_callbacks, + &(*ctx)->frame_user_data)) != 0) { wslay_event_context_free(*ctx); return r; } (*ctx)->read_enabled = (*ctx)->write_enabled = 1; - (*ctx)->send_queue = wslay_queue_new(); - if(!(*ctx)->send_queue) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } - (*ctx)->send_ctrl_queue = wslay_queue_new(); - if(!(*ctx)->send_ctrl_queue) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } + wslay_queue_init(&(*ctx)->send_queue); + wslay_queue_init(&(*ctx)->send_ctrl_queue); (*ctx)->queued_msg_count = 0; (*ctx)->queued_msg_length = 0; - for(i = 0; i < 2; ++i) { + for (i = 0; i < 2; ++i) { + wslay_queue_init(&(*ctx)->imsgs[i].chunks); wslay_event_imsg_reset(&(*ctx)->imsgs[i]); - (*ctx)->imsgs[i].chunks = wslay_queue_new(); - if(!(*ctx)->imsgs[i].chunks) { - wslay_event_context_free(*ctx); - return WSLAY_ERR_NOMEM; - } } (*ctx)->imsg = &(*ctx)->imsgs[0]; (*ctx)->obufmark = (*ctx)->obuflimit = (*ctx)->obuf; (*ctx)->status_code_sent = WSLAY_CODE_ABNORMAL_CLOSURE; (*ctx)->status_code_recv = WSLAY_CODE_ABNORMAL_CLOSURE; - (*ctx)->max_recv_msg_length = (1u << 31)-1; + (*ctx)->max_recv_msg_length = (1u << 31) - 1; return 0; } -int wslay_event_context_server_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +int wslay_event_context_server_init( + wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks, + void *user_data) { int r; - if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { return r; } (*ctx)->server = 1; return 0; } -int wslay_event_context_client_init -(wslay_event_context_ptr *ctx, - const struct wslay_event_callbacks *callbacks, - void *user_data) -{ +int wslay_event_context_client_init( + wslay_event_context_ptr *ctx, const struct wslay_event_callbacks *callbacks, + void *user_data) { int r; - if((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { + if ((r = wslay_event_context_init(ctx, callbacks, user_data)) != 0) { return r; } (*ctx)->server = 0; return 0; } -void wslay_event_context_free(wslay_event_context_ptr ctx) -{ +void wslay_event_context_free(wslay_event_context_ptr ctx) { int i; - if(!ctx) { + if (!ctx) { return; } - for(i = 0; i < 2; ++i) { + for (i = 0; i < 2; ++i) { wslay_event_imsg_chunks_free(&ctx->imsgs[i]); - wslay_queue_free(ctx->imsgs[i].chunks); + wslay_queue_deinit(&ctx->imsgs[i].chunks); } - if(ctx->send_queue) { - while(!wslay_queue_empty(ctx->send_queue)) { - wslay_event_omsg_free(wslay_queue_top(ctx->send_queue)); - wslay_queue_pop(ctx->send_queue); - } - wslay_queue_free(ctx->send_queue); + + while (!wslay_queue_empty(&ctx->send_queue)) { + struct wslay_event_omsg *omsg = wslay_struct_of( + wslay_queue_top(&ctx->send_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); + wslay_event_omsg_free(omsg); } - if(ctx->send_ctrl_queue) { - while(!wslay_queue_empty(ctx->send_ctrl_queue)) { - wslay_event_omsg_free(wslay_queue_top(ctx->send_ctrl_queue)); - wslay_queue_pop(ctx->send_ctrl_queue); - } - wslay_queue_free(ctx->send_ctrl_queue); + wslay_queue_deinit(&ctx->send_queue); + + while (!wslay_queue_empty(&ctx->send_ctrl_queue)) { + struct wslay_event_omsg *omsg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); + wslay_event_omsg_free(omsg); } + wslay_queue_deinit(&ctx->send_ctrl_queue); + wslay_frame_context_free(ctx->frame_ctx); wslay_event_omsg_free(ctx->omsg); free(ctx); } -static void wslay_event_call_on_frame_recv_start_callback -(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) -{ - if(ctx->callbacks.on_frame_recv_start_callback) { +static void wslay_event_call_on_frame_recv_start_callback( + wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) { + if (ctx->callbacks.on_frame_recv_start_callback) { struct wslay_event_on_frame_recv_start_arg arg; arg.fin = iocb->fin; arg.rsv = iocb->rsv; @@ -532,10 +469,9 @@ static void wslay_event_call_on_frame_recv_start_callback } } -static void wslay_event_call_on_frame_recv_chunk_callback -(wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) -{ - if(ctx->callbacks.on_frame_recv_chunk_callback) { +static void wslay_event_call_on_frame_recv_chunk_callback( + wslay_event_context_ptr ctx, const struct wslay_frame_iocb *iocb) { + if (ctx->callbacks.on_frame_recv_chunk_callback) { struct wslay_event_on_frame_recv_chunk_arg arg; arg.data = iocb->data; arg.data_length = iocb->data_length; @@ -543,205 +479,202 @@ static void wslay_event_call_on_frame_recv_chunk_callback } } -static void wslay_event_call_on_frame_recv_end_callback -(wslay_event_context_ptr ctx) -{ - if(ctx->callbacks.on_frame_recv_end_callback) { +static void +wslay_event_call_on_frame_recv_end_callback(wslay_event_context_ptr ctx) { + if (ctx->callbacks.on_frame_recv_end_callback) { ctx->callbacks.on_frame_recv_end_callback(ctx, ctx->user_data); } } -static int wslay_event_is_valid_status_code(uint16_t status_code) -{ - return (1000 <= status_code && status_code <= 1011 && - status_code != 1004 && status_code != 1005 && status_code != 1006) || - (3000 <= status_code && status_code <= 4999); +static int wslay_event_is_valid_status_code(uint16_t status_code) { + return (1000 <= status_code && status_code <= 1011 && status_code != 1004 && + status_code != 1005 && status_code != 1006) || + (3000 <= status_code && status_code <= 4999); } -static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) -{ +static int wslay_event_config_get_no_buffering(wslay_event_context_ptr ctx) { return (ctx->config & WSLAY_CONFIG_NO_BUFFERING) > 0; } -int wslay_event_recv(wslay_event_context_ptr ctx) -{ +int wslay_event_recv(wslay_event_context_ptr ctx) { struct wslay_frame_iocb iocb; ssize_t r; - while(ctx->read_enabled) { + while (ctx->read_enabled) { memset(&iocb, 0, sizeof(iocb)); r = wslay_frame_recv(ctx->frame_ctx, &iocb); - if(r >= 0) { + if (r >= 0) { int new_frame = 0; /* RSV1 is not allowed on control and continuation frames */ - if((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || - (wslay_get_rsv1(iocb.rsv) && (wslay_is_ctrl_frame(iocb.opcode) || - iocb.opcode == WSLAY_CONTINUATION_FRAME)) || - (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((!wslay_event_verify_rsv_bits(ctx, iocb.rsv)) || + (wslay_get_rsv1(iocb.rsv) && + (wslay_is_ctrl_frame(iocb.opcode) || + iocb.opcode == WSLAY_CONTINUATION_FRAME)) || + (ctx->server && !iocb.mask) || (!ctx->server && iocb.mask)) { + if ((r = wslay_event_queue_close_wrapper(ctx, WSLAY_CODE_PROTOCOL_ERROR, + NULL, 0)) != 0) { + return (int)r; } break; } - if(ctx->imsg->opcode == 0xffu) { - if(iocb.opcode == WSLAY_TEXT_FRAME || - iocb.opcode == WSLAY_BINARY_FRAME || - iocb.opcode == WSLAY_CONNECTION_CLOSE || - iocb.opcode == WSLAY_PING || - iocb.opcode == WSLAY_PONG) { + if (ctx->imsg->opcode == 0xffu) { + if (iocb.opcode == WSLAY_TEXT_FRAME || + iocb.opcode == WSLAY_BINARY_FRAME || + iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) { wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); new_frame = 1; } else { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } - } else if(ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { - if(iocb.opcode == WSLAY_CONTINUATION_FRAME) { + } else if (ctx->ipayloadlen == 0 && ctx->ipayloadoff == 0) { + if (iocb.opcode == WSLAY_CONTINUATION_FRAME) { ctx->imsg->fin = iocb.fin; - } else if(iocb.opcode == WSLAY_CONNECTION_CLOSE || - iocb.opcode == WSLAY_PING || - iocb.opcode == WSLAY_PONG) { + } else if (iocb.opcode == WSLAY_CONNECTION_CLOSE || + iocb.opcode == WSLAY_PING || iocb.opcode == WSLAY_PONG) { ctx->imsg = &ctx->imsgs[1]; wslay_event_imsg_set(ctx->imsg, iocb.fin, iocb.rsv, iocb.opcode); } else { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } new_frame = 1; } - if(new_frame) { - if(ctx->imsg->msg_length+iocb.payload_length > - ctx->max_recv_msg_length) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { - return r; + if (new_frame) { + if (ctx->imsg->msg_length + iocb.payload_length > + ctx->max_recv_msg_length) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_MESSAGE_TOO_BIG, NULL, 0)) != 0) { + return (int)r; } break; } ctx->ipayloadlen = iocb.payload_length; wslay_event_call_on_frame_recv_start_callback(ctx, &iocb); - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { - if((r = wslay_event_imsg_append_chunk(ctx->imsg, - iocb.payload_length)) != 0) { + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + if ((r = wslay_event_imsg_append_chunk(ctx->imsg, + iocb.payload_length)) != 0) { ctx->read_enabled = 0; - return r; + return (int)r; } } } /* If RSV1 bit is set then it is too early for utf-8 validation */ - if((!wslay_get_rsv1(ctx->imsg->rsv) && - ctx->imsg->opcode == WSLAY_TEXT_FRAME) || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + if ((!wslay_get_rsv1(ctx->imsg->rsv) && + ctx->imsg->opcode == WSLAY_TEXT_FRAME) || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { size_t i; - if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { i = 2; } else { i = 0; } - for(; i < iocb.data_length; ++i) { + for (; i < iocb.data_length; ++i) { uint32_t codep; - if(decode(&ctx->imsg->utf8state, &codep, - iocb.data[i]) == UTF8_REJECT) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { - return r; + if (decode(&ctx->imsg->utf8state, &codep, iocb.data[i]) == + UTF8_REJECT) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != + 0) { + return (int)r; } break; } } } - if(ctx->imsg->utf8state == UTF8_REJECT) { + if (ctx->imsg->utf8state == UTF8_REJECT) { break; } wslay_event_call_on_frame_recv_chunk_callback(ctx, &iocb); - if(iocb.data_length > 0) { - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { + if (iocb.data_length > 0) { + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { struct wslay_event_byte_chunk *chunk; - chunk = wslay_queue_tail(ctx->imsg->chunks); - wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, - iocb.data, iocb.data_length); + chunk = wslay_struct_of(wslay_queue_tail(&ctx->imsg->chunks), + struct wslay_event_byte_chunk, qe); + wslay_event_byte_chunk_copy(chunk, ctx->ipayloadoff, iocb.data, + iocb.data_length); } ctx->ipayloadoff += iocb.data_length; } - if(ctx->ipayloadoff == ctx->ipayloadlen) { - if(ctx->imsg->fin && - (ctx->imsg->opcode == WSLAY_TEXT_FRAME || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && - ctx->imsg->utf8state != UTF8_ACCEPT) { - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { - return r; + if (ctx->ipayloadoff == ctx->ipayloadlen) { + if (ctx->imsg->fin && + (ctx->imsg->opcode == WSLAY_TEXT_FRAME || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) && + ctx->imsg->utf8state != UTF8_ACCEPT) { + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA, NULL, 0)) != 0) { + return (int)r; } break; } wslay_event_call_on_frame_recv_end_callback(ctx); - if(ctx->imsg->fin) { - if(ctx->callbacks.on_msg_recv_callback || - ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || - ctx->imsg->opcode == WSLAY_PING) { + if (ctx->imsg->fin) { + if (ctx->callbacks.on_msg_recv_callback || + ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE || + ctx->imsg->opcode == WSLAY_PING) { struct wslay_event_on_msg_recv_arg arg; uint16_t status_code = 0; uint8_t *msg = NULL; size_t msg_length = 0; - if(!wslay_event_config_get_no_buffering(ctx) || - wslay_is_ctrl_frame(iocb.opcode)) { - msg = wslay_event_flatten_queue(ctx->imsg->chunks, + if (!wslay_event_config_get_no_buffering(ctx) || + wslay_is_ctrl_frame(iocb.opcode)) { + msg = wslay_event_flatten_queue(&ctx->imsg->chunks, ctx->imsg->msg_length); - if(ctx->imsg->msg_length && !msg) { + if (ctx->imsg->msg_length && !msg) { ctx->read_enabled = 0; return WSLAY_ERR_NOMEM; } msg_length = ctx->imsg->msg_length; } - if(ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->imsg->opcode == WSLAY_CONNECTION_CLOSE) { const uint8_t *reason; size_t reason_length; - if(ctx->imsg->msg_length >= 2) { + if (ctx->imsg->msg_length >= 2) { memcpy(&status_code, msg, 2); status_code = ntohs(status_code); - if(!wslay_event_is_valid_status_code(status_code)) { + if (!wslay_event_is_valid_status_code(status_code)) { free(msg); - if((r = wslay_event_queue_close_wrapper - (ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { - return r; + if ((r = wslay_event_queue_close_wrapper( + ctx, WSLAY_CODE_PROTOCOL_ERROR, NULL, 0)) != 0) { + return (int)r; } break; } - reason = msg+2; - reason_length = ctx->imsg->msg_length-2; + reason = msg + 2; + reason_length = ctx->imsg->msg_length - 2; } else { reason = NULL; reason_length = 0; } ctx->close_status |= WSLAY_CLOSE_RECEIVED; ctx->status_code_recv = - status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; - if((r = wslay_event_queue_close_wrapper - (ctx, status_code, reason, reason_length)) != 0) { + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + if ((r = wslay_event_queue_close_wrapper(ctx, status_code, reason, + reason_length)) != 0) { free(msg); - return r; + return (int)r; } - } else if(ctx->imsg->opcode == WSLAY_PING) { - struct wslay_event_msg arg; - arg.opcode = WSLAY_PONG; - arg.msg = msg; - arg.msg_length = ctx->imsg->msg_length; - if((r = wslay_event_queue_msg(ctx, &arg)) && - r != WSLAY_ERR_NO_MORE_MSG) { + } else if (ctx->imsg->opcode == WSLAY_PING) { + struct wslay_event_msg pong_arg; + pong_arg.opcode = WSLAY_PONG; + pong_arg.msg = msg; + pong_arg.msg_length = ctx->imsg->msg_length; + if ((r = wslay_event_queue_msg(ctx, &pong_arg)) && + r != WSLAY_ERR_NO_MORE_MSG) { ctx->read_enabled = 0; free(msg); - return r; + return (int)r; } } - if(ctx->callbacks.on_msg_recv_callback) { + if (ctx->callbacks.on_msg_recv_callback) { arg.rsv = ctx->imsg->rsv; arg.opcode = ctx->imsg->opcode; arg.msg = msg; @@ -753,17 +686,17 @@ int wslay_event_recv(wslay_event_context_ptr ctx) free(msg); } wslay_event_imsg_reset(ctx->imsg); - if(ctx->imsg == &ctx->imsgs[1]) { + if (ctx->imsg == &ctx->imsgs[1]) { ctx->imsg = &ctx->imsgs[0]; } } ctx->ipayloadlen = ctx->ipayloadoff = 0; } } else { - if(r != WSLAY_ERR_WANT_READ || - (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { - if((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { - return r; + if (r != WSLAY_ERR_WANT_READ || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if ((r = wslay_event_queue_close_wrapper(ctx, 0, NULL, 0)) != 0) { + return (int)r; } return WSLAY_ERR_CALLBACK_FAILURE; } @@ -773,26 +706,25 @@ int wslay_event_recv(wslay_event_context_ptr ctx) return 0; } -static void wslay_event_on_non_fragmented_msg_popped -(wslay_event_context_ptr ctx) -{ +static void +wslay_event_on_non_fragmented_msg_popped(wslay_event_context_ptr ctx) { ctx->omsg->fin = 1; ctx->opayloadlen = ctx->omsg->data_length; ctx->opayloadoff = 0; } -static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop -(wslay_event_context_ptr ctx) -{ +static struct wslay_event_omsg * +wslay_event_send_ctrl_queue_pop(wslay_event_context_ptr ctx) { /* * If Close control frame is queued, we don't send any control frame * other than Close. */ - if(ctx->close_status & WSLAY_CLOSE_QUEUED) { - while(!wslay_queue_empty(ctx->send_ctrl_queue)) { - struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); - wslay_queue_pop(ctx->send_ctrl_queue); - if(msg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->close_status & WSLAY_CLOSE_QUEUED) { + while (!wslay_queue_empty(&ctx->send_ctrl_queue)) { + struct wslay_event_omsg *msg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); + if (msg->opcode == WSLAY_CONNECTION_CLOSE) { return msg; } else { wslay_event_omsg_free(msg); @@ -800,71 +732,73 @@ static struct wslay_event_omsg* wslay_event_send_ctrl_queue_pop } return NULL; } else { - struct wslay_event_omsg *msg = wslay_queue_top(ctx->send_ctrl_queue); - wslay_queue_pop(ctx->send_ctrl_queue); + struct wslay_event_omsg *msg = wslay_struct_of( + wslay_queue_top(&ctx->send_ctrl_queue), struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_ctrl_queue); return msg; } } -int wslay_event_send(wslay_event_context_ptr ctx) -{ +int wslay_event_send(wslay_event_context_ptr ctx) { struct wslay_frame_iocb iocb; ssize_t r; - while(ctx->write_enabled && - (!wslay_queue_empty(ctx->send_queue) || - !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg)) { - if(!ctx->omsg) { - if(wslay_queue_empty(ctx->send_ctrl_queue)) { - ctx->omsg = wslay_queue_top(ctx->send_queue); - wslay_queue_pop(ctx->send_queue); + while (ctx->write_enabled && + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) { + if (!ctx->omsg) { + if (wslay_queue_empty(&ctx->send_ctrl_queue)) { + ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue), + struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); } else { ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); - if(ctx->omsg == NULL) { + if (ctx->omsg == NULL) { break; } } - if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { wslay_event_on_non_fragmented_msg_popped(ctx); } - } else if(!wslay_is_ctrl_frame(ctx->omsg->opcode) && - ctx->frame_ctx->ostate == PREP_HEADER && - !wslay_queue_empty(ctx->send_ctrl_queue)) { - if((r = wslay_queue_push_front(ctx->send_queue, ctx->omsg)) != 0) { - ctx->write_enabled = 0; - return r; - } + } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(&ctx->send_ctrl_queue)) { + wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe); ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); - if(ctx->omsg == NULL) { + if (ctx->omsg == NULL) { break; } /* ctrl message has WSLAY_NON_FRAGMENTED */ wslay_event_on_non_fragmented_msg_popped(ctx); } - if(ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { memset(&iocb, 0, sizeof(iocb)); iocb.fin = 1; iocb.opcode = ctx->omsg->opcode; iocb.rsv = ctx->omsg->rsv; - iocb.mask = ctx->server^1; - iocb.data = ctx->omsg->data+ctx->opayloadoff; - iocb.data_length = ctx->opayloadlen-ctx->opayloadoff; + iocb.mask = ctx->server ^ 1; + iocb.data = ctx->omsg->data; + iocb.data_length = ctx->opayloadlen; + if (ctx->opayloadoff) { + iocb.data += ctx->opayloadoff; + iocb.data_length -= ctx->opayloadoff; + } iocb.payload_length = ctx->opayloadlen; r = wslay_frame_send(ctx->frame_ctx, &iocb); - if(r >= 0) { - ctx->opayloadoff += r; - if(ctx->opayloadoff == ctx->opayloadlen) { + if (r >= 0) { + ctx->opayloadoff += (uint64_t)r; + if (ctx->opayloadoff == ctx->opayloadlen) { --ctx->queued_msg_count; ctx->queued_msg_length -= ctx->omsg->data_length; - if(ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { uint16_t status_code = 0; ctx->write_enabled = 0; ctx->close_status |= WSLAY_CLOSE_SENT; - if(ctx->omsg->data_length >= 2) { + if (ctx->omsg->data_length >= 2) { memcpy(&status_code, ctx->omsg->data, 2); status_code = ntohs(status_code); } ctx->status_code_sent = - status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; } wslay_event_omsg_free(ctx->omsg); ctx->omsg = NULL; @@ -872,30 +806,29 @@ int wslay_event_send(wslay_event_context_ptr ctx) break; } } else { - if(r != WSLAY_ERR_WANT_WRITE || - (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { + if (r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } break; } } else { - if(ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { int eof = 0; r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), - &ctx->omsg->source, - &eof, ctx->user_data); - if(r == 0) { + &ctx->omsg->source, &eof, ctx->user_data); + if (r == 0 && eof == 0) { break; - } else if(r < 0) { + } else if (r < 0) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } - ctx->obuflimit = ctx->obuf+r; - if(eof) { + ctx->obuflimit = ctx->obuf + r; + if (eof) { ctx->omsg->fin = 1; } - ctx->opayloadlen = r; + ctx->opayloadlen = (uint64_t)r; ctx->opayloadoff = 0; } memset(&iocb, 0, sizeof(iocb)); @@ -904,29 +837,28 @@ int wslay_event_send(wslay_event_context_ptr ctx) iocb.rsv = ctx->omsg->rsv; iocb.mask = ctx->server ? 0 : 1; iocb.data = ctx->obufmark; - iocb.data_length = ctx->obuflimit-ctx->obufmark; + iocb.data_length = (size_t)(ctx->obuflimit - ctx->obufmark); iocb.payload_length = ctx->opayloadlen; r = wslay_frame_send(ctx->frame_ctx, &iocb); - if(r >= 0) { + if (r >= 0) { ctx->obufmark += r; - if(ctx->obufmark == ctx->obuflimit) { + if (ctx->obufmark == ctx->obuflimit) { ctx->obufmark = ctx->obuflimit = ctx->obuf; - if(ctx->omsg->fin) { + if (ctx->omsg->fin) { --ctx->queued_msg_count; wslay_event_omsg_free(ctx->omsg); ctx->omsg = NULL; } else { ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; /* RSV1 is not set on continuation frames */ - ctx->omsg->rsv = ctx->omsg->rsv & ~WSLAY_RSV1_BIT; + ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT); } } else { break; } } else { - if(r != WSLAY_ERR_WANT_WRITE || - (ctx->error != WSLAY_ERR_WOULDBLOCK && - ctx->error != 0)) { + if (r != WSLAY_ERR_WANT_WRITE || + (ctx->error != WSLAY_ERR_WOULDBLOCK && ctx->error != 0)) { ctx->write_enabled = 0; return WSLAY_ERR_CALLBACK_FAILURE; } @@ -937,91 +869,214 @@ int wslay_event_send(wslay_event_context_ptr ctx) return 0; } -void wslay_event_set_error(wslay_event_context_ptr ctx, int val) -{ +ssize_t wslay_event_write(wslay_event_context_ptr ctx, uint8_t *buf, + size_t buflen) { + struct wslay_frame_iocb iocb; + ssize_t r; + uint8_t *buf_last = buf; + size_t wpayloadlen; + while (ctx->write_enabled && + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg)) { + if (!ctx->omsg) { + if (wslay_queue_empty(&ctx->send_ctrl_queue)) { + ctx->omsg = wslay_struct_of(wslay_queue_top(&ctx->send_queue), + struct wslay_event_omsg, qe); + wslay_queue_pop(&ctx->send_queue); + } else { + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if (ctx->omsg == NULL) { + break; + } + } + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + wslay_event_on_non_fragmented_msg_popped(ctx); + } + } else if (!wslay_is_ctrl_frame(ctx->omsg->opcode) && + ctx->frame_ctx->ostate == PREP_HEADER && + !wslay_queue_empty(&ctx->send_ctrl_queue)) { + wslay_queue_push_front(&ctx->send_queue, &ctx->omsg->qe); + ctx->omsg = wslay_event_send_ctrl_queue_pop(ctx); + if (ctx->omsg == NULL) { + break; + } + /* ctrl message has WSLAY_NON_FRAGMENTED */ + wslay_event_on_non_fragmented_msg_popped(ctx); + } + if (ctx->omsg->type == WSLAY_NON_FRAGMENTED) { + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server ^ 1; + iocb.data = ctx->omsg->data; + iocb.data_length = ctx->opayloadlen; + if (ctx->opayloadoff) { + iocb.data += ctx->opayloadoff; + iocb.data_length -= ctx->opayloadoff; + } + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen, + &wpayloadlen); + if (r > 0) { + assert((size_t)r <= buflen); + + buf_last += r; + buflen -= (size_t)r; + + ctx->opayloadoff += wpayloadlen; + if (ctx->opayloadoff == ctx->opayloadlen) { + --ctx->queued_msg_count; + ctx->queued_msg_length -= ctx->omsg->data_length; + if (ctx->omsg->opcode == WSLAY_CONNECTION_CLOSE) { + uint16_t status_code = 0; + ctx->write_enabled = 0; + ctx->close_status |= WSLAY_CLOSE_SENT; + if (ctx->omsg->data_length >= 2) { + memcpy(&status_code, ctx->omsg->data, 2); + status_code = ntohs(status_code); + } + ctx->status_code_sent = + status_code == 0 ? WSLAY_CODE_NO_STATUS_RCVD : status_code; + } + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + break; + } + } else if (r == 0) { + return buf_last - buf; + } else { + return WSLAY_ERR_CALLBACK_FAILURE; + } + } else { + if (ctx->omsg->fin == 0 && ctx->obuflimit == ctx->obufmark) { + int eof = 0; + r = ctx->omsg->read_callback(ctx, ctx->obuf, sizeof(ctx->obuf), + &ctx->omsg->source, &eof, ctx->user_data); + if (r == 0 && eof == 0) { + break; + } else if (r < 0) { + ctx->write_enabled = 0; + return WSLAY_ERR_CALLBACK_FAILURE; + } + ctx->obuflimit = ctx->obuf + r; + if (eof) { + ctx->omsg->fin = 1; + } + ctx->opayloadlen = (uint64_t)r; + ctx->opayloadoff = 0; + } + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = ctx->omsg->fin; + iocb.opcode = ctx->omsg->opcode; + iocb.rsv = ctx->omsg->rsv; + iocb.mask = ctx->server ? 0 : 1; + iocb.data = ctx->obufmark; + iocb.data_length = (size_t)(ctx->obuflimit - ctx->obufmark); + iocb.payload_length = ctx->opayloadlen; + r = wslay_frame_write(ctx->frame_ctx, &iocb, buf_last, buflen, + &wpayloadlen); + if (r > 0) { + assert((size_t)r <= buflen); + + buf_last += r; + buflen -= (size_t)r; + + ctx->obufmark += wpayloadlen; + if (ctx->obufmark == ctx->obuflimit) { + ctx->obufmark = ctx->obuflimit = ctx->obuf; + if (ctx->omsg->fin) { + --ctx->queued_msg_count; + wslay_event_omsg_free(ctx->omsg); + ctx->omsg = NULL; + } else { + ctx->omsg->opcode = WSLAY_CONTINUATION_FRAME; + /* RSV1 is not set on continuation frames */ + ctx->omsg->rsv = (uint8_t)(ctx->omsg->rsv & ~WSLAY_RSV1_BIT); + } + } else { + break; + } + } else if (r == 0) { + return buf_last - buf; + } else { + return WSLAY_ERR_CALLBACK_FAILURE; + } + } + } + return buf_last - buf; +} + +void wslay_event_set_error(wslay_event_context_ptr ctx, int val) { ctx->error = val; } -int wslay_event_want_read(wslay_event_context_ptr ctx) -{ +int wslay_event_want_read(wslay_event_context_ptr ctx) { return ctx->read_enabled; } -int wslay_event_want_write(wslay_event_context_ptr ctx) -{ +int wslay_event_want_write(wslay_event_context_ptr ctx) { return ctx->write_enabled && - (!wslay_queue_empty(ctx->send_queue) || - !wslay_queue_empty(ctx->send_ctrl_queue) || ctx->omsg); + (!wslay_queue_empty(&ctx->send_queue) || + !wslay_queue_empty(&ctx->send_ctrl_queue) || ctx->omsg); } -void wslay_event_shutdown_read(wslay_event_context_ptr ctx) -{ +void wslay_event_shutdown_read(wslay_event_context_ptr ctx) { ctx->read_enabled = 0; } -void wslay_event_shutdown_write(wslay_event_context_ptr ctx) -{ +void wslay_event_shutdown_write(wslay_event_context_ptr ctx) { ctx->write_enabled = 0; } -int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) -{ +int wslay_event_get_read_enabled(wslay_event_context_ptr ctx) { return ctx->read_enabled; } -int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) -{ +int wslay_event_get_write_enabled(wslay_event_context_ptr ctx) { return ctx->write_enabled; } -int wslay_event_get_close_received(wslay_event_context_ptr ctx) -{ +int wslay_event_get_close_received(wslay_event_context_ptr ctx) { return (ctx->close_status & WSLAY_CLOSE_RECEIVED) > 0; } -int wslay_event_get_close_sent(wslay_event_context_ptr ctx) -{ +int wslay_event_get_close_sent(wslay_event_context_ptr ctx) { return (ctx->close_status & WSLAY_CLOSE_SENT) > 0; } void wslay_event_config_set_allowed_rsv_bits(wslay_event_context_ptr ctx, - uint8_t rsv) -{ + uint8_t rsv) { /* We currently only allow WSLAY_RSV1_BIT or WSLAY_RSV_NONE */ ctx->allowed_rsv_bits = rsv & WSLAY_RSV1_BIT; } -void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) -{ - if(val) { +void wslay_event_config_set_no_buffering(wslay_event_context_ptr ctx, int val) { + if (val) { ctx->config |= WSLAY_CONFIG_NO_BUFFERING; } else { - ctx->config &= ~WSLAY_CONFIG_NO_BUFFERING; + ctx->config &= (uint32_t)~WSLAY_CONFIG_NO_BUFFERING; } } void wslay_event_config_set_max_recv_msg_length(wslay_event_context_ptr ctx, - uint64_t val) -{ + uint64_t val) { ctx->max_recv_msg_length = val; } -uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) -{ +uint16_t wslay_event_get_status_code_received(wslay_event_context_ptr ctx) { return ctx->status_code_recv; } -uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) -{ +uint16_t wslay_event_get_status_code_sent(wslay_event_context_ptr ctx) { return ctx->status_code_sent; } -size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) -{ +size_t wslay_event_get_queued_msg_count(wslay_event_context_ptr ctx) { return ctx->queued_msg_count; } -size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) -{ +size_t wslay_event_get_queued_msg_length(wslay_event_context_ptr ctx) { return ctx->queued_msg_length; } diff --git a/deps/wslay/lib/wslay_event.h b/deps/wslay/lib/wslay_event.h index 36feb903..e30c3d19 100644 --- a/deps/wslay/lib/wslay_event.h +++ b/deps/wslay/lib/wslay_event.h @@ -31,10 +31,10 @@ #include -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/**/ *send_queue; + struct wslay_queue /**/ send_queue; /* Queue for control frames */ - struct wslay_queue/**/ *send_ctrl_queue; + struct wslay_queue /**/ send_ctrl_queue; /* Size of send_queue + size of send_ctrl_queue */ size_t queued_msg_count; /* The sum of message length in send_queue */ diff --git a/deps/wslay/lib/wslay_frame.c b/deps/wslay/lib/wslay_frame.c index 445e750c..435044a3 100644 --- a/deps/wslay/lib/wslay_frame.c +++ b/deps/wslay/lib/wslay_frame.c @@ -34,10 +34,9 @@ int wslay_frame_context_init(wslay_frame_context_ptr *ctx, const struct wslay_frame_callbacks *callbacks, - void *user_data) -{ - *ctx = (wslay_frame_context_ptr)malloc(sizeof(struct wslay_frame_context)); - if(*ctx == NULL) { + void *user_data) { + *ctx = malloc(sizeof(struct wslay_frame_context)); + if (*ctx == NULL) { return -1; } memset(*ctx, 0, sizeof(struct wslay_frame_context)); @@ -50,38 +49,35 @@ int wslay_frame_context_init(wslay_frame_context_ptr *ctx, return 0; } -void wslay_frame_context_free(wslay_frame_context_ptr ctx) -{ - free(ctx); -} +void wslay_frame_context_free(wslay_frame_context_ptr ctx) { free(ctx); } ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, - struct wslay_frame_iocb *iocb) -{ - if(iocb->data_length > iocb->payload_length) { + struct wslay_frame_iocb *iocb) { + if (iocb->data_length > iocb->payload_length) { return WSLAY_ERR_INVALID_ARGUMENT; } - if(ctx->ostate == PREP_HEADER) { + if (ctx->ostate == PREP_HEADER) { uint8_t *hdptr = ctx->oheader; memset(ctx->oheader, 0, sizeof(ctx->oheader)); - *hdptr |= (iocb->fin << 7) & 0x80u; - *hdptr |= (iocb->rsv << 4) & 0x70u; - *hdptr |= iocb->opcode & 0xfu; + *hdptr |= (uint8_t)((uint8_t)(iocb->fin << 7) & 0x80u); + *hdptr |= (uint8_t)((uint8_t)(iocb->rsv << 4) & 0x70u); + /* Suppress stubborn gcc-10 warning */ + *hdptr |= (uint8_t)((uint8_t)(iocb->opcode << 0) & 0xfu); ++hdptr; - *hdptr |= (iocb->mask << 7) & 0x80u; - if(wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + *hdptr |= (uint8_t)((uint8_t)(iocb->mask << 7) & 0x80u); + if (wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { return WSLAY_ERR_INVALID_ARGUMENT; } - if(iocb->payload_length < 126) { - *hdptr |= iocb->payload_length; + if (iocb->payload_length < 126) { + *hdptr |= (uint8_t)iocb->payload_length; ++hdptr; - } else if(iocb->payload_length < (1 << 16)) { - uint16_t len = htons(iocb->payload_length); + } else if (iocb->payload_length < (1 << 16)) { + uint16_t len = htons((uint16_t)iocb->payload_length); *hdptr |= 126; ++hdptr; memcpy(hdptr, &len, 2); hdptr += 2; - } else if(iocb->payload_length < (1ull << 63)) { + } else if (iocb->payload_length < (1ull << 63)) { uint64_t len = hton64(iocb->payload_length); *hdptr |= 127; ++hdptr; @@ -91,9 +87,9 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, /* Too large payload length */ return WSLAY_ERR_INVALID_ARGUMENT; } - if(iocb->mask) { - if(ctx->callbacks.genmask_callback(ctx->omaskkey, 4, - ctx->user_data) != 0) { + if (iocb->mask) { + if (ctx->callbacks.genmask_callback(ctx->omaskkey, 4, ctx->user_data) != + 0) { return WSLAY_ERR_INVALID_CALLBACK; } else { ctx->omask = 1; @@ -107,21 +103,21 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, ctx->opayloadlen = iocb->payload_length; ctx->opayloadoff = 0; } - if(ctx->ostate == SEND_HEADER) { - ptrdiff_t len = ctx->oheaderlimit-ctx->oheadermark; + if (ctx->ostate == SEND_HEADER) { + ptrdiff_t len = ctx->oheaderlimit - ctx->oheadermark; ssize_t r; int flags = 0; - if(iocb->data_length > 0) { + if (iocb->data_length > 0) { flags |= WSLAY_MSG_MORE; }; - r = ctx->callbacks.send_callback(ctx->oheadermark, len, flags, + r = ctx->callbacks.send_callback(ctx->oheadermark, (size_t)len, flags, ctx->user_data); - if(r > 0) { - if(r > len) { + if (r > 0) { + if (r > len) { return WSLAY_ERR_INVALID_CALLBACK; } else { ctx->oheadermark += r; - if(ctx->oheadermark == ctx->oheaderlimit) { + if (ctx->oheadermark == ctx->oheaderlimit) { ctx->ostate = SEND_PAYLOAD; } else { return WSLAY_ERR_WANT_WRITE; @@ -131,34 +127,34 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, return WSLAY_ERR_WANT_WRITE; } } - if(ctx->ostate == SEND_PAYLOAD) { + if (ctx->ostate == SEND_PAYLOAD) { size_t totallen = 0; - if(iocb->data_length > 0) { - if(ctx->omask) { + if (iocb->data_length > 0) { + if (ctx->omask) { uint8_t temp[4096]; const uint8_t *datamark = iocb->data, - *datalimit = iocb->data+iocb->data_length; - while(datamark < datalimit) { - size_t datalen = datalimit - datamark; - const uint8_t *writelimit = datamark+ - wslay_min(sizeof(temp), datalen); - size_t writelen = writelimit-datamark; + *datalimit = iocb->data + iocb->data_length; + while (datamark < datalimit) { + size_t datalen = (size_t)(datalimit - datamark); + const uint8_t *writelimit = + datamark + wslay_min(sizeof(temp), datalen); + size_t writelen = (size_t)(writelimit - datamark); ssize_t r; size_t i; - for(i = 0; i < writelen; ++i) { - temp[i] = datamark[i]^ctx->omaskkey[(ctx->opayloadoff+i)%4]; + for (i = 0; i < writelen; ++i) { + temp[i] = datamark[i] ^ ctx->omaskkey[(ctx->opayloadoff + i) % 4]; } r = ctx->callbacks.send_callback(temp, writelen, 0, ctx->user_data); - if(r > 0) { - if((size_t)r > writelen) { + if (r > 0) { + if ((size_t)r > writelen) { return WSLAY_ERR_INVALID_CALLBACK; } else { datamark += r; - ctx->opayloadoff += r; - totallen += r; + ctx->opayloadoff += (uint64_t)r; + totallen += (size_t)r; } } else { - if(totallen > 0) { + if (totallen > 0) { break; } else { return WSLAY_ERR_WANT_WRITE; @@ -169,44 +165,148 @@ ssize_t wslay_frame_send(wslay_frame_context_ptr ctx, ssize_t r; r = ctx->callbacks.send_callback(iocb->data, iocb->data_length, 0, ctx->user_data); - if(r > 0) { - if((size_t)r > iocb->data_length) { + if (r > 0) { + if ((size_t)r > iocb->data_length) { return WSLAY_ERR_INVALID_CALLBACK; } else { - ctx->opayloadoff += r; - totallen = r; + ctx->opayloadoff += (uint64_t)r; + totallen = (size_t)r; } } else { return WSLAY_ERR_WANT_WRITE; } } } - if(ctx->opayloadoff == ctx->opayloadlen) { + if (ctx->opayloadoff == ctx->opayloadlen) { ctx->ostate = PREP_HEADER; } - return totallen; + return (ssize_t)totallen; } return WSLAY_ERR_INVALID_ARGUMENT; } -static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) -{ - ptrdiff_t len = ctx->ibuflimit-ctx->ibufmark; - memmove(ctx->ibuf, ctx->ibufmark, len); - ctx->ibuflimit = ctx->ibuf+len; +ssize_t wslay_frame_write(wslay_frame_context_ptr ctx, + struct wslay_frame_iocb *iocb, uint8_t *buf, + size_t buflen, size_t *pwpayloadlen) { + uint8_t *buf_last = buf; + size_t i; + size_t hdlen; + + *pwpayloadlen = 0; + + if (iocb->data_length > iocb->payload_length) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + + switch (ctx->ostate) { + case PREP_HEADER: + case PREP_HEADER_NOBUF: + hdlen = 2; + if (iocb->payload_length < 126) { + /* nothing to do */ + } else if (iocb->payload_length < (1 << 16)) { + hdlen += 2; + } else if (iocb->payload_length < (1ull << 63)) { + hdlen += 8; + } + if (iocb->mask) { + hdlen += 4; + } + + if (buflen < hdlen) { + ctx->ostate = PREP_HEADER_NOBUF; + return 0; + } + + memset(buf_last, 0, hdlen); + *buf_last |= (uint8_t)((uint8_t)(iocb->fin << 7) & 0x80u); + *buf_last |= (uint8_t)((uint8_t)(iocb->rsv << 4) & 0x70u); + /* Suppress stubborn gcc-10 warning */ + *buf_last |= (uint8_t)((uint8_t)(iocb->opcode << 0) & 0xfu); + ++buf_last; + *buf_last |= (uint8_t)((uint8_t)(iocb->mask << 7) & 0x80u); + if (wslay_is_ctrl_frame(iocb->opcode) && iocb->payload_length > 125) { + return WSLAY_ERR_INVALID_ARGUMENT; + } + if (iocb->payload_length < 126) { + *buf_last |= (uint8_t)iocb->payload_length; + ++buf_last; + } else if (iocb->payload_length < (1 << 16)) { + uint16_t len = htons((uint16_t)iocb->payload_length); + *buf_last |= 126; + ++buf_last; + memcpy(buf_last, &len, 2); + buf_last += 2; + } else if (iocb->payload_length < (1ull << 63)) { + uint64_t len = hton64(iocb->payload_length); + *buf_last |= 127; + ++buf_last; + memcpy(buf_last, &len, 8); + buf_last += 8; + } else { + /* Too large payload length */ + return WSLAY_ERR_INVALID_ARGUMENT; + } + if (iocb->mask) { + if (ctx->callbacks.genmask_callback(ctx->omaskkey, 4, ctx->user_data) != + 0) { + return WSLAY_ERR_INVALID_CALLBACK; + } else { + ctx->omask = 1; + memcpy(buf_last, ctx->omaskkey, 4); + buf_last += 4; + } + } + ctx->ostate = SEND_PAYLOAD; + ctx->opayloadlen = iocb->payload_length; + ctx->opayloadoff = 0; + + buflen -= (size_t)(buf_last - buf); + /* fall through */ + case SEND_PAYLOAD: + if (iocb->data_length > 0) { + size_t writelen = wslay_min(buflen, iocb->data_length); + + if (ctx->omask) { + for (i = 0; i < writelen; ++i) { + *buf_last++ = + iocb->data[i] ^ ctx->omaskkey[(ctx->opayloadoff + i) % 4]; + } + } else { + memcpy(buf_last, iocb->data, writelen); + buf_last += writelen; + } + + ctx->opayloadoff += writelen; + *pwpayloadlen = writelen; + } + + if (ctx->opayloadoff == ctx->opayloadlen) { + ctx->ostate = PREP_HEADER; + } + + return buf_last - buf; + default: + return WSLAY_ERR_INVALID_ARGUMENT; + } +} + +static void wslay_shift_ibuf(wslay_frame_context_ptr ctx) { + ptrdiff_t len = ctx->ibuflimit - ctx->ibufmark; + memmove(ctx->ibuf, ctx->ibufmark, (size_t)len); + ctx->ibuflimit = ctx->ibuf + len; ctx->ibufmark = ctx->ibuf; } -static ssize_t wslay_recv(wslay_frame_context_ptr ctx) -{ +static ssize_t wslay_recv(wslay_frame_context_ptr ctx) { ssize_t r; - if(ctx->ibufmark != ctx->ibuf) { + if (ctx->ibufmark != ctx->ibuf) { wslay_shift_ibuf(ctx); } - r = ctx->callbacks.recv_callback - (ctx->ibuflimit, ctx->ibuf+sizeof(ctx->ibuf)-ctx->ibuflimit, - 0, ctx->user_data); - if(r > 0) { + r = ctx->callbacks.recv_callback( + ctx->ibuflimit, (size_t)(ctx->ibuf + sizeof(ctx->ibuf) - ctx->ibuflimit), + 0, ctx->user_data); + if (r > 0) { ctx->ibuflimit += r; } else { r = WSLAY_ERR_WANT_READ; @@ -217,17 +317,16 @@ static ssize_t wslay_recv(wslay_frame_context_ptr ctx) #define WSLAY_AVAIL_IBUF(ctx) ((size_t)(ctx->ibuflimit - ctx->ibufmark)) ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, - struct wslay_frame_iocb *iocb) -{ + struct wslay_frame_iocb *iocb) { ssize_t r; - if(ctx->istate == RECV_HEADER1) { + if (ctx->istate == RECV_HEADER1) { uint8_t fin, opcode, rsv, payloadlen; - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } fin = (ctx->ibufmark[0] >> 7) & 1; @@ -240,19 +339,19 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, ctx->imask = (ctx->ibufmark[0] >> 7) & 1; payloadlen = ctx->ibufmark[0] & 0x7fu; ++ctx->ibufmark; - if(wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { + if (wslay_is_ctrl_frame(opcode) && (payloadlen > 125 || !fin)) { return WSLAY_ERR_PROTO; } - if(payloadlen == 126) { + if (payloadlen == 126) { ctx->istate = RECV_EXT_PAYLOADLEN; ctx->ireqread = 2; - } else if(payloadlen == 127) { + } else if (payloadlen == 127) { ctx->istate = RECV_EXT_PAYLOADLEN; ctx->ireqread = 8; } else { ctx->ipayloadlen = payloadlen; ctx->ipayloadoff = 0; - if(ctx->imask) { + if (ctx->imask) { ctx->istate = RECV_MASKKEY; ctx->ireqread = 4; } else { @@ -260,42 +359,41 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, } } } - if(ctx->istate == RECV_EXT_PAYLOADLEN) { - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (ctx->istate == RECV_EXT_PAYLOADLEN) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } } ctx->ipayloadlen = 0; ctx->ipayloadoff = 0; - memcpy((uint8_t*)&ctx->ipayloadlen+(8-ctx->ireqread), - ctx->ibufmark, ctx->ireqread); + memcpy((uint8_t *)&ctx->ipayloadlen + (8 - ctx->ireqread), ctx->ibufmark, + ctx->ireqread); ctx->ipayloadlen = ntoh64(ctx->ipayloadlen); ctx->ibufmark += ctx->ireqread; - if(ctx->ireqread == 8) { - if(ctx->ipayloadlen < (1 << 16) || - ctx->ipayloadlen & (1ull << 63)) { + if (ctx->ireqread == 8) { + if (ctx->ipayloadlen < (1 << 16) || ctx->ipayloadlen & (1ull << 63)) { return WSLAY_ERR_PROTO; } - } else if(ctx->ipayloadlen < 126) { + } else if (ctx->ipayloadlen < 126) { return WSLAY_ERR_PROTO; } - if(ctx->imask) { + if (ctx->imask) { ctx->istate = RECV_MASKKEY; ctx->ireqread = 4; } else { ctx->istate = RECV_PAYLOAD; } } - if(ctx->istate == RECV_MASKKEY) { - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { - if((r = wslay_recv(ctx)) <= 0) { + if (ctx->istate == RECV_MASKKEY) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } - if(WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { + if (WSLAY_AVAIL_IBUF(ctx) < ctx->ireqread) { return WSLAY_ERR_WANT_READ; } } @@ -303,25 +401,25 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, ctx->ibufmark += 4; ctx->istate = RECV_PAYLOAD; } - if(ctx->istate == RECV_PAYLOAD) { + if (ctx->istate == RECV_PAYLOAD) { uint8_t *readlimit, *readmark; - uint64_t rempayloadlen = ctx->ipayloadlen-ctx->ipayloadoff; - if(WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { - if((r = wslay_recv(ctx)) <= 0) { + uint64_t rempayloadlen = ctx->ipayloadlen - ctx->ipayloadoff; + if (WSLAY_AVAIL_IBUF(ctx) == 0 && rempayloadlen > 0) { + if ((r = wslay_recv(ctx)) <= 0) { return r; } } readmark = ctx->ibufmark; - readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen ? - ctx->ibuflimit : ctx->ibufmark+rempayloadlen; - if(ctx->imask) { - for(; ctx->ibufmark != readlimit; - ++ctx->ibufmark, ++ctx->ipayloadoff) { + readlimit = WSLAY_AVAIL_IBUF(ctx) < rempayloadlen + ? ctx->ibuflimit + : ctx->ibufmark + rempayloadlen; + if (ctx->imask) { + for (; ctx->ibufmark != readlimit; ++ctx->ibufmark, ++ctx->ipayloadoff) { ctx->ibufmark[0] ^= ctx->imaskkey[ctx->ipayloadoff % 4]; } } else { ctx->ibufmark = readlimit; - ctx->ipayloadoff += readlimit-readmark; + ctx->ipayloadoff += (uint64_t)(readlimit - readmark); } iocb->fin = ctx->iom.fin; iocb->rsv = ctx->iom.rsv; @@ -329,12 +427,12 @@ ssize_t wslay_frame_recv(wslay_frame_context_ptr ctx, iocb->payload_length = ctx->ipayloadlen; iocb->mask = ctx->imask; iocb->data = readmark; - iocb->data_length = ctx->ibufmark-readmark; - if(ctx->ipayloadlen == ctx->ipayloadoff) { + iocb->data_length = (size_t)(ctx->ibufmark - readmark); + if (ctx->ipayloadlen == ctx->ipayloadoff) { ctx->istate = RECV_HEADER1; ctx->ireqread = 2; } - return iocb->data_length; + return (ssize_t)iocb->data_length; } return WSLAY_ERR_INVALID_ARGUMENT; } diff --git a/deps/wslay/lib/wslay_frame.h b/deps/wslay/lib/wslay_frame.h index 6a75858c..3ac98112 100644 --- a/deps/wslay/lib/wslay_frame.h +++ b/deps/wslay/lib/wslay_frame.h @@ -33,6 +33,7 @@ enum wslay_frame_state { PREP_HEADER, + PREP_HEADER_NOBUF, SEND_HEADER, SEND_PAYLOAD, RECV_HEADER1, diff --git a/deps/wslay/lib/wslay_macro.h b/deps/wslay/lib/wslay_macro.h new file mode 100644 index 00000000..a06cff98 --- /dev/null +++ b/deps/wslay/lib/wslay_macro.h @@ -0,0 +1,39 @@ +/* + * Wslay - The WebSocket Library + * + * 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 + * "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. + */ +#ifndef WSLAY_MACRO_H +#define WSLAY_MACRO_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include + +#include + +#define wslay_struct_of(ptr, type, member) \ + ((type *)(void *)((char *)(ptr)-offsetof(type, member))) + +#endif /* WSLAY_MACRO_H */ diff --git a/deps/wslay/lib/wslay_net.c b/deps/wslay/lib/wslay_net.c index d3867c21..e256158b 100644 --- a/deps/wslay/lib/wslay_net.c +++ b/deps/wslay/lib/wslay_net.c @@ -26,10 +26,9 @@ #ifndef WORDS_BIGENDIAN -uint64_t wslay_byteswap64(uint64_t x) -{ +uint64_t wslay_byteswap64(uint64_t x) { uint64_t u = ntohl(x & 0xffffffffllu); - uint64_t l = ntohl(x >> 32); + uint64_t l = ntohl((uint32_t)(x >> 32)); return (u << 32) | l; } diff --git a/deps/wslay/lib/wslay_queue.c b/deps/wslay/lib/wslay_queue.c index 8d266968..ebde3ba8 100644 --- a/deps/wslay/lib/wslay_queue.c +++ b/deps/wslay/lib/wslay_queue.c @@ -27,91 +27,51 @@ #include #include -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_init(struct wslay_queue *queue) { + queue->top = NULL; + queue->tail = &queue->top; } -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_deinit(struct wslay_queue *queue) { (void)queue; } + +void wslay_queue_push(struct wslay_queue *queue, + struct wslay_queue_entry *ent) { + ent->next = NULL; + *queue->tail = ent; + queue->tail = &ent->next; +} + +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; } } -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; - - } 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) -{ +void wslay_queue_pop(struct wslay_queue *queue) { 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) -{ - assert(queue->tail); - return queue->tail->data; +struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue) { + assert(queue->top); + return queue->top; } -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; } diff --git a/deps/wslay/lib/wslay_queue.h b/deps/wslay/lib/wslay_queue.h index 55e78a04..fa16aea4 100644 --- a/deps/wslay/lib/wslay_queue.h +++ b/deps/wslay/lib/wslay_queue.h @@ -31,23 +31,23 @@ #include -struct wslay_queue_cell { - void *data; - struct wslay_queue_cell *next; +struct wslay_queue_entry { + struct wslay_queue_entry *next; }; struct wslay_queue { - struct wslay_queue_cell *top; - struct wslay_queue_cell *tail; + struct wslay_queue_entry *top; + struct wslay_queue_entry **tail; }; -struct wslay_queue* wslay_queue_new(void); -void wslay_queue_free(struct wslay_queue *queue); -int wslay_queue_push(struct wslay_queue *queue, void *data); -int wslay_queue_push_front(struct wslay_queue *queue, void *data); +void wslay_queue_init(struct wslay_queue *queue); +void wslay_queue_deinit(struct wslay_queue *queue); +void wslay_queue_push(struct wslay_queue *queue, struct wslay_queue_entry *ent); +void wslay_queue_push_front(struct wslay_queue *queue, + struct wslay_queue_entry *ent); void wslay_queue_pop(struct wslay_queue *queue); -void* wslay_queue_top(struct wslay_queue *queue); -void* wslay_queue_tail(struct wslay_queue *queue); +struct wslay_queue_entry *wslay_queue_top(struct wslay_queue *queue); +struct wslay_queue_entry *wslay_queue_tail(struct wslay_queue *queue); int wslay_queue_empty(struct wslay_queue *queue); #endif /* WSLAY_QUEUE_H */ diff --git a/deps/wslay/tests/main.c b/deps/wslay/tests/main.c index 66a387c3..52429741 100644 --- a/deps/wslay/tests/main.c +++ b/deps/wslay/tests/main.c @@ -30,35 +30,27 @@ #include "wslay_event_test.h" #include "wslay_queue_test.h" -static int init_suite1(void) -{ - return 0; -} +static int init_suite1(void) { return 0; } -static int clean_suite1(void) -{ - return 0; -} +static int clean_suite1(void) { return 0; } +int main(void) { + CU_pSuite pSuite = NULL; + unsigned int num_tests_failed; -int main(void) -{ - CU_pSuite pSuite = NULL; - unsigned int num_tests_failed; + /* initialize the CUnit test registry */ + if (CUE_SUCCESS != CU_initialize_registry()) + return CU_get_error(); - /* initialize the CUnit test registry */ - if (CUE_SUCCESS != CU_initialize_registry()) - return CU_get_error(); + /* add a suite to the registry */ + pSuite = CU_add_suite("libwslay_TestSuite", init_suite1, clean_suite1); + if (NULL == pSuite) { + CU_cleanup_registry(); + return CU_get_error(); + } - /* add a suite to the registry */ - pSuite = CU_add_suite("libwslay_TestSuite", init_suite1, clean_suite1); - if (NULL == pSuite) { - CU_cleanup_registry(); - return CU_get_error(); - } - - /* add the tests to the suite */ - if(!CU_add_test(pSuite, "wslay_frame_context_init", + /* add the tests to the suite */ + if (!CU_add_test(pSuite, "wslay_frame_context_init", test_wslay_frame_context_init) || !CU_add_test(pSuite, "wslay_frame_recv", test_wslay_frame_recv) || !CU_add_test(pSuite, "wslay_frame_recv_1byte", @@ -90,8 +82,23 @@ int main(void) test_wslay_frame_send_too_large_payload) || !CU_add_test(pSuite, "wslay_frame_send_ctrl_frame_too_large_payload", test_wslay_frame_send_ctrl_frame_too_large_payload) || + !CU_add_test(pSuite, "wslay_frame_write", test_wslay_frame_write) || + !CU_add_test(pSuite, "wslay_frame_write_fragmented", + test_wslay_frame_write_fragmented) || + !CU_add_test(pSuite, "wslay_frame_write_interleaved_ctrl_frame", + test_wslay_frame_write_interleaved_ctrl_frame) || + !CU_add_test(pSuite, "wslay_frame_write_1byte_masked", + test_wslay_frame_write_1byte_masked) || + !CU_add_test(pSuite, "wslay_frame_write_zero_payloadlen", + test_wslay_frame_write_zero_payloadlen) || + !CU_add_test(pSuite, "wslay_frame_write_too_large_payload", + test_wslay_frame_write_too_large_payload) || + !CU_add_test(pSuite, "wslay_frame_write_ctrl_frame_too_large_payload", + test_wslay_frame_write_ctrl_frame_too_large_payload) || !CU_add_test(pSuite, "wslay_event_send_fragmented_msg", test_wslay_event_send_fragmented_msg) || + !CU_add_test(pSuite, "wslay_event_send_fragmented_msg_empty_data", + test_wslay_event_send_fragmented_msg_empty_data) || !CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_ctrl", test_wslay_event_send_fragmented_msg_with_ctrl) || !CU_add_test(pSuite, "wslay_event_send_fragmented_msg_with_rsv1", @@ -124,20 +131,32 @@ int main(void) test_wslay_event_message_too_big) || !CU_add_test(pSuite, "wslay_event_config_set_allowed_rsv_bits", test_wslay_event_config_set_allowed_rsv_bits) || + !CU_add_test(pSuite, "wslay_event_write_fragmented_msg", + test_wslay_event_write_fragmented_msg) || + !CU_add_test(pSuite, "wslay_event_write_fragmented_msg_empty_data", + test_wslay_event_write_fragmented_msg_empty_data) || + !CU_add_test(pSuite, "wslay_event_write_fragmented_msg_with_ctrl", + test_wslay_event_write_fragmented_msg_with_ctrl) || + !CU_add_test(pSuite, "wslay_event_write_fragmented_msg_with_rsv1", + test_wslay_event_write_fragmented_msg_with_rsv1) || + !CU_add_test(pSuite, "wslay_event_write_msg_with_rsv1", + test_wslay_event_write_msg_with_rsv1) || + !CU_add_test(pSuite, "wslay_event_write_ctrl_msg_first", + test_wslay_event_write_ctrl_msg_first) || !CU_add_test(pSuite, "wslay_queue", test_wslay_queue)) { - CU_cleanup_registry(); - return CU_get_error(); - } + CU_cleanup_registry(); + return CU_get_error(); + } - /* Run all tests using the CUnit Basic interface */ - CU_basic_set_mode(CU_BRM_VERBOSE); - CU_basic_run_tests(); - num_tests_failed = CU_get_number_of_tests_failed(); - CU_cleanup_registry(); - if (CU_get_error() == CUE_SUCCESS) { - return (int)num_tests_failed; - } else { - printf("CUnit Error: %s\n", CU_get_error_msg()); - return CU_get_error(); - } + /* Run all tests using the CUnit Basic interface */ + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + num_tests_failed = CU_get_number_of_tests_failed(); + CU_cleanup_registry(); + if (CU_get_error() == CUE_SUCCESS) { + return (int)num_tests_failed; + } else { + printf("CUnit Error: %s\n", CU_get_error_msg()); + return CU_get_error(); + } } diff --git a/deps/wslay/tests/wslay_event_test.c b/deps/wslay/tests/wslay_event_test.c index b023b89b..f3f2a465 100644 --- a/deps/wslay/tests/wslay_event_test.c +++ b/deps/wslay/tests/wslay_event_test.c @@ -32,8 +32,8 @@ struct scripted_data_feed { uint8_t data[8192]; - uint8_t* datamark; - uint8_t* datalimit; + uint8_t *datamark; + uint8_t *datalimit; size_t feedseq[8192]; size_t seqidx; }; @@ -49,44 +49,43 @@ struct my_user_data { }; static void scripted_data_feed_init(struct scripted_data_feed *df, - const uint8_t *data, size_t data_length) -{ + const uint8_t *data, size_t data_length) { memset(df, 0, sizeof(struct scripted_data_feed)); - memcpy(df->data, data, data_length); + if (data_length) { + memcpy(df->data, data, data_length); + } df->datamark = df->data; - df->datalimit = df->data+data_length; + df->datalimit = df->data + data_length; df->feedseq[0] = data_length; } -static ssize_t scripted_read_callback -(wslay_event_context_ptr ctx, - uint8_t *data, size_t len, const union wslay_event_msg_source *source, - int *eof, void *user_data) -{ - struct scripted_data_feed *df = (struct scripted_data_feed*)source->data; +static ssize_t +scripted_read_callback(wslay_event_context_ptr ctx, uint8_t *data, size_t len, + const union wslay_event_msg_source *source, int *eof, + void *user_data) { + struct scripted_data_feed *df = (struct scripted_data_feed *)source->data; size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx]; memcpy(data, df->datamark, wlen); df->datamark += wlen; - if(wlen <= len) { + if (wlen <= len) { ++df->seqidx; } else { df->feedseq[df->seqidx] -= wlen; } - if(df->datamark == df->datalimit) { + if (df->datamark == df->datalimit) { *eof = 1; } return wlen; } static ssize_t scripted_recv_callback(wslay_event_context_ptr ctx, - uint8_t* data, size_t len, int flags, - void *user_data) -{ - struct scripted_data_feed *df = ((struct my_user_data*)user_data)->df; + uint8_t *data, size_t len, int flags, + void *user_data) { + struct scripted_data_feed *df = ((struct my_user_data *)user_data)->df; size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx]; memcpy(data, df->datamark, wlen); df->datamark += wlen; - if(wlen <= len) { + if (wlen <= len) { ++df->seqidx; } else { df->feedseq[df->seqidx] -= wlen; @@ -96,45 +95,38 @@ static ssize_t scripted_recv_callback(wslay_event_context_ptr ctx, static ssize_t accumulator_send_callback(wslay_event_context_ptr ctx, const uint8_t *buf, size_t len, - int flags, void* user_data) -{ - struct accumulator *acc = ((struct my_user_data*)user_data)->acc; - assert(acc->length+len < sizeof(acc->buf)); - memcpy(acc->buf+acc->length, buf, len); + int flags, void *user_data) { + struct accumulator *acc = ((struct my_user_data *)user_data)->acc; + assert(acc->length + len < sizeof(acc->buf)); + memcpy(acc->buf + acc->length, buf, len); acc->length += len; return len; } static ssize_t one_accumulator_send_callback(wslay_event_context_ptr ctx, const uint8_t *buf, size_t len, - int flags, void* user_data) -{ - struct accumulator *acc = ((struct my_user_data*)user_data)->acc; + int flags, void *user_data) { + struct accumulator *acc = ((struct my_user_data *)user_data)->acc; assert(len > 0); - memcpy(acc->buf+acc->length, buf, 1); + memcpy(acc->buf + acc->length, buf, 1); acc->length += 1; return 1; } -static ssize_t fail_recv_callback(wslay_event_context_ptr ctx, - uint8_t* data, size_t len, int flags, - void *user_data) -{ +static ssize_t fail_recv_callback(wslay_event_context_ptr ctx, uint8_t *data, + size_t len, int flags, void *user_data) { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); return -1; } static ssize_t fail_send_callback(wslay_event_context_ptr ctx, const uint8_t *buf, size_t len, int flags, - void* user_data) -{ + void *user_data) { wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE); return -1; } - -void test_wslay_event_send_fragmented_msg(void) -{ +void test_wslay_event_send_fragmented_msg(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; @@ -142,11 +134,8 @@ void test_wslay_event_send_fragmented_msg(void) const char msg[] = "Hello"; struct scripted_data_feed df; struct wslay_event_fragmented_msg arg; - const uint8_t ans[] = { - 0x01, 0x03, 0x48, 0x65, 0x6c, - 0x80, 0x02, 0x6c, 0x6f - }; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)-1); + const uint8_t ans[] = {0x01, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f}; + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); df.feedseq[0] = 3; df.feedseq[1] = 2; memset(&callbacks, 0, sizeof(callbacks)); @@ -166,8 +155,33 @@ void test_wslay_event_send_fragmented_msg(void) wslay_event_context_free(ctx); } -void test_wslay_event_send_fragmented_msg_with_ctrl(void) -{ +void test_wslay_event_send_fragmented_msg_empty_data(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct my_user_data ud; + struct accumulator acc; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + const uint8_t ans[] = {0x81, 0x00}; + scripted_data_feed_init(&df, NULL, 0); + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = accumulator_send_callback; + memset(&acc, 0, sizeof(acc)); + ud.acc = &acc; + wslay_event_context_server_init(&ctx, &callbacks, &ud); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg)); + CU_ASSERT(0 == wslay_event_send(ctx)); + CU_ASSERT_EQUAL(2, acc.length); + CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length)); + wslay_event_context_free(ctx); +} + +void test_wslay_event_send_fragmented_msg_with_ctrl(void) { int i; wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; @@ -178,11 +192,11 @@ void test_wslay_event_send_fragmented_msg_with_ctrl(void) struct wslay_event_fragmented_msg arg; struct wslay_event_msg ctrl_arg; const uint8_t ans[] = { - 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ - 0x89, 0x00, /* unmasked ping */ - 0x80, 0x02, 0x6c, 0x6f /* "lo" */ + 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ + 0x89, 0x00, /* unmasked ping */ + 0x80, 0x02, 0x6c, 0x6f /* "lo" */ }; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)-1); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); df.feedseq[0] = 3; df.feedseq[1] = 2; memset(&callbacks, 0, sizeof(callbacks)); @@ -205,7 +219,7 @@ void test_wslay_event_send_fragmented_msg_with_ctrl(void) ctrl_arg.msg_length = 0; CU_ASSERT(0 == wslay_event_queue_msg(ctx, &ctrl_arg)); CU_ASSERT(2 == wslay_event_get_queued_msg_count(ctx)); - for(i = 0; i < 10; ++i) { + for (i = 0; i < 10; ++i) { CU_ASSERT(0 == wslay_event_send(ctx)); } CU_ASSERT(0 == wslay_event_get_queued_msg_count(ctx)); @@ -214,8 +228,7 @@ void test_wslay_event_send_fragmented_msg_with_ctrl(void) wslay_event_context_free(ctx); } -void test_wslay_event_send_fragmented_msg_with_rsv1(void) -{ +void test_wslay_event_send_fragmented_msg_with_rsv1(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; @@ -223,11 +236,8 @@ void test_wslay_event_send_fragmented_msg_with_rsv1(void) const char msg[] = "Hello"; struct scripted_data_feed df; struct wslay_event_fragmented_msg arg; - const uint8_t ans[] = { - 0x41, 0x03, 0x48, 0x65, 0x6c, - 0x80, 0x02, 0x6c, 0x6f - }; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)-1); + const uint8_t ans[] = {0x41, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f}; + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); df.feedseq[0] = 3; df.feedseq[1] = 2; memset(&callbacks, 0, sizeof(callbacks)); @@ -249,8 +259,7 @@ void test_wslay_event_send_fragmented_msg_with_rsv1(void) wslay_event_context_free(ctx); } -void test_wslay_event_send_msg_with_rsv1(void) -{ +void test_wslay_event_send_msg_with_rsv1(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; @@ -258,7 +267,7 @@ void test_wslay_event_send_msg_with_rsv1(void) const char msg[] = "Hello"; struct wslay_event_msg arg; const uint8_t ans[] = { - 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; memset(&callbacks, 0, sizeof(callbacks)); @@ -270,7 +279,7 @@ void test_wslay_event_send_msg_with_rsv1(void) memset(&arg, 0, sizeof(arg)); arg.opcode = WSLAY_TEXT_FRAME; - arg.msg = (const uint8_t*)msg; + arg.msg = (const uint8_t *)msg; arg.msg_length = 5; CU_ASSERT(0 == wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); CU_ASSERT(0 == wslay_event_send(ctx)); @@ -279,8 +288,7 @@ void test_wslay_event_send_msg_with_rsv1(void) wslay_event_context_free(ctx); } -void test_wslay_event_send_ctrl_msg_first(void) -{ +void test_wslay_event_send_ctrl_msg_first(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; @@ -288,8 +296,8 @@ void test_wslay_event_send_ctrl_msg_first(void) const char msg[] = "Hello"; struct wslay_event_msg arg; const uint8_t ans[] = { - 0x89, 0x00, /* unmasked ping */ - 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + 0x89, 0x00, /* unmasked ping */ + 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; @@ -302,7 +310,7 @@ void test_wslay_event_send_ctrl_msg_first(void) arg.msg_length = 0; CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg)); arg.opcode = WSLAY_TEXT_FRAME; - arg.msg = (const uint8_t*)msg; + arg.msg = (const uint8_t *)msg; arg.msg_length = 5; CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg)); CU_ASSERT(0 == wslay_event_send(ctx)); @@ -311,8 +319,7 @@ void test_wslay_event_send_ctrl_msg_first(void) wslay_event_context_free(ctx); } -void test_wslay_event_send_ctrl_msg_with_rsv1(void) -{ +void test_wslay_event_send_ctrl_msg_with_rsv1(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct wslay_event_msg arg; @@ -331,15 +338,14 @@ void test_wslay_event_send_ctrl_msg_with_rsv1(void) wslay_event_context_free(ctx); } -void test_wslay_event_queue_close(void) -{ +void test_wslay_event_queue_close(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; struct accumulator acc; const char msg[] = "H"; const uint8_t ans[] = { - 0x88, 0x03, 0x03, 0xf1, 0x48 /* "H" */ + 0x88, 0x03, 0x03, 0xf1, 0x48 /* "H" */ }; memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; @@ -347,7 +353,7 @@ void test_wslay_event_queue_close(void) ud.acc = &acc; wslay_event_context_server_init(&ctx, &callbacks, &ud); CU_ASSERT(0 == wslay_event_queue_close(ctx, WSLAY_CODE_MESSAGE_TOO_BIG, - (const uint8_t*)msg, 1)); + (const uint8_t *)msg, 1)); CU_ASSERT(0 == wslay_event_send(ctx)); CU_ASSERT(5 == acc.length); CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length)); @@ -355,14 +361,13 @@ void test_wslay_event_queue_close(void) wslay_event_context_free(ctx); } -void test_wslay_event_queue_close_without_code(void) -{ +void test_wslay_event_queue_close_without_code(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; struct accumulator acc; - const uint8_t ans[] = { 0x88, 0x00 }; - struct wslay_event_msg ping = { WSLAY_PING, NULL, 0 }; + const uint8_t ans[] = {0x88, 0x00}; + struct wslay_event_msg ping = {WSLAY_PING, NULL, 0}; memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; memset(&acc, 0, sizeof(acc)); @@ -375,19 +380,17 @@ void test_wslay_event_queue_close_without_code(void) CU_ASSERT(2 == acc.length); CU_ASSERT(0 == memcmp(ans, acc.buf, acc.length)); CU_ASSERT(1 == wslay_event_get_close_sent(ctx)); - CU_ASSERT(WSLAY_CODE_NO_STATUS_RCVD == - wslay_event_get_status_code_sent(ctx)); + CU_ASSERT(WSLAY_CODE_NO_STATUS_RCVD == wslay_event_get_status_code_sent(ctx)); wslay_event_context_free(ctx); } -void test_wslay_event_recv_close_without_code(void) -{ +void test_wslay_event_recv_close_without_code(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; - const uint8_t msg[] = { 0x88u, 0x00 }; + const uint8_t msg[] = {0x88u, 0x00}; struct scripted_data_feed df; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); callbacks.recv_callback = scripted_recv_callback; ud.df = &df; @@ -399,23 +402,22 @@ void test_wslay_event_recv_close_without_code(void) wslay_event_context_free(ctx); } -void test_wslay_event_reply_close(void) -{ +void test_wslay_event_reply_close(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; struct accumulator acc; /* Masked close frame with code = 1009, reason = "Hello" */ - const uint8_t msg[] = { 0x88u, 0x87u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x03, 0xf1, /* 1009 */ - 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + const uint8_t msg[] = { + 0x88u, 0x87u, 0x00u, 0x00u, 0x00u, 0x00u, 0x03, 0xf1, /* 1009 */ + 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; - const uint8_t ans[] = { 0x88u, 0x07u, - 0x03, 0xf1, /* 1009 */ - 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + const uint8_t ans[] = { + 0x88u, 0x07u, 0x03, 0xf1, /* 1009 */ + 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; struct scripted_data_feed df; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; callbacks.recv_callback = scripted_recv_callback; @@ -445,8 +447,7 @@ void test_wslay_event_reply_close(void) wslay_event_context_free(ctx); } -void test_wslay_event_no_more_msg(void) -{ +void test_wslay_event_no_more_msg(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); @@ -456,8 +457,7 @@ void test_wslay_event_no_more_msg(void) wslay_event_context_free(ctx); } -void test_wslay_event_callback_failure(void) -{ +void test_wslay_event_callback_failure(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); @@ -472,9 +472,8 @@ void test_wslay_event_callback_failure(void) static void no_buffering_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ - if(arg->opcode == WSLAY_PING) { + void *user_data) { + if (arg->opcode == WSLAY_PING) { CU_ASSERT(3 == arg->msg_length); CU_ASSERT(0 == memcmp("Foo", arg->msg, arg->msg_length)); } else { @@ -483,18 +482,17 @@ static void no_buffering_callback(wslay_event_context_ptr ctx, } } -void test_wslay_event_no_buffering(void) -{ +void test_wslay_event_no_buffering(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; const uint8_t msg[] = { - 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ - 0x89, 0x03, 0x46, 0x6f, 0x6f, /* ping with "Foo" */ - 0x80, 0x02, 0x6c, 0x6f, /* "lo" */ + 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ + 0x89, 0x03, 0x46, 0x6f, 0x6f, /* ping with "Foo" */ + 0x80, 0x02, 0x6c, 0x6f, /* "lo" */ }; struct scripted_data_feed df; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); ud.df = &df; callbacks.recv_callback = scripted_recv_callback; @@ -510,35 +508,33 @@ void test_wslay_event_no_buffering(void) static void text_rsv1_on_msg_recv_callback(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, - void *user_data) -{ + void *user_data) { CU_ASSERT(WSLAY_TEXT_FRAME == arg->opcode); CU_ASSERT(WSLAY_RSV1_BIT == arg->rsv); } -void test_wslay_event_recv_text_frame_with_rsv1(void) -{ +void test_wslay_event_recv_text_frame_with_rsv1(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; const uint8_t msg[] = { - 0xc1, 0x07, 0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00 // "Hello" pm-deflate + 0xc1, 0x07, 0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00 // "Hello" pm-deflate }; const uint8_t fragmented[] = { - 0x41, 0x03, 0xf2, 0x48, 0xcd, // First fragment - 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00 // Second fragment, RSV1 bit off + 0x41, 0x03, 0xf2, 0x48, 0xcd, // First fragment + 0x80, 0x04, 0xc9, 0xc9, 0x07, 0x00 // Second fragment, RSV1 bit off }; const uint8_t bad_fragment[] = { - 0x41, 0x03, 0xf2, 0x48, 0xcd, - 0xc0, 0x04, 0xc9, 0xc9, 0x07, 0x00 // RSV1 bit on + 0x41, 0x03, 0xf2, 0x48, 0xcd, 0xc0, + 0x04, 0xc9, 0xc9, 0x07, 0x00 // RSV1 bit on }; const uint8_t pingmsg[] = { - 0xc9, 0x03, 0x46, 0x6f, 0x6f /* ping with "Foo" */ + 0xc9, 0x03, 0x46, 0x6f, 0x6f /* ping with "Foo" */ }; struct scripted_data_feed df; /* Message marked with RSV1 should skip UTF-8 validation */ - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); ud.df = &df; callbacks.recv_callback = scripted_recv_callback; @@ -551,7 +547,7 @@ void test_wslay_event_recv_text_frame_with_rsv1(void) /* UTF-8 validation is skipped for continuation frames if the * initial frame was marked with RSV1 bit */ - scripted_data_feed_init(&df, (const uint8_t*)fragmented, sizeof(fragmented)); + scripted_data_feed_init(&df, (const uint8_t *)fragmented, sizeof(fragmented)); memset(&callbacks, 0, sizeof(callbacks)); ud.df = &df; callbacks.recv_callback = scripted_recv_callback; @@ -563,7 +559,7 @@ void test_wslay_event_recv_text_frame_with_rsv1(void) wslay_event_context_free(ctx); /* disallow RSV1 */ - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); wslay_event_context_client_init(&ctx, &callbacks, &ud); CU_ASSERT(0 == wslay_event_recv(ctx)); /* Close frame must be queued */ @@ -571,8 +567,8 @@ void test_wslay_event_recv_text_frame_with_rsv1(void) wslay_event_context_free(ctx); /* RSV1 is not allowed in continuation frame */ - scripted_data_feed_init(&df, (const uint8_t*)bad_fragment, - sizeof(bad_fragment)); + scripted_data_feed_init(&df, (const uint8_t *)bad_fragment, + sizeof(bad_fragment)); wslay_event_context_client_init(&ctx, &callbacks, &ud); wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); CU_ASSERT(0 == wslay_event_recv(ctx)); @@ -581,7 +577,7 @@ void test_wslay_event_recv_text_frame_with_rsv1(void) wslay_event_context_free(ctx); /* RSV1 is not allowed in ping frame */ - scripted_data_feed_init(&df, (const uint8_t*)pingmsg, sizeof(pingmsg)); + scripted_data_feed_init(&df, (const uint8_t *)pingmsg, sizeof(pingmsg)); wslay_event_context_client_init(&ctx, &callbacks, &ud); wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); CU_ASSERT(0 == wslay_event_recv(ctx)); @@ -590,21 +586,21 @@ void test_wslay_event_recv_text_frame_with_rsv1(void) wslay_event_context_free(ctx); } -void test_wslay_event_frame_too_big(void) -{ +void test_wslay_event_frame_too_big(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; struct accumulator acc; /* Masked text frame */ - const uint8_t msg[] = { 0x81, 0x85, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + const uint8_t msg[] = { + 0x81, 0x85, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; - const uint8_t ans[] = { 0x88, 0x02, - 0x03, 0xf1 /* 1009 */ + const uint8_t ans[] = { + 0x88, 0x02, 0x03, 0xf1 /* 1009 */ }; struct scripted_data_feed df; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; callbacks.recv_callback = scripted_recv_callback; @@ -623,23 +619,23 @@ void test_wslay_event_frame_too_big(void) wslay_event_context_free(ctx); } -void test_wslay_event_message_too_big(void) -{ +void test_wslay_event_message_too_big(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; struct my_user_data ud; struct accumulator acc; /* Masked text 2 frames */ - const uint8_t msg[] = { 0x01, 0x85, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, /* "Hello" */ - 0x80, 0x85, 0x00, 0x00, 0x00, 0x00, - 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + const uint8_t msg[] = { + 0x01, 0x85, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, /* "Hello" */ + 0x80, 0x85, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ }; - const uint8_t ans[] = { 0x88, 0x02, - 0x03, 0xf1 /* 1009 */ + const uint8_t ans[] = { + 0x88, 0x02, 0x03, 0xf1 /* 1009 */ }; struct scripted_data_feed df; - scripted_data_feed_init(&df, (const uint8_t*)msg, sizeof(msg)); + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg)); memset(&callbacks, 0, sizeof(callbacks)); callbacks.send_callback = accumulator_send_callback; callbacks.recv_callback = scripted_recv_callback; @@ -658,8 +654,7 @@ void test_wslay_event_message_too_big(void) wslay_event_context_free(ctx); } -void test_wslay_event_config_set_allowed_rsv_bits(void) -{ +void test_wslay_event_config_set_allowed_rsv_bits(void) { wslay_event_context_ptr ctx; struct wslay_event_callbacks callbacks; @@ -683,3 +678,164 @@ void test_wslay_event_config_set_allowed_rsv_bits(void) wslay_event_context_free(ctx); } + +void test_wslay_event_write_fragmented_msg(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + const char msg[] = "Hello"; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + const uint8_t ans[] = {0x01, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f}; + uint8_t buf[1024]; + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); + df.feedseq[0] = 3; + df.feedseq[1] = 2; + memset(&callbacks, 0, sizeof(callbacks)); + wslay_event_context_server_init(&ctx, &callbacks, NULL); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg)); + CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf))); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} + +void test_wslay_event_write_fragmented_msg_empty_data(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + const uint8_t ans[] = {0x81, 0x00}; + uint8_t buf[1024]; + scripted_data_feed_init(&df, NULL, 0); + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = accumulator_send_callback; + wslay_event_context_server_init(&ctx, &callbacks, NULL); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg)); + CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf))); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} + +void test_wslay_event_write_fragmented_msg_with_ctrl(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + const char msg[] = "Hello"; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + struct wslay_event_msg ctrl_arg; + const uint8_t ans[] = { + 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ + 0x89, 0x00, /* unmasked ping */ + 0x80, 0x02, 0x6c, 0x6f /* "lo" */ + }; + uint8_t buf[1024]; + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); + df.feedseq[0] = 3; + df.feedseq[1] = 2; + memset(&callbacks, 0, sizeof(callbacks)); + wslay_event_context_server_init(&ctx, &callbacks, NULL); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == wslay_event_queue_fragmented_msg(ctx, &arg)); + CU_ASSERT(1 == wslay_event_get_queued_msg_count(ctx)); + CU_ASSERT(0 == wslay_event_get_queued_msg_length(ctx)); + CU_ASSERT(4 == wslay_event_write(ctx, buf, 4)); + + memset(&ctrl_arg, 0, sizeof(ctrl_arg)); + ctrl_arg.opcode = WSLAY_PING; + ctrl_arg.msg_length = 0; + CU_ASSERT(0 == wslay_event_queue_msg(ctx, &ctrl_arg)); + CU_ASSERT(2 == wslay_event_get_queued_msg_count(ctx)); + CU_ASSERT(7 == wslay_event_write(ctx, buf + 4, sizeof(buf) - 4)); + CU_ASSERT(0 == wslay_event_get_queued_msg_count(ctx)); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} + +void test_wslay_event_write_fragmented_msg_with_rsv1(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + const char msg[] = "Hello"; + struct scripted_data_feed df; + struct wslay_event_fragmented_msg arg; + const uint8_t ans[] = {0x41, 0x03, 0x48, 0x65, 0x6c, 0x80, 0x02, 0x6c, 0x6f}; + uint8_t buf[1024]; + scripted_data_feed_init(&df, (const uint8_t *)msg, sizeof(msg) - 1); + df.feedseq[0] = 3; + df.feedseq[1] = 2; + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.send_callback = accumulator_send_callback; + wslay_event_context_server_init(&ctx, &callbacks, NULL); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.source.data = &df; + arg.read_callback = scripted_read_callback; + CU_ASSERT(0 == + wslay_event_queue_fragmented_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); + CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf))); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} + +void test_wslay_event_write_msg_with_rsv1(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + const char msg[] = "Hello"; + struct wslay_event_msg arg; + const uint8_t ans[] = { + 0xc1, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + }; + uint8_t buf[1024]; + memset(&callbacks, 0, sizeof(callbacks)); + wslay_event_context_server_init(&ctx, &callbacks, NULL); + wslay_event_config_set_allowed_rsv_bits(ctx, WSLAY_RSV1_BIT); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.msg = (const uint8_t *)msg; + arg.msg_length = 5; + CU_ASSERT(0 == wslay_event_queue_msg_ex(ctx, &arg, WSLAY_RSV1_BIT)); + CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf))); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} + +void test_wslay_event_write_ctrl_msg_first(void) { + wslay_event_context_ptr ctx; + struct wslay_event_callbacks callbacks; + const char msg[] = "Hello"; + struct wslay_event_msg arg; + const uint8_t ans[] = { + 0x89, 0x00, /* unmasked ping */ + 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f /* "Hello" */ + }; + uint8_t buf[1024]; + memset(&callbacks, 0, sizeof(callbacks)); + wslay_event_context_server_init(&ctx, &callbacks, NULL); + + memset(&arg, 0, sizeof(arg)); + arg.opcode = WSLAY_PING; + arg.msg_length = 0; + CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg)); + arg.opcode = WSLAY_TEXT_FRAME; + arg.msg = (const uint8_t *)msg; + arg.msg_length = 5; + CU_ASSERT(0 == wslay_event_queue_msg(ctx, &arg)); + CU_ASSERT(sizeof(ans) == wslay_event_write(ctx, buf, sizeof(buf))); + CU_ASSERT(0 == memcmp(ans, buf, sizeof(ans))); + wslay_event_context_free(ctx); +} diff --git a/deps/wslay/tests/wslay_event_test.h b/deps/wslay/tests/wslay_event_test.h index 834be263..58dc0690 100644 --- a/deps/wslay/tests/wslay_event_test.h +++ b/deps/wslay/tests/wslay_event_test.h @@ -26,6 +26,7 @@ #define WSLAY_EVENT_TEST_H void test_wslay_event_send_fragmented_msg(void); +void test_wslay_event_send_fragmented_msg_empty_data(void); void test_wslay_event_send_fragmented_msg_with_ctrl(void); void test_wslay_event_send_fragmented_msg_with_rsv1(void); void test_wslay_event_send_msg_with_rsv1(void); @@ -42,5 +43,11 @@ void test_wslay_event_recv_text_frame_with_rsv1(void); void test_wslay_event_frame_too_big(void); void test_wslay_event_message_too_big(void); void test_wslay_event_config_set_allowed_rsv_bits(void); +void test_wslay_event_write_fragmented_msg(void); +void test_wslay_event_write_fragmented_msg_empty_data(void); +void test_wslay_event_write_fragmented_msg_with_ctrl(void); +void test_wslay_event_write_fragmented_msg_with_rsv1(void); +void test_wslay_event_write_msg_with_rsv1(void); +void test_wslay_event_write_ctrl_msg_first(void); #endif /* WSLAY_EVENT_TEST_H */ diff --git a/deps/wslay/tests/wslay_frame_test.c b/deps/wslay/tests/wslay_frame_test.c index 9ad3d305..2b50e73b 100644 --- a/deps/wslay/tests/wslay_frame_test.c +++ b/deps/wslay/tests/wslay_frame_test.c @@ -30,8 +30,7 @@ #include "wslay_frame.h" -void test_wslay_frame_context_init(void) -{ +void test_wslay_frame_context_init(void) { wslay_frame_context_ptr ctx; struct wslay_frame_callbacks callbacks; int user_data; @@ -42,30 +41,30 @@ void test_wslay_frame_context_init(void) struct scripted_data_feed { uint8_t data[8192]; - uint8_t* datamark; - uint8_t* datalimit; + uint8_t *datamark; + uint8_t *datalimit; size_t feedseq[8192]; size_t seqidx; }; static void scripted_data_feed_init(struct scripted_data_feed *df, - uint8_t *data, size_t data_length) -{ + uint8_t *data, size_t data_length) { memset(df, 0, sizeof(struct scripted_data_feed)); - memcpy(df->data, data, data_length); + if (data_length) { + memcpy(df->data, data, data_length); + } df->datamark = df->data; - df->datalimit = df->data+data_length; + df->datalimit = df->data + data_length; df->feedseq[0] = data_length; } -static ssize_t scripted_recv_callback(uint8_t* data, size_t len, int flags, - void *user_data) -{ - struct scripted_data_feed *df = (struct scripted_data_feed*)user_data; +static ssize_t scripted_recv_callback(uint8_t *data, size_t len, int flags, + void *user_data) { + struct scripted_data_feed *df = (struct scripted_data_feed *)user_data; size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx]; memcpy(data, df->datamark, wlen); df->datamark += wlen; - if(wlen <= len) { + if (wlen <= len) { ++df->seqidx; } else { df->feedseq[df->seqidx] -= wlen; @@ -73,14 +72,13 @@ static ssize_t scripted_recv_callback(uint8_t* data, size_t len, int flags, return wlen; } -static ssize_t scripted_send_callback(const uint8_t* data, size_t len, - int flags, void *user_data) -{ - struct scripted_data_feed *df = (struct scripted_data_feed*)user_data; +static ssize_t scripted_send_callback(const uint8_t *data, size_t len, + int flags, void *user_data) { + struct scripted_data_feed *df = (struct scripted_data_feed *)user_data; size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx]; memcpy(df->datamark, data, wlen); df->datamark += wlen; - if(wlen <= len) { + if (wlen <= len) { ++df->seqidx; } else { df->feedseq[df->seqidx] -= wlen; @@ -88,17 +86,14 @@ static ssize_t scripted_send_callback(const uint8_t* data, size_t len, return wlen; } -void test_wslay_frame_recv(void) -{ +void test_wslay_frame_recv(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; /* Masked text frame containing "Hello" */ - uint8_t msg[] = { 0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, 0x7fu, 0x9fu, - 0x4du, 0x51u, 0x58u }; + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; scripted_data_feed_init(&df, msg, sizeof(msg)); wslay_frame_context_init(&ctx, &callbacks, &df); @@ -114,28 +109,25 @@ void test_wslay_frame_recv(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_1byte(void) -{ +void test_wslay_frame_recv_1byte(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; size_t i; /* Masked text frame containing "Hello" */ - uint8_t msg[] = { 0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, 0x7fu, 0x9fu, - 0x4du, 0x51u, 0x58u }; + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; scripted_data_feed_init(&df, msg, sizeof(msg)); - for(i = 0; i < sizeof(msg); ++i) { + for (i = 0; i < sizeof(msg); ++i) { df.feedseq[i] = 1; } wslay_frame_context_init(&ctx, &callbacks, &df); - for(i = 0; i < 4; ++i) { + for (i = 0; i < 4; ++i) { CU_ASSERT(WSLAY_ERR_WANT_READ == wslay_frame_recv(ctx, &iocb)); } - for(i = 0; i < 5; ++i) { + for (i = 0; i < 5; ++i) { CU_ASSERT(1 == wslay_frame_recv(ctx, &iocb)); CU_ASSERT_EQUAL(1, iocb.fin); CU_ASSERT_EQUAL(0, iocb.rsv); @@ -143,24 +135,21 @@ void test_wslay_frame_recv_1byte(void) CU_ASSERT_EQUAL(5, iocb.payload_length); CU_ASSERT_EQUAL(1, iocb.mask); CU_ASSERT_EQUAL(1, iocb.data_length); - CU_ASSERT_EQUAL(msg[6+i]^msg[2+i%4], iocb.data[0]); + CU_ASSERT_EQUAL(msg[6 + i] ^ msg[2 + i % 4], iocb.data[0]); } CU_ASSERT(WSLAY_ERR_WANT_READ == wslay_frame_recv(ctx, &iocb)); wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_fragmented(void) -{ +void test_wslay_frame_recv_fragmented(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; /* Unmasked message */ - uint8_t msg[] = { 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ - 0x80, 0x02, 0x6c, 0x6f }; /* "lo" */ + uint8_t msg[] = {0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ + 0x80, 0x02, 0x6c, 0x6f}; /* "lo" */ scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = 5; df.feedseq[1] = 4; @@ -187,23 +176,19 @@ void test_wslay_frame_recv_fragmented(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_interleaved_ctrl_frame(void) -{ +void test_wslay_frame_recv_interleaved_ctrl_frame(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; /* Unmasked message */ - uint8_t msg[] = { 0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ - /* ping with "Hello" */ - 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, - 0x80, 0x02, 0x6c, 0x6f }; /* "lo" */ + uint8_t msg[] = {0x01, 0x03, 0x48, 0x65, 0x6c, /* "Hel" */ + /* ping with "Hello" */ + 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80, 0x02, 0x6c, + 0x6f}; /* "lo" */ scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = 5; - df.feedseq[1] = 7, - df.feedseq[2] = 4; + df.feedseq[1] = 7, df.feedseq[2] = 4; wslay_frame_context_init(&ctx, &callbacks, &df); CU_ASSERT(3 == wslay_frame_recv(ctx, &iocb)); @@ -236,16 +221,13 @@ void test_wslay_frame_recv_interleaved_ctrl_frame(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_zero_payloadlen(void) -{ +void test_wslay_frame_recv_zero_payloadlen(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; /* Unmasked message */ - uint8_t msg[] = { 0x81, 0x00 }; /* "" */ + uint8_t msg[] = {0x81, 0x00}; /* "" */ scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = 2; wslay_frame_context_init(&ctx, &callbacks, &df); @@ -261,15 +243,12 @@ void test_wslay_frame_recv_zero_payloadlen(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_too_large_payload(void) -{ +void test_wslay_frame_recv_too_large_payload(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; - uint8_t msg[] = { 0x81, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + uint8_t msg[] = {0x81, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = sizeof(msg); wslay_frame_context_init(&ctx, &callbacks, &df); @@ -278,15 +257,12 @@ void test_wslay_frame_recv_too_large_payload(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_ctrl_frame_too_large_payload(void) -{ +void test_wslay_frame_recv_ctrl_frame_too_large_payload(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; - uint8_t msg[] = { 0x88, 0x7e }; + uint8_t msg[] = {0x88, 0x7e}; scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = sizeof(msg); wslay_frame_context_init(&ctx, &callbacks, &df); @@ -295,15 +271,12 @@ void test_wslay_frame_recv_ctrl_frame_too_large_payload(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_minimum_ext_payload16(void) -{ +void test_wslay_frame_recv_minimum_ext_payload16(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; - uint8_t msg[] = { 0x81, 0x7e, 0x00, 0x7d }; + uint8_t msg[] = {0x81, 0x7e, 0x00, 0x7d}; scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = sizeof(msg); wslay_frame_context_init(&ctx, &callbacks, &df); @@ -312,15 +285,12 @@ void test_wslay_frame_recv_minimum_ext_payload16(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_recv_minimum_ext_payload64(void) -{ +void test_wslay_frame_recv_minimum_ext_payload64(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { NULL, - scripted_recv_callback, - NULL }; + struct wslay_frame_callbacks callbacks = {NULL, scripted_recv_callback, NULL}; struct scripted_data_feed df; struct wslay_frame_iocb iocb; - uint8_t msg[] = { 0x81, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}; + uint8_t msg[] = {0x81, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}; scripted_data_feed_init(&df, msg, sizeof(msg)); df.feedseq[0] = sizeof(msg); wslay_frame_context_init(&ctx, &callbacks, &df); @@ -335,34 +305,29 @@ struct accumulator { }; static ssize_t accumulator_send_callback(const uint8_t *buf, size_t len, - int flags, void* user_data) -{ - struct accumulator *acc = (struct accumulator*)user_data; - assert(acc->length+len < sizeof(acc->buf)); - memcpy(acc->buf+acc->length, buf, len); + int flags, void *user_data) { + struct accumulator *acc = (struct accumulator *)user_data; + assert(acc->length + len < sizeof(acc->buf)); + memcpy(acc->buf + acc->length, buf, len); acc->length += len; return len; } -static int static_genmask_callback(uint8_t *buf, size_t len, - void* user_data) -{ - static const uint8_t makskey[] = { 0x37u, 0xfau, 0x21u, 0x3du }; +static int static_genmask_callback(uint8_t *buf, size_t len, void *user_data) { + static const uint8_t makskey[] = {0x37u, 0xfau, 0x21u, 0x3du}; memcpy(buf, makskey, 4); return 0; } -void test_wslay_frame_send(void) -{ +void test_wslay_frame_send(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { accumulator_send_callback, - NULL, - static_genmask_callback }; + struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL, + static_genmask_callback}; struct accumulator acc; struct wslay_frame_iocb iocb; /* Masked text frame containing "Hello" */ - uint8_t msg[] = { 0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, 0x7fu, 0x9fu, - 0x4du, 0x51u, 0x58u }; + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; wslay_frame_context_init(&ctx, &callbacks, &acc); memset(&iocb, 0, sizeof(iocb)); acc.length = 0; @@ -370,7 +335,7 @@ void test_wslay_frame_send(void) iocb.opcode = WSLAY_TEXT_FRAME; iocb.mask = 1; iocb.payload_length = 5; - iocb.data = (const uint8_t*)"Hello"; + iocb.data = (const uint8_t *)"Hello"; iocb.data_length = 5; CU_ASSERT(5 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg), acc.length); @@ -379,17 +344,15 @@ void test_wslay_frame_send(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_send_fragmented(void) -{ +void test_wslay_frame_send_fragmented(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { accumulator_send_callback, - NULL, - static_genmask_callback }; + struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL, + static_genmask_callback}; struct accumulator acc; struct wslay_frame_iocb iocb; /* Unmasked message */ - uint8_t msg1[] = { 0x01, 0x03, 0x48, 0x65, 0x6c }; /* "Hel" */ - uint8_t msg2[] = { 0x80, 0x02, 0x6c, 0x6f }; /* "lo" */ + uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; /* "Hel" */ + uint8_t msg2[] = {0x80, 0x02, 0x6c, 0x6f}; /* "lo" */ wslay_frame_context_init(&ctx, &callbacks, &acc); memset(&iocb, 0, sizeof(iocb)); acc.length = 0; @@ -397,7 +360,7 @@ void test_wslay_frame_send_fragmented(void) iocb.opcode = WSLAY_TEXT_FRAME; iocb.mask = 0; iocb.payload_length = 3; - iocb.data = (const uint8_t*)"Hel"; + iocb.data = (const uint8_t *)"Hel"; iocb.data_length = 3; CU_ASSERT(3 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg1), acc.length); @@ -407,7 +370,7 @@ void test_wslay_frame_send_fragmented(void) iocb.fin = 1; iocb.opcode = WSLAY_CONTINUATION_FRAME; iocb.payload_length = 2; - iocb.data = (const uint8_t*)"lo"; + iocb.data = (const uint8_t *)"lo"; iocb.data_length = 2; CU_ASSERT(2 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg2), acc.length); @@ -416,21 +379,19 @@ void test_wslay_frame_send_fragmented(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_send_interleaved_ctrl_frame(void) -{ +void test_wslay_frame_send_interleaved_ctrl_frame(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { accumulator_send_callback, - NULL, - static_genmask_callback }; + struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL, + static_genmask_callback}; struct accumulator acc; struct wslay_frame_iocb iocb; /* Unmasked message */ /* text with "Hel", with fin = 0 */ - uint8_t msg1[] = { 0x01, 0x03, 0x48, 0x65, 0x6c }; + uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; /* ping with "Hello" */ - uint8_t msg2[] = { 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f }; + uint8_t msg2[] = {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f}; /* text with "lo", continuation frame for msg1, with fin = 1 */ - uint8_t msg3[] = { 0x80, 0x02, 0x6c, 0x6f }; + uint8_t msg3[] = {0x80, 0x02, 0x6c, 0x6f}; wslay_frame_context_init(&ctx, &callbacks, &acc); memset(&iocb, 0, sizeof(iocb)); acc.length = 0; @@ -438,7 +399,7 @@ void test_wslay_frame_send_interleaved_ctrl_frame(void) iocb.opcode = WSLAY_TEXT_FRAME; iocb.mask = 0; iocb.payload_length = 3; - iocb.data = (const uint8_t*)"Hel"; + iocb.data = (const uint8_t *)"Hel"; iocb.data_length = 3; CU_ASSERT(3 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg1), acc.length); @@ -448,7 +409,7 @@ void test_wslay_frame_send_interleaved_ctrl_frame(void) iocb.fin = 1; iocb.opcode = WSLAY_PING; iocb.payload_length = 5; - iocb.data = (const uint8_t*)"Hello"; + iocb.data = (const uint8_t *)"Hello"; iocb.data_length = 5; CU_ASSERT(5 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg2), acc.length); @@ -458,7 +419,7 @@ void test_wslay_frame_send_interleaved_ctrl_frame(void) iocb.fin = 1; iocb.opcode = WSLAY_CONTINUATION_FRAME; iocb.payload_length = 2; - iocb.data = (const uint8_t*)"lo"; + iocb.data = (const uint8_t *)"lo"; iocb.data_length = 2; CU_ASSERT(2 == wslay_frame_send(ctx, &iocb)); CU_ASSERT_EQUAL(sizeof(msg3), acc.length); @@ -467,21 +428,19 @@ void test_wslay_frame_send_interleaved_ctrl_frame(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_send_1byte_masked(void) -{ +void test_wslay_frame_send_1byte_masked(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { scripted_send_callback, - NULL, - static_genmask_callback }; + struct wslay_frame_callbacks callbacks = {scripted_send_callback, NULL, + static_genmask_callback}; struct wslay_frame_iocb iocb; /* Masked text frame containing "Hello" */ - uint8_t msg[] = { 0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, 0x7fu, 0x9fu, - 0x4du, 0x51u, 0x58u }; + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; uint8_t hello[] = "Hello"; struct scripted_data_feed df; size_t i; scripted_data_feed_init(&df, NULL, 0); - for(i = 0; i < sizeof(msg); ++i) { + for (i = 0; i < sizeof(msg); ++i) { df.feedseq[i] = 1; } wslay_frame_context_init(&ctx, &callbacks, &df); @@ -491,8 +450,8 @@ void test_wslay_frame_send_1byte_masked(void) iocb.mask = 1; iocb.payload_length = 5; iocb.data = hello; - iocb.data_length = sizeof(hello)-1; - for(i = 0; i < 5; ++i) { + iocb.data_length = sizeof(hello) - 1; + for (i = 0; i < 5; ++i) { CU_ASSERT_EQUAL(WSLAY_ERR_WANT_WRITE, wslay_frame_send(ctx, &iocb)); } CU_ASSERT_EQUAL(5, wslay_frame_send(ctx, &iocb)); @@ -500,16 +459,14 @@ void test_wslay_frame_send_1byte_masked(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_send_zero_payloadlen(void) -{ +void test_wslay_frame_send_zero_payloadlen(void) { wslay_frame_context_ptr ctx; - struct wslay_frame_callbacks callbacks = { accumulator_send_callback, - NULL, - static_genmask_callback }; + struct wslay_frame_callbacks callbacks = {accumulator_send_callback, NULL, + static_genmask_callback}; struct accumulator acc; struct wslay_frame_iocb iocb; /* Unmasked message */ - uint8_t msg[] = { 0x81, 0x00 }; /* "" */ + uint8_t msg[] = {0x81, 0x00}; /* "" */ acc.length = 0; wslay_frame_context_init(&ctx, &callbacks, &acc); memset(&iocb, 0, sizeof(iocb)); @@ -525,8 +482,7 @@ void test_wslay_frame_send_zero_payloadlen(void) wslay_frame_context_free(ctx); } -void test_wslay_frame_send_too_large_payload(void) -{ +void test_wslay_frame_send_too_large_payload(void) { wslay_frame_context_ptr ctx; struct wslay_frame_callbacks callbacks; struct wslay_frame_iocb iocb; @@ -536,14 +492,12 @@ void test_wslay_frame_send_too_large_payload(void) iocb.opcode = WSLAY_TEXT_FRAME; iocb.mask = 0; iocb.payload_length = UINT64_MAX; - CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, - wslay_frame_send(ctx, &iocb)); + CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, wslay_frame_send(ctx, &iocb)); wslay_frame_context_free(ctx); } -void test_wslay_frame_send_ctrl_frame_too_large_payload(void) -{ +void test_wslay_frame_send_ctrl_frame_too_large_payload(void) { wslay_frame_context_ptr ctx; struct wslay_frame_callbacks callbacks; struct wslay_frame_iocb iocb; @@ -553,8 +507,213 @@ void test_wslay_frame_send_ctrl_frame_too_large_payload(void) iocb.opcode = WSLAY_PING; iocb.mask = 0; iocb.payload_length = 1024; - CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, - wslay_frame_send(ctx, &iocb)); + CU_ASSERT_EQUAL(WSLAY_ERR_INVALID_ARGUMENT, wslay_frame_send(ctx, &iocb)); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks = {NULL, NULL, + static_genmask_callback}; + struct wslay_frame_iocb iocb; + /* Masked text frame containing "Hello" */ + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 1; + iocb.payload_length = 5; + iocb.data = (const uint8_t *)"Hello"; + iocb.data_length = 5; + CU_ASSERT(11 == + wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(iocb.data_length == wpayloadlen); + CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_fragmented(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks = {NULL, NULL, + static_genmask_callback}; + struct wslay_frame_iocb iocb; + /* Unmasked message */ + uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; /* "Hel" */ + uint8_t msg2[] = {0x80, 0x02, 0x6c, 0x6f}; /* "lo" */ + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 0; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 0; + iocb.payload_length = 3; + iocb.data = (const uint8_t *)"Hel"; + iocb.data_length = 3; + CU_ASSERT(5 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(3 == wpayloadlen); + CU_ASSERT(memcmp(msg1, buf, sizeof(msg1)) == 0); + + iocb.fin = 1; + iocb.opcode = WSLAY_CONTINUATION_FRAME; + iocb.payload_length = 2; + iocb.data = (const uint8_t *)"lo"; + iocb.data_length = 2; + CU_ASSERT(4 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(2 == wpayloadlen); + CU_ASSERT(memcmp(msg2, buf, sizeof(msg2)) == 0); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_interleaved_ctrl_frame(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks = {NULL, NULL, + static_genmask_callback}; + struct wslay_frame_iocb iocb; + /* Unmasked message */ + /* text with "Hel", with fin = 0 */ + uint8_t msg1[] = {0x01, 0x03, 0x48, 0x65, 0x6c}; + /* ping with "Hello" */ + uint8_t msg2[] = {0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f}; + /* text with "lo", continuation frame for msg1, with fin = 1 */ + uint8_t msg3[] = {0x80, 0x02, 0x6c, 0x6f}; + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 0; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 0; + iocb.payload_length = 3; + iocb.data = (const uint8_t *)"Hel"; + iocb.data_length = 3; + CU_ASSERT(5 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(3 == wpayloadlen); + CU_ASSERT(memcmp(msg1, buf, sizeof(msg1)) == 0); + + iocb.fin = 1; + iocb.opcode = WSLAY_PING; + iocb.payload_length = 5; + iocb.data = (const uint8_t *)"Hello"; + iocb.data_length = 5; + CU_ASSERT(7 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(5 == wpayloadlen); + CU_ASSERT(memcmp(msg2, buf, sizeof(msg2)) == 0); + + iocb.fin = 1; + iocb.opcode = WSLAY_CONTINUATION_FRAME; + iocb.payload_length = 2; + iocb.data = (const uint8_t *)"lo"; + iocb.data_length = 2; + CU_ASSERT(4 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(2 == wpayloadlen); + CU_ASSERT(memcmp(msg3, buf, sizeof(msg3)) == 0); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_1byte_masked(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks = {NULL, NULL, + static_genmask_callback}; + struct wslay_frame_iocb iocb; + /* Masked text frame containing "Hello" */ + uint8_t msg[] = {0x81u, 0x85u, 0x37u, 0xfau, 0x21u, 0x3du, + 0x7fu, 0x9fu, 0x4du, 0x51u, 0x58u}; + uint8_t hello[] = "Hello"; + size_t i; + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 1; + iocb.payload_length = 5; + iocb.data = hello; + iocb.data_length = sizeof(hello) - 1; + + CU_ASSERT_EQUAL(6, wslay_frame_write(ctx, &iocb, buf, 6, &wpayloadlen)); + CU_ASSERT(0 == wpayloadlen); + + for (i = 0; i < 5; ++i) { + CU_ASSERT_EQUAL( + 1, wslay_frame_write(ctx, &iocb, buf + 6 + i, 1, &wpayloadlen)); + CU_ASSERT(1 == wpayloadlen); + + ++iocb.data; + --iocb.data_length; + } + + CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_zero_payloadlen(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks = {NULL, NULL, + static_genmask_callback}; + struct wslay_frame_iocb iocb; + /* Unmasked message */ + uint8_t msg[] = {0x81, 0x00}; /* "" */ + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 0; + iocb.payload_length = 0; + iocb.data_length = 0; + CU_ASSERT(2 == wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + CU_ASSERT(0 == wpayloadlen); + CU_ASSERT(memcmp(msg, buf, sizeof(msg)) == 0); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_too_large_payload(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks; + struct wslay_frame_iocb iocb; + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = WSLAY_TEXT_FRAME; + iocb.mask = 0; + iocb.payload_length = UINT64_MAX; + CU_ASSERT_EQUAL( + WSLAY_ERR_INVALID_ARGUMENT, + wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); + + wslay_frame_context_free(ctx); +} + +void test_wslay_frame_write_ctrl_frame_too_large_payload(void) { + wslay_frame_context_ptr ctx; + struct wslay_frame_callbacks callbacks; + struct wslay_frame_iocb iocb; + uint8_t buf[1024]; + size_t wpayloadlen; + wslay_frame_context_init(&ctx, &callbacks, NULL); + memset(&iocb, 0, sizeof(iocb)); + iocb.fin = 1; + iocb.opcode = WSLAY_PING; + iocb.mask = 0; + iocb.payload_length = 1024; + CU_ASSERT_EQUAL( + WSLAY_ERR_INVALID_ARGUMENT, + wslay_frame_write(ctx, &iocb, buf, sizeof(buf), &wpayloadlen)); wslay_frame_context_free(ctx); } diff --git a/deps/wslay/tests/wslay_frame_test.h b/deps/wslay/tests/wslay_frame_test.h index e45291ae..be29581c 100644 --- a/deps/wslay/tests/wslay_frame_test.h +++ b/deps/wslay/tests/wslay_frame_test.h @@ -42,5 +42,12 @@ void test_wslay_frame_send_1byte_masked(void); void test_wslay_frame_send_zero_payloadlen(void); void test_wslay_frame_send_too_large_payload(void); void test_wslay_frame_send_ctrl_frame_too_large_payload(void); +void test_wslay_frame_write(void); +void test_wslay_frame_write_fragmented(void); +void test_wslay_frame_write_interleaved_ctrl_frame(void); +void test_wslay_frame_write_1byte_masked(void); +void test_wslay_frame_write_zero_payloadlen(void); +void test_wslay_frame_write_too_large_payload(void); +void test_wslay_frame_write_ctrl_frame_too_large_payload(void); #endif /* WSLAY_FRAME_TEST_H */ diff --git a/deps/wslay/tests/wslay_queue_test.c b/deps/wslay/tests/wslay_queue_test.c index 83fa8618..841a1aea 100644 --- a/deps/wslay/tests/wslay_queue_test.c +++ b/deps/wslay/tests/wslay_queue_test.c @@ -27,33 +27,49 @@ #include #include "wslay_queue.h" +#include "wslay_macro.h" -void test_wslay_queue(void) -{ - int ints[] = { 1, 2, 3, 4, 5 }; +struct queue_entry { + struct wslay_queue_entry qe; + int value; +}; + +void test_wslay_queue(void) { + struct queue_entry ents[] = { + {{0}, 1}, {{0}, 2}, {{0}, 3}, {{0}, 4}, {{0}, 5}, + }; int i; - struct wslay_queue *queue = wslay_queue_new(); - CU_ASSERT(wslay_queue_empty(queue)); - for(i = 0; i < 5; ++i) { - wslay_queue_push(queue, &ints[i]); - CU_ASSERT_EQUAL(ints[0], *(int*)(wslay_queue_top(queue))); - CU_ASSERT(!wslay_queue_empty(queue)); + struct wslay_queue queue; + wslay_queue_init(&queue); + CU_ASSERT(wslay_queue_empty(&queue)); + for (i = 0; i < 5; ++i) { + wslay_queue_push(&queue, &ents[i].qe); + CU_ASSERT_EQUAL(ents[0].value, wslay_struct_of(wslay_queue_top(&queue), + struct queue_entry, qe) + ->value); + CU_ASSERT(!wslay_queue_empty(&queue)); } - for(i = 0; i < 5; ++i) { - CU_ASSERT_EQUAL(ints[i], *(int*)(wslay_queue_top(queue))); - wslay_queue_pop(queue); + for (i = 0; i < 5; ++i) { + CU_ASSERT_EQUAL(ents[i].value, wslay_struct_of(wslay_queue_top(&queue), + struct queue_entry, qe) + ->value); + wslay_queue_pop(&queue); } - CU_ASSERT(wslay_queue_empty(queue)); + CU_ASSERT(wslay_queue_empty(&queue)); - for(i = 0; i < 5; ++i) { - wslay_queue_push_front(queue, &ints[i]); - CU_ASSERT_EQUAL(ints[i], *(int*)(wslay_queue_top(queue))); - CU_ASSERT(!wslay_queue_empty(queue)); + for (i = 0; i < 5; ++i) { + wslay_queue_push_front(&queue, &ents[i].qe); + CU_ASSERT_EQUAL(ents[i].value, wslay_struct_of(wslay_queue_top(&queue), + struct queue_entry, qe) + ->value); + CU_ASSERT(!wslay_queue_empty(&queue)); } - for(i = 4; i >= 0; --i) { - CU_ASSERT_EQUAL(ints[i], *(int*)(wslay_queue_top(queue))); - wslay_queue_pop(queue); + for (i = 4; i >= 0; --i) { + CU_ASSERT_EQUAL(ents[i].value, wslay_struct_of(wslay_queue_top(&queue), + struct queue_entry, qe) + ->value); + wslay_queue_pop(&queue); } - CU_ASSERT(wslay_queue_empty(queue)); - wslay_queue_free(queue); + CU_ASSERT(wslay_queue_empty(&queue)); + wslay_queue_deinit(&queue); } diff --git a/deps/wslay/tests/wslay_stack_test.c b/deps/wslay/tests/wslay_stack_test.c index fd4c3daf..eb81c247 100644 --- a/deps/wslay/tests/wslay_stack_test.c +++ b/deps/wslay/tests/wslay_stack_test.c @@ -28,19 +28,18 @@ #include "wslay_stack.h" -void test_wslay_stack() -{ - int ints[] = { 1, 2, 3, 4, 5 }; +void test_wslay_stack() { + int ints[] = {1, 2, 3, 4, 5}; int i; struct wslay_stack *stack = wslay_stack_new(); CU_ASSERT(wslay_stack_empty(stack)); - for(i = 0; i < 5; ++i) { + for (i = 0; i < 5; ++i) { wslay_stack_push(stack, &ints[i]); - CU_ASSERT_EQUAL(ints[i], *(int*)(wslay_stack_top(stack))); + CU_ASSERT_EQUAL(ints[i], *(int *)(wslay_stack_top(stack))); CU_ASSERT(!wslay_stack_empty(stack)); } - for(i = 4; i >= 0; --i) { - CU_ASSERT_EQUAL(ints[i], *(int*)(wslay_stack_top(stack))); + for (i = 4; i >= 0; --i) { + CU_ASSERT_EQUAL(ints[i], *(int *)(wslay_stack_top(stack))); wslay_stack_pop(stack); } CU_ASSERT(wslay_stack_empty(stack));