libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit ff13abc1c1d7d2b30d69d5c0bd4a237e1801c50b
parent 1fd9b3779f58e2f3385f9fdd5df8761fb991508e
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 16 Sep 2025 11:00:37 +0200

remove broken experimental code

Diffstat:
Msrc/Makefile.am | 5-----
Dsrc/microhttpd_ws/Makefile.am | 43-------------------------------------------
Dsrc/microhttpd_ws/mhd_websocket.c | 2443-------------------------------------------------------------------------------
Dsrc/microhttpd_ws/sha1.c | 378-------------------------------------------------------------------------------
Dsrc/microhttpd_ws/sha1.h | 110-------------------------------------------------------------------------------
Dsrc/microhttpd_ws/test_websocket.c | 10105-------------------------------------------------------------------------------
Dsrc/microhttpd_ws/test_websocket_browser.c | 567-------------------------------------------------------------------------------
7 files changed, 0 insertions(+), 13651 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am @@ -9,11 +9,6 @@ SUBDIRS += testzzuf endif endif -# Finally (last!) also build experimental lib... -if HAVE_EXPERIMENTAL -SUBDIRS += microhttpd_ws -endif - if BUILD_EXAMPLES SUBDIRS += examples endif diff --git a/src/microhttpd_ws/Makefile.am b/src/microhttpd_ws/Makefile.am @@ -1,43 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/include \ - -I$(top_srcdir)/src/microhttpd - -AM_CFLAGS = $(HIDDEN_VISIBILITY_CFLAGS) - -$(top_builddir)/src/microhttpd/libmicrohttpd.la: $(top_builddir)/src/microhttpd/Makefile - @echo ' cd $(top_builddir)/src/microhttpd && $(MAKE) $(AM_MAKEFLAGS) libmicrohttpd.la'; \ - $(am__cd) $(top_builddir)/src/microhttpd && $(MAKE) $(AM_MAKEFLAGS) libmicrohttpd.la - -noinst_DATA = -MOSTLYCLEANFILES = - -SUBDIRS = . - -lib_LTLIBRARIES = \ - libmicrohttpd_ws.la -libmicrohttpd_ws_la_SOURCES = \ - sha1.c sha1.h \ - mhd_websocket.c -libmicrohttpd_ws_la_CPPFLAGS = \ - $(AM_CPPFLAGS) $(MHD_LIB_CPPFLAGS) \ - -DBUILDING_MHD_LIB=1 -libmicrohttpd_ws_la_CFLAGS = \ - $(AM_CFLAGS) $(MHD_LIB_CFLAGS) -libmicrohttpd_ws_la_LDFLAGS = \ - $(MHD_LIB_LDFLAGS) \ - $(W32_MHD_LIB_LDFLAGS) \ - -version-info 0:0:0 -libmicrohttpd_ws_la_LIBADD = \ - $(MHD_LIBDEPS) - -TESTS = $(check_PROGRAMS) - -check_PROGRAMS = \ - test_websocket - -test_websocket_SOURCES = \ - test_websocket.c -test_websocket_LDADD = \ - $(top_builddir)/src/microhttpd_ws/libmicrohttpd_ws.la \ - $(top_builddir)/src/microhttpd/libmicrohttpd.la diff --git a/src/microhttpd_ws/mhd_websocket.c b/src/microhttpd_ws/mhd_websocket.c @@ -1,2443 +0,0 @@ -/* - This file is part of libmicrohttpd - Copyright (C) 2021 David Gausmann - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -*/ - -/** - * @file microhttpd_ws/mhd_websocket.c - * @brief Support for the websocket protocol - * @author David Gausmann - */ -#include "platform.h" -#include "microhttpd.h" -#include "microhttpd_ws.h" -#include "sha1.h" - -struct MHD_WebSocketStream -{ - /* The function pointer to malloc for payload (can be used to use different memory management) */ - MHD_WebSocketMallocCallback malloc; - /* The function pointer to realloc for payload (can be used to use different memory management) */ - MHD_WebSocketReallocCallback realloc; - /* The function pointer to free for payload (can be used to use different memory management) */ - MHD_WebSocketFreeCallback free; - /* A closure for the random number generator (only used for client mode; usually not required) */ - void *cls_rng; - /* The random number generator (only used for client mode; usually not required) */ - MHD_WebSocketRandomNumberGenerator rng; - /* The flags specified upon initialization. It may alter the behavior of decoding/encoding */ - int flags; - /* The current step for the decoder. 0 means start of a frame. */ - char decode_step; - /* Specifies whether the stream is valid (1) or not (0), - if a close frame has been received this is (-1) to indicate that no data frames are allowed anymore */ - char validity; - /* The current step of the UTF-8 encoding check in the data payload */ - char data_utf8_step; - /* The current step of the UTF-8 encoding check in the control payload */ - char control_utf8_step; - /* if != 0 means that we expect a CONTINUATION frame */ - char data_type; - /* The start of the current frame (may differ from data_payload for CONTINUATION frames) */ - char *data_payload_start; - /* The buffer for the data frame */ - char *data_payload; - /* The buffer for the control frame */ - char *control_payload; - /* Configuration for the maximum allowed buffer size for payload data */ - size_t max_payload_size; - /* The current frame header size */ - size_t frame_header_size; - /* The current data payload size (can be greater than payload_size for fragmented frames) */ - size_t data_payload_size; - /* The size of the payload of the current frame (control or data) */ - size_t payload_size; - /* The processing offset to the start of the payload of the current frame (control or data) */ - size_t payload_index; - /* The frame header of the current frame (control or data) */ - char frame_header[32]; - /* The mask key of the current frame (control or data); this is 0 if no masking used */ - char mask_key[4]; -}; - -#define MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT MHD_WEBSOCKET_FLAG_CLIENT -#define MHD_WEBSOCKET_FLAG_MASK_FRAGMENTATION \ - MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS -#define MHD_WEBSOCKET_FLAG_MASK_GENERATE_CLOSE_FRAMES \ - MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR -#define MHD_WEBSOCKET_FLAG_MASK_ALL \ - (MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT \ - | MHD_WEBSOCKET_FLAG_MASK_FRAGMENTATION \ - | MHD_WEBSOCKET_FLAG_MASK_GENERATE_CLOSE_FRAMES) - -enum MHD_WebSocket_Opcode -{ - MHD_WebSocket_Opcode_Continuation = 0x0, - MHD_WebSocket_Opcode_Text = 0x1, - MHD_WebSocket_Opcode_Binary = 0x2, - MHD_WebSocket_Opcode_Close = 0x8, - MHD_WebSocket_Opcode_Ping = 0x9, - MHD_WebSocket_Opcode_Pong = 0xA -}; - -enum MHD_WebSocket_DecodeStep -{ - MHD_WebSocket_DecodeStep_Start = 0, - MHD_WebSocket_DecodeStep_Length1ofX = 1, - MHD_WebSocket_DecodeStep_Length1of2 = 2, - MHD_WebSocket_DecodeStep_Length2of2 = 3, - MHD_WebSocket_DecodeStep_Length1of8 = 4, - MHD_WebSocket_DecodeStep_Length2of8 = 5, - MHD_WebSocket_DecodeStep_Length3of8 = 6, - MHD_WebSocket_DecodeStep_Length4of8 = 7, - MHD_WebSocket_DecodeStep_Length5of8 = 8, - MHD_WebSocket_DecodeStep_Length6of8 = 9, - MHD_WebSocket_DecodeStep_Length7of8 = 10, - MHD_WebSocket_DecodeStep_Length8of8 = 11, - MHD_WebSocket_DecodeStep_Mask1Of4 = 12, - MHD_WebSocket_DecodeStep_Mask2Of4 = 13, - MHD_WebSocket_DecodeStep_Mask3Of4 = 14, - MHD_WebSocket_DecodeStep_Mask4Of4 = 15, - MHD_WebSocket_DecodeStep_HeaderCompleted = 16, - MHD_WebSocket_DecodeStep_PayloadOfDataFrame = 17, - MHD_WebSocket_DecodeStep_PayloadOfControlFrame = 18, - MHD_WebSocket_DecodeStep_BrokenStream = 99 -}; - -enum MHD_WebSocket_UTF8Result -{ - MHD_WebSocket_UTF8Result_Invalid = 0, - MHD_WebSocket_UTF8Result_Valid = 1, - MHD_WebSocket_UTF8Result_Incomplete = 2 -}; - -static void -MHD_websocket_copy_payload (char *dst, - const char *src, - size_t len, - uint32_t mask, - unsigned long mask_offset); - -static int -MHD_websocket_check_utf8 (const char *buf, - size_t buf_len, - int *utf8_step, - size_t *buf_offset); - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_decode_header_complete (struct MHD_WebSocketStream *ws, - char **payload, - size_t *payload_len); - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream *ws, - char **payload, - size_t *payload_len); - -static char -MHD_websocket_encode_is_masked (struct MHD_WebSocketStream *ws); -static char -MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws, - size_t payload_len); - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_data (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - int fragmentation, - char **frame, - size_t *frame_len, - char opcode); - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - char **frame, - size_t *frame_len, - char opcode); - -static uint32_t -MHD_websocket_generate_mask (struct MHD_WebSocketStream *ws); - -static uint16_t -MHD_htons (uint16_t value); - -static uint64_t -MHD_htonll (uint64_t value); - - -/** - * Checks whether the HTTP version is 1.1 or above. - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_check_http_version (const char *http_version) -{ - /* validate parameters */ - if (NULL == http_version) - { - /* Like with the other check routines, */ - /* NULL is threated as "value not given" and not as parameter error */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - /* Check whether the version has a valid format */ - /* RFC 1945 3.1: The format must be "HTTP/x.x" where x is */ - /* any digit and must appear at least once */ - if (('H' != http_version[0]) || - ('T' != http_version[1]) || - ('T' != http_version[2]) || - ('P' != http_version[3]) || - ('/' != http_version[4])) - { - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - /* Find the major and minor part of the version */ - /* RFC 1945 3.1: Both numbers must be threated as separate integers. */ - /* Leading zeros must be ignored and both integers may have multiple digits */ - const char *major = NULL; - const char *dot = NULL; - size_t i = 5; - for (;;) - { - char c = http_version[i]; - if (('0' <= c) && ('9' >= c)) - { - if ((NULL == major) || - ((http_version + i == major + 1) && ('0' == *major)) ) - { - major = http_version + i; - } - ++i; - } - else if ('.' == http_version[i]) - { - dot = http_version + i; - ++i; - break; - } - else - { - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - } - const char *minor = NULL; - const char *end = NULL; - for (;;) - { - char c = http_version[i]; - if (('0' <= c) && ('9' >= c)) - { - if ((NULL == minor) || - ((http_version + i == minor + 1) && ('0' == *minor)) ) - { - minor = http_version + i; - } - ++i; - } - else if (0 == c) - { - end = http_version + i; - break; - } - else - { - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - } - if ((NULL == major) || (NULL == dot) || (NULL == minor) || (NULL == end)) - { - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - if ((2 <= dot - major) || ('2' <= *major) || - (('1' == *major) && ((2 <= end - minor) || ('1' <= *minor))) ) - { - return MHD_WEBSOCKET_STATUS_OK; - } - - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; -} - - -/** - * Checks whether the "Connection" request header has the 'Upgrade' token. - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_check_connection_header (const char *connection_header) -{ - /* validate parameters */ - if (NULL == connection_header) - { - /* To be compatible with the return value */ - /* of MHD_lookup_connection_value, */ - /* NULL is threated as "value not given" and not as parameter error */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - /* Check whether the Connection includes an Upgrade token */ - /* RFC 7230 6.1: Multiple tokens may appear. */ - /* RFC 7230 3.2.6: Tokens are comma separated */ - const char *token_start = NULL; - const char *token_end = NULL; - for (size_t i = 0; ; ++i) - { - char c = connection_header[i]; - - /* RFC 7230 3.2.6: The list of allowed characters is a token is: */ - /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */ - /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */ - /* DIGIT / ALPHA */ - if (('!' == c) || ('#' == c) || ('$' == c) || ('%' == c) || - ('&' == c) || ('\'' == c) || ('*' == c) || - ('+' == c) || ('-' == c) || ('.' == c) || ('^' == c) || - ('_' == c) || ('`' == c) || ('|' == c) || ('~' == c) || - (('0' <= c) && ('9' >= c)) || - (('A' <= c) && ('Z' >= c)) || (('a' <= c) && ('z' >= c)) ) - { - /* This is a valid token character */ - if (NULL == token_start) - { - token_start = connection_header + i; - } - token_end = connection_header + i + 1; - } - else if ((' ' == c) || ('\t' == c)) - { - /* White-spaces around tokens will be ignored */ - } - else if ((',' == c) || (0 == c)) - { - /* Check the token (case-insensitive) */ - if (NULL != token_start) - { - if (7 == (token_end - token_start) ) - { - if ( (('U' == token_start[0]) || ('u' == token_start[0])) && - (('P' == token_start[1]) || ('p' == token_start[1])) && - (('G' == token_start[2]) || ('g' == token_start[2])) && - (('R' == token_start[3]) || ('r' == token_start[3])) && - (('A' == token_start[4]) || ('a' == token_start[4])) && - (('D' == token_start[5]) || ('d' == token_start[5])) && - (('E' == token_start[6]) || ('e' == token_start[6])) ) - { - /* The token equals to "Upgrade" */ - return MHD_WEBSOCKET_STATUS_OK; - } - } - } - if (0 == c) - { - break; - } - token_start = NULL; - token_end = NULL; - } - else - { - /* RFC 7230 3.2.6: Other characters are not allowed */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - } - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; -} - - -/** - * Checks whether the "Upgrade" request header has the "websocket" keyword. - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_check_upgrade_header (const char *upgrade_header) -{ - /* validate parameters */ - if (NULL == upgrade_header) - { - /* To be compatible with the return value */ - /* of MHD_lookup_connection_value, */ - /* NULL is threated as "value not given" and not as parameter error */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - /* Check whether the Connection includes an Upgrade token */ - /* RFC 7230 6.1: Multiple tokens may appear. */ - /* RFC 7230 3.2.6: Tokens are comma separated */ - const char *keyword_start = NULL; - const char *keyword_end = NULL; - for (size_t i = 0; ; ++i) - { - char c = upgrade_header[i]; - - /* RFC 7230 3.2.6: The list of allowed characters is a token is: */ - /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */ - /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */ - /* DIGIT / ALPHA */ - /* We also allow "/" here as the sub-delimiter for the protocol version */ - if (('!' == c) || ('#' == c) || ('$' == c) || ('%' == c) || - ('&' == c) || ('\'' == c) || ('*' == c) || - ('+' == c) || ('-' == c) || ('.' == c) || ('^' == c) || - ('_' == c) || ('`' == c) || ('|' == c) || ('~' == c) || - ('/' == c) || - (('0' <= c) && ('9' >= c)) || - (('A' <= c) && ('Z' >= c)) || (('a' <= c) && ('z' >= c)) ) - { - /* This is a valid token character */ - if (NULL == keyword_start) - { - keyword_start = upgrade_header + i; - } - keyword_end = upgrade_header + i + 1; - } - else if ((' ' == c) || ('\t' == c)) - { - /* White-spaces around tokens will be ignored */ - } - else if ((',' == c) || (0 == c)) - { - /* Check the token (case-insensitive) */ - if (NULL != keyword_start) - { - if (9 == (keyword_end - keyword_start) ) - { - if ( (('W' == keyword_start[0]) || ('w' == keyword_start[0])) && - (('E' == keyword_start[1]) || ('e' == keyword_start[1])) && - (('B' == keyword_start[2]) || ('b' == keyword_start[2])) && - (('S' == keyword_start[3]) || ('s' == keyword_start[3])) && - (('O' == keyword_start[4]) || ('o' == keyword_start[4])) && - (('C' == keyword_start[5]) || ('c' == keyword_start[5])) && - (('K' == keyword_start[6]) || ('k' == keyword_start[6])) && - (('E' == keyword_start[7]) || ('e' == keyword_start[7])) && - (('T' == keyword_start[8]) || ('t' == keyword_start[8])) ) - { - /* The keyword equals to "websocket" */ - return MHD_WEBSOCKET_STATUS_OK; - } - } - } - if (0 == c) - { - break; - } - keyword_start = NULL; - keyword_end = NULL; - } - else - { - /* RFC 7230 3.2.6: Other characters are not allowed */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - } - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; -} - - -/** - * Checks whether the "Sec-WebSocket-Version" request header - * equals to "13" - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_check_version_header (const char *version_header) -{ - /* validate parameters */ - if (NULL == version_header) - { - /* To be compatible with the return value */ - /* of MHD_lookup_connection_value, */ - /* NULL is threated as "value not given" and not as parameter error */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - if (('1' == version_header[0]) && - ('3' == version_header[1]) && - (0 == version_header[2])) - { - /* The version equals to "13" */ - return MHD_WEBSOCKET_STATUS_OK; - } - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; -} - - -/** - * Creates the response for the Sec-WebSocket-Accept header - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_create_accept_header (const char *sec_websocket_key, - char *sec_websocket_accept) -{ - /* initialize output variables for errors cases */ - if (NULL != sec_websocket_accept) - *sec_websocket_accept = 0; - - /* validate parameters */ - if (NULL == sec_websocket_accept) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - if (NULL == sec_websocket_key) - { - /* NULL is not a parameter error, */ - /* because MHD_lookup_connection_value returns NULL */ - /* if the header wasn't found */ - return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; - } - - /* build SHA1 hash of the given key and the UUID appended */ - char sha1[20]; - const char *suffix = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - int length = (int) strlen (sec_websocket_key); - struct sha1_ctx ctx; - MHD_SHA1_init (&ctx); - MHD_SHA1_update (&ctx, (const uint8_t *) sec_websocket_key, length); - MHD_SHA1_update (&ctx, (const uint8_t *) suffix, 36); - MHD_SHA1_finish (&ctx, (uint8_t *) sha1); - - /* base64 encode that SHA1 hash */ - /* (simple algorithm here; SHA1 has always 20 bytes, */ - /* which will always result in a 28 bytes base64 hash) */ - const char *base64_encoding_table = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - for (int i = 0, j = 0; i < 20;) - { - uint32_t octet_a = i < 20 ? (unsigned char) sha1[i++] : 0; - uint32_t octet_b = i < 20 ? (unsigned char) sha1[i++] : 0; - uint32_t octet_c = i < 20 ? (unsigned char) sha1[i++] : 0; - uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; - - sec_websocket_accept[j++] = base64_encoding_table[(triple >> 3 * 6) & 0x3F]; - sec_websocket_accept[j++] = base64_encoding_table[(triple >> 2 * 6) & 0x3F]; - sec_websocket_accept[j++] = base64_encoding_table[(triple >> 1 * 6) & 0x3F]; - sec_websocket_accept[j++] = base64_encoding_table[(triple >> 0 * 6) & 0x3F]; - - } - sec_websocket_accept[27] = '='; - sec_websocket_accept[28] = 0; - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Initializes a new websocket stream - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_stream_init (struct MHD_WebSocketStream **ws, - int flags, - size_t max_payload_size) -{ - return MHD_websocket_stream_init2 (ws, - flags, - max_payload_size, - malloc, - realloc, - free, - NULL, - NULL); -} - - -/** - * Initializes a new websocket stream with - * additional parameters for allocation functions - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_stream_init2 (struct MHD_WebSocketStream **ws, - int flags, - size_t max_payload_size, - MHD_WebSocketMallocCallback callback_malloc, - MHD_WebSocketReallocCallback callback_realloc, - MHD_WebSocketFreeCallback callback_free, - void *cls_rng, - MHD_WebSocketRandomNumberGenerator callback_rng) -{ - /* initialize output variables for errors cases */ - if (NULL != ws) - *ws = NULL; - - /* validate parameters */ - if ((NULL == ws) || - (0 != (flags & ~MHD_WEBSOCKET_FLAG_MASK_ALL)) || - ((uint64_t) 0x7FFFFFFFFFFFFFFF < max_payload_size) || - (NULL == callback_malloc) || - (NULL == callback_realloc) || - (NULL == callback_free) || - ((0 != (flags & MHD_WEBSOCKET_FLAG_CLIENT)) && - (NULL == callback_rng))) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* allocate stream */ - struct MHD_WebSocketStream *ws_ = (struct MHD_WebSocketStream *) malloc ( - sizeof (struct MHD_WebSocketStream)); - if (NULL == ws_) - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - - /* initialize stream */ - memset (ws_, 0, sizeof (struct MHD_WebSocketStream)); - ws_->flags = flags; - ws_->max_payload_size = max_payload_size; - ws_->malloc = callback_malloc; - ws_->realloc = callback_realloc; - ws_->free = callback_free; - ws_->cls_rng = cls_rng; - ws_->rng = callback_rng; - ws_->validity = MHD_WEBSOCKET_VALIDITY_VALID; - - /* return stream */ - *ws = ws_; - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Frees a previously allocated websocket stream - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_stream_free (struct MHD_WebSocketStream *ws) -{ - /* validate parameters */ - if (NULL == ws) - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - - /* free allocated payload data */ - if (ws->data_payload) - ws->free (ws->data_payload); - if (ws->control_payload) - ws->free (ws->control_payload); - - /* free the stream */ - free (ws); - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Invalidates a websocket stream (no more decoding possible) - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_stream_invalidate (struct MHD_WebSocketStream *ws) -{ - /* validate parameters */ - if (NULL == ws) - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - - /* invalidate stream */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Returns whether a websocket stream is valid - */ -_MHD_EXTERN enum MHD_WEBSOCKET_VALIDITY -MHD_websocket_stream_is_valid (struct MHD_WebSocketStream *ws) -{ - /* validate parameters */ - if (NULL == ws) - return MHD_WEBSOCKET_VALIDITY_INVALID; - - return ws->validity; -} - - -/** - * Decodes incoming data to a websocket frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_decode (struct MHD_WebSocketStream *ws, - const char *streambuf, - size_t streambuf_len, - size_t *streambuf_read_len, - char **payload, - size_t *payload_len) -{ - /* initialize output variables for errors cases */ - if (NULL != streambuf_read_len) - *streambuf_read_len = 0; - if (NULL != payload) - *payload = NULL; - if (NULL != payload_len) - *payload_len = 0; - - /* validate parameters */ - if ((NULL == ws) || - ((NULL == streambuf) && (0 != streambuf_len)) || - (NULL == streambuf_read_len) || - (NULL == payload) || - (NULL == payload_len) ) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* validate stream validity */ - if (MHD_WEBSOCKET_VALIDITY_INVALID == ws->validity) - return MHD_WEBSOCKET_STATUS_STREAM_BROKEN; - - /* decode loop */ - size_t current = 0; - while (current < streambuf_len) - { - switch (ws->decode_step) - { - /* start of frame */ - case MHD_WebSocket_DecodeStep_Start: - { - /* The first byte contains the opcode, the fin flag and three reserved bits */ - if (MHD_WEBSOCKET_VALIDITY_INVALID != ws->validity) - { - char opcode = streambuf [current]; - if (0 != (opcode & 0x70)) - { - /* RFC 6455 5.2 RSV1-3: If a reserved flag is set */ - /* (while it isn't specified by an extension) the communication must fail. */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - switch (opcode & 0x0F) - { - case MHD_WebSocket_Opcode_Continuation: - if (0 == ws->data_type) - { - /* RFC 6455 5.4: Continuation frame without previous data frame */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if (MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES == - ws->validity) - { - /* RFC 6455 5.5.1: After a close frame has been sent, */ - /* no data frames may be sent (so we don't accept data frames */ - /* for decoding anymore) */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - break; - - case MHD_WebSocket_Opcode_Text: - case MHD_WebSocket_Opcode_Binary: - if (0 != ws->data_type) - { - /* RFC 6455 5.4: Continuation expected, but new data frame */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if (MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES == - ws->validity) - { - /* RFC 6455 5.5.1: After a close frame has been sent, */ - /* no data frames may be sent (so we don't accept data frames */ - /* for decoding anymore) */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - break; - - case MHD_WebSocket_Opcode_Close: - case MHD_WebSocket_Opcode_Ping: - case MHD_WebSocket_Opcode_Pong: - if ((opcode & 0x80) == 0) - { - /* RFC 6455 5.4: Control frames may not be fragmented */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if (MHD_WebSocket_Opcode_Close == (opcode & 0x0F)) - { - /* RFC 6455 5.5.1: After a close frame has been sent, */ - /* no data frames may be sent (so we don't accept data frames */ - /* for decoding anymore) */ - ws->validity = - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES; - } - break; - - default: - /* RFC 6455 5.2 OPCODE: Only six opcodes are specified. */ - /* All other are invalid in version 13 of the protocol. */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - } - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - ws->decode_step = MHD_WebSocket_DecodeStep_Length1ofX; - } - break; - - case MHD_WebSocket_DecodeStep_Length1ofX: - { - /* The second byte specifies whether the data is masked and the size */ - /* (the client MUST mask the payload, the server MUST NOT mask the payload) */ - char frame_len = streambuf [current]; - char is_masked = (frame_len & 0x80); - frame_len &= 0x7f; - if (MHD_WEBSOCKET_VALIDITY_INVALID != ws->validity) - { - if (0 != is_masked) - { - if (MHD_WEBSOCKET_FLAG_CLIENT == (ws->flags - & MHD_WEBSOCKET_FLAG_CLIENT)) - { - /* RFC 6455 5.1: All frames from the server must be unmasked */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - } - else - { - if (MHD_WEBSOCKET_FLAG_SERVER == (ws->flags - & MHD_WEBSOCKET_FLAG_CLIENT)) - { - /* RFC 6455 5.1: All frames from the client must be masked */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - } - if (126 <= frame_len) - { - if (0 != (ws->frame_header [0] & 0x08)) - { - /* RFC 6455 5.5: Control frames may not have more payload than 125 bytes */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - } - if (1 == frame_len) - { - if (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0F)) - { - /* RFC 6455 5.5.1: The close frame must have at least */ - /* two bytes of payload if payload is used */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - } - } - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - - if (126 == frame_len) - { - ws->decode_step = MHD_WebSocket_DecodeStep_Length1of2; - } - else if (127 == frame_len) - { - ws->decode_step = MHD_WebSocket_DecodeStep_Length1of8; - } - else - { - size_t size = (size_t) frame_len; - if ((SIZE_MAX < size) || - (ws->max_payload_size && (ws->max_payload_size < size)) ) - { - /* RFC 6455 7.4.1 1009: If the message is too big to process, we may close the connection */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - ws->payload_size = size; - if (0 != is_masked) - { - /* with mask */ - ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; - } - else - { - /* without mask */ - *((uint32_t *) ws->mask_key) = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; - } - } - } - break; - - /* Payload size first byte of 2 bytes */ - case MHD_WebSocket_DecodeStep_Length1of2: - /* Payload size first 7 bytes of 8 bytes */ - case MHD_WebSocket_DecodeStep_Length1of8: - case MHD_WebSocket_DecodeStep_Length2of8: - case MHD_WebSocket_DecodeStep_Length3of8: - case MHD_WebSocket_DecodeStep_Length4of8: - case MHD_WebSocket_DecodeStep_Length5of8: - case MHD_WebSocket_DecodeStep_Length6of8: - case MHD_WebSocket_DecodeStep_Length7of8: - /* Mask first 3 bytes of 4 bytes */ - case MHD_WebSocket_DecodeStep_Mask1Of4: - case MHD_WebSocket_DecodeStep_Mask2Of4: - case MHD_WebSocket_DecodeStep_Mask3Of4: - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - ++ws->decode_step; - break; - - /* 2 byte length finished */ - case MHD_WebSocket_DecodeStep_Length2of2: - { - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - size_t size = (size_t) MHD_htons ( - *((uint16_t *) &ws->frame_header [2])); - if (125 >= size) - { - /* RFC 6455 5.2 Payload length: The minimal number of bytes */ - /* must be used for the length */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if ((SIZE_MAX < size) || - (ws->max_payload_size && (ws->max_payload_size < size)) ) - { - /* RFC 6455 7.4.1 1009: If the message is too big to process, */ - /* we may close the connection */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - ws->payload_size = size; - if (0 != (ws->frame_header [1] & 0x80)) - { - /* with mask */ - ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; - } - else - { - /* without mask */ - *((uint32_t *) ws->mask_key) = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; - } - } - break; - - /* 8 byte length finished */ - case MHD_WebSocket_DecodeStep_Length8of8: - { - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - uint64_t size = MHD_htonll (*((uint64_t *) &ws->frame_header [2])); - if (0x7fffffffffffffff < size) - { - /* RFC 6455 5.2 frame-payload-length-63: The length may */ - /* not exceed 0x7fffffffffffffff */ - ws->decode_step = MHD_WebSocket_DecodeStep_BrokenStream; - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if (65535 >= size) - { - /* RFC 6455 5.2 Payload length: The minimal number of bytes */ - /* must be used for the length */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - } - if ((SIZE_MAX < size) || - (ws->max_payload_size && (ws->max_payload_size < size)) ) - { - /* RFC 6455 7.4.1 1009: If the message is too big to process, */ - /* we may close the connection */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - ws->payload_size = (size_t) size; - - if (0 != (ws->frame_header [1] & 0x80)) - { - /* with mask */ - ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; - } - else - { - /* without mask */ - *((uint32_t *) ws->mask_key) = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; - } - } - break; - - /* mask finished */ - case MHD_WebSocket_DecodeStep_Mask4Of4: - ws->frame_header [ws->frame_header_size++] = streambuf [current++]; - *((uint32_t *) ws->mask_key) = *((uint32_t *) &ws->frame_header [ws-> - frame_header_size - - 4]); - ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; - break; - - /* header finished */ - case MHD_WebSocket_DecodeStep_HeaderCompleted: - /* return or assign either to data or control */ - { - int ret = MHD_websocket_decode_header_complete (ws, - payload, - payload_len); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - *streambuf_read_len = current; - return ret; - } - } - break; - - /* payload data */ - case MHD_WebSocket_DecodeStep_PayloadOfDataFrame: - case MHD_WebSocket_DecodeStep_PayloadOfControlFrame: - { - size_t bytes_needed = ws->payload_size - ws->payload_index; - size_t bytes_remaining = streambuf_len - current; - size_t bytes_to_take = bytes_needed < bytes_remaining ? bytes_needed : - bytes_remaining; - if (0 != bytes_to_take) - { - size_t utf8_start = ws->payload_index; - char *decode_payload = ws->decode_step == - MHD_WebSocket_DecodeStep_PayloadOfDataFrame ? - ws->data_payload_start : - ws->control_payload; - - /* copy the new payload data (with unmasking if necessary */ - MHD_websocket_copy_payload (decode_payload + ws->payload_index, - &streambuf [current], - bytes_to_take, - *((uint32_t *) ws->mask_key), - (unsigned long) (ws->payload_index - & 0x03)); - current += bytes_to_take; - ws->payload_index += bytes_to_take; - if (((MHD_WebSocket_DecodeStep_PayloadOfDataFrame == - ws->decode_step) && - (MHD_WebSocket_Opcode_Text == ws->data_type)) || - ((MHD_WebSocket_DecodeStep_PayloadOfControlFrame == - ws->decode_step) && - (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0f)) && - (2 < ws->payload_index)) ) - { - /* RFC 6455 8.1: We need to check the UTF-8 validity */ - int utf8_step; - char *decode_payload_utf8; - size_t bytes_to_check; - size_t utf8_error_offset = 0; - if (MHD_WebSocket_DecodeStep_PayloadOfDataFrame == ws->decode_step) - { - utf8_step = ws->data_utf8_step; - decode_payload_utf8 = decode_payload + utf8_start; - bytes_to_check = bytes_to_take; - } - else - { - utf8_step = ws->control_utf8_step; - if ((MHD_WebSocket_Opcode_Close == (ws->frame_header [0] - & 0x0f)) && - (2 > utf8_start) ) - { - /* The first two bytes of the close frame are binary content and */ - /* must be skipped in the UTF-8 check */ - utf8_start = 2; - utf8_error_offset = 2; - } - decode_payload_utf8 = decode_payload + utf8_start; - bytes_to_check = bytes_to_take - utf8_start; - } - size_t utf8_check_offset = 0; - int utf8_result = MHD_websocket_check_utf8 (decode_payload_utf8, - bytes_to_check, - &utf8_step, - &utf8_check_offset); - if (MHD_WebSocket_UTF8Result_Invalid != utf8_result) - { - /* memorize current validity check step to continue later */ - ws->data_utf8_step = utf8_step; - } - else - { - /* RFC 6455 8.1: We must fail on broken UTF-8 sequence */ - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8, - 0, - 0, - payload, - payload_len); - } - *streambuf_read_len = current - bytes_to_take - + utf8_check_offset + utf8_error_offset; - return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; - } - } - } - } - - if (ws->payload_size == ws->payload_index) - { - /* all payload data of the current frame has been received */ - int ret = MHD_websocket_decode_payload_complete (ws, - payload, - payload_len); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - *streambuf_read_len = current; - return ret; - } - } - break; - - case MHD_WebSocket_DecodeStep_BrokenStream: - *streambuf_read_len = current; - return MHD_WEBSOCKET_STATUS_STREAM_BROKEN; - } - } - - /* Special treatment for zero payload length messages */ - if (MHD_WebSocket_DecodeStep_HeaderCompleted == ws->decode_step) - { - int ret = MHD_websocket_decode_header_complete (ws, - payload, - payload_len); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - *streambuf_read_len = current; - return ret; - } - } - switch (ws->decode_step) - { - case MHD_WebSocket_DecodeStep_PayloadOfDataFrame: - case MHD_WebSocket_DecodeStep_PayloadOfControlFrame: - if (ws->payload_size == ws->payload_index) - { - /* all payload data of the current frame has been received */ - int ret = MHD_websocket_decode_payload_complete (ws, - payload, - payload_len); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - *streambuf_read_len = current; - return ret; - } - } - break; - } - *streambuf_read_len = current; - - /* more data needed */ - return MHD_WEBSOCKET_STATUS_OK; -} - - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_decode_header_complete (struct MHD_WebSocketStream *ws, - char **payload, - size_t *payload_len) -{ - /* assign either to data or control */ - char opcode = ws->frame_header [0] & 0x0f; - switch (opcode) - { - case MHD_WebSocket_Opcode_Continuation: - { - /* validate payload size */ - size_t new_size_total = ws->payload_size + ws->data_payload_size; - if ((0 != ws->max_payload_size) && (ws->max_payload_size < - new_size_total) ) - { - /* RFC 6455 7.4.1 1009: If the message is too big to process, */ - /* we may close the connection */ - ws->decode_step = MHD_WebSocket_DecodeStep_BrokenStream; - ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; - if (0 != (ws->flags - & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) - { - MHD_websocket_encode_close (ws, - MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, - 0, - 0, - payload, - payload_len); - } - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - /* allocate buffer for continued data frame */ - char *new_buf = NULL; - if (0 != new_size_total) - { - new_buf = ws->realloc (ws->data_payload, new_size_total + 1); - if (NULL == new_buf) - { - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - } - new_buf [new_size_total] = 0; - ws->data_payload_start = &new_buf[ws->data_payload_size]; - } - else - { - ws->data_payload_start = new_buf; - } - ws->data_payload = new_buf; - ws->data_payload_size = new_size_total; - } - ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfDataFrame; - break; - - case MHD_WebSocket_Opcode_Text: - case MHD_WebSocket_Opcode_Binary: - /* allocate buffer for data frame */ - { - size_t new_size_total = ws->payload_size; - char *new_buf = NULL; - if (0 != new_size_total) - { - new_buf = ws->malloc (new_size_total + 1); - if (NULL == new_buf) - { - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - } - new_buf [new_size_total] = 0; - } - ws->data_payload = new_buf; - ws->data_payload_start = new_buf; - ws->data_payload_size = new_size_total; - ws->data_type = opcode; - } - ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfDataFrame; - break; - - case MHD_WebSocket_Opcode_Close: - case MHD_WebSocket_Opcode_Ping: - case MHD_WebSocket_Opcode_Pong: - /* allocate buffer for control frame */ - { - size_t new_size_total = ws->payload_size; - char *new_buf = NULL; - if (0 != new_size_total) - { - new_buf = ws->malloc (new_size_total + 1); - if (NULL == new_buf) - { - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - } - new_buf[new_size_total] = 0; - } - ws->control_payload = new_buf; - } - ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfControlFrame; - break; - } - - return MHD_WEBSOCKET_STATUS_OK; -} - - -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream *ws, - char **payload, - size_t *payload_len) -{ - /* all payload data of the current frame has been received */ - char is_continue = MHD_WebSocket_Opcode_Continuation == - (ws->frame_header [0] & 0x0F); - char is_fin = ws->frame_header [0] & 0x80; - if (0 != is_fin) - { - /* the frame is complete */ - if (MHD_WebSocket_DecodeStep_PayloadOfDataFrame == ws->decode_step) - { - /* data frame */ - char data_type = ws->data_type; - if ((0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) && - (0 != is_continue)) - { - data_type |= 0x40; /* mark as last fragment */ - } - *payload = ws->data_payload; - *payload_len = ws->data_payload_size; - ws->data_payload = 0; - ws->data_payload_start = 0; - ws->data_payload_size = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_Start; - ws->payload_index = 0; - ws->data_type = 0; - ws->frame_header_size = 0; - return data_type; - } - else - { - /* control frame */ - *payload = ws->control_payload; - *payload_len = ws->payload_size; - ws->control_payload = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_Start; - ws->payload_index = 0; - ws->frame_header_size = 0; - return (ws->frame_header [0] & 0x0f); - } - } - else if (0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) - { - /* RFC 6455 5.4: To allow streaming, the user can choose */ - /* to return fragments */ - if ((MHD_WebSocket_Opcode_Text == ws->data_type) && - (MHD_WEBSOCKET_UTF8STEP_NORMAL != ws->data_utf8_step) ) - { - /* the last UTF-8 sequence is incomplete, so we keep the start of - that and only return the part before */ - size_t given_utf8 = 0; - switch (ws->data_utf8_step) - { - /* one byte given */ - case MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1: - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2: - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2: - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2: - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3: - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3: - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3: - given_utf8 = 1; - break; - /* two bytes given */ - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2: - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3: - given_utf8 = 2; - break; - /* three bytes given */ - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3: - given_utf8 = 3; - break; - } - size_t new_len = ws->data_payload_size - given_utf8; - if (0 != new_len) - { - char *next_payload = ws->malloc (given_utf8 + 1); - if (NULL == next_payload) - { - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - } - memcpy (next_payload, - ws->data_payload_start + ws->payload_index - given_utf8, - given_utf8); - next_payload[given_utf8] = 0; - - ws->data_payload[new_len] = 0; - *payload = ws->data_payload; - *payload_len = new_len; - ws->data_payload = next_payload; - ws->data_payload_size = given_utf8; - } - else - { - *payload = NULL; - *payload_len = 0; - } - ws->decode_step = MHD_WebSocket_DecodeStep_Start; - ws->payload_index = 0; - ws->frame_header_size = 0; - if (0 != is_continue) - return ws->data_type | 0x20; /* mark as middle fragment */ - else - return ws->data_type | 0x10; /* mark as first fragment */ - } - else - { - /* we simply pass the entire data frame */ - *payload = ws->data_payload; - *payload_len = ws->data_payload_size; - ws->data_payload = 0; - ws->data_payload_start = 0; - ws->data_payload_size = 0; - ws->decode_step = MHD_WebSocket_DecodeStep_Start; - ws->payload_index = 0; - ws->frame_header_size = 0; - if (0 != is_continue) - return ws->data_type | 0x20; /* mark as middle fragment */ - else - return ws->data_type | 0x10; /* mark as first fragment */ - } - } - else - { - /* RFC 6455 5.4: We must await a continuation frame to get */ - /* the remainder of this data frame */ - ws->decode_step = MHD_WebSocket_DecodeStep_Start; - ws->frame_header_size = 0; - ws->payload_index = 0; - return MHD_WEBSOCKET_STATUS_OK; - } -} - - -/** - * Splits the received close reason - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_split_close_reason (const char *payload, - size_t payload_len, - unsigned short *reason_code, - const char **reason_utf8, - size_t *reason_utf8_len) -{ - /* initialize output variables for errors cases */ - if (NULL != reason_code) - *reason_code = MHD_WEBSOCKET_CLOSEREASON_NO_REASON; - if (NULL != reason_utf8) - *reason_utf8 = NULL; - if (NULL != reason_utf8_len) - *reason_utf8_len = 0; - - /* validate parameters */ - if ((NULL == payload) && (0 != payload_len)) - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - if (1 == payload_len) - return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; - if (125 < payload_len) - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - - /* decode reason code */ - if (2 > payload_len) - { - if (NULL != reason_code) - *reason_code = MHD_WEBSOCKET_CLOSEREASON_NO_REASON; - } - else - { - if (NULL != reason_code) - *reason_code = MHD_htons (*((uint16_t *) payload)); - } - - /* decode reason text */ - if (2 >= payload_len) - { - if (NULL != reason_utf8) - *reason_utf8 = NULL; - if (NULL != reason_utf8_len) - *reason_utf8_len = 0; - } - else - { - if (NULL != reason_utf8) - *reason_utf8 = payload + 2; - if (NULL != reason_utf8_len) - *reason_utf8_len = payload_len - 2; - } - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Encodes a text into a websocket text frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_text (struct MHD_WebSocketStream *ws, - const char *payload_utf8, - size_t payload_utf8_len, - int fragmentation, - char **frame, - size_t *frame_len, - int *utf8_step) -{ - /* initialize output variables for errors cases */ - if (NULL != frame) - *frame = NULL; - if (NULL != frame_len) - *frame_len = 0; - if ((NULL != utf8_step) && - ((MHD_WEBSOCKET_FRAGMENTATION_FIRST == fragmentation) || - (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation) )) - { - /* the old UTF-8 step will be ignored for new fragments */ - *utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; - } - - /* validate parameters */ - if ((NULL == ws) || - ((0 != payload_utf8_len) && (NULL == payload_utf8)) || - (NULL == frame) || - (NULL == frame_len) || - (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || - (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) || - ((MHD_WEBSOCKET_FRAGMENTATION_NONE != fragmentation) && - (NULL == utf8_step)) ) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* check max length */ - if ((uint64_t) 0x7FFFFFFFFFFFFFFF < (uint64_t) payload_utf8_len) - { - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - - /* check UTF-8 */ - int utf8_result = MHD_websocket_check_utf8 (payload_utf8, - payload_utf8_len, - utf8_step, - NULL); - if ((MHD_WebSocket_UTF8Result_Invalid == utf8_result) || - ((MHD_WebSocket_UTF8Result_Incomplete == utf8_result) && - (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation)) ) - { - return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; - } - - /* encode data */ - return MHD_websocket_encode_data (ws, - payload_utf8, - payload_utf8_len, - fragmentation, - frame, - frame_len, - MHD_WebSocket_Opcode_Text); -} - - -/** - * Encodes binary data into a websocket binary frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_binary (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - int fragmentation, - char **frame, - size_t *frame_len) -{ - /* initialize output variables for errors cases */ - if (NULL != frame) - *frame = NULL; - if (NULL != frame_len) - *frame_len = 0; - - /* validate parameters */ - if ((NULL == ws) || - ((0 != payload_len) && (NULL == payload)) || - (NULL == frame) || - (NULL == frame_len) || - (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || - (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) ) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* check max length */ - if ((uint64_t) 0x7FFFFFFFFFFFFFFF < (uint64_t) payload_len) - { - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - } - - return MHD_websocket_encode_data (ws, - payload, - payload_len, - fragmentation, - frame, - frame_len, - MHD_WebSocket_Opcode_Binary); -} - - -/** - * Internal function for encoding text/binary data into a websocket frame - */ -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_data (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - int fragmentation, - char **frame, - size_t *frame_len, - char opcode) -{ - /* calculate length and masking */ - char is_masked = MHD_websocket_encode_is_masked (ws); - size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); - size_t total_len = overhead_len + payload_len; - uint32_t mask = 0 != is_masked ? MHD_websocket_generate_mask (ws) : 0; - - /* allocate memory */ - char *result = ws->malloc (total_len + 1); - if (NULL == result) - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - result [total_len] = 0; - *frame = result; - *frame_len = total_len; - - /* add the opcode */ - switch (fragmentation) - { - case MHD_WEBSOCKET_FRAGMENTATION_NONE: - *(result++) = 0x80 | opcode; - break; - case MHD_WEBSOCKET_FRAGMENTATION_FIRST: - *(result++) = opcode; - break; - case MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING: - *(result++) = MHD_WebSocket_Opcode_Continuation; - break; - case MHD_WEBSOCKET_FRAGMENTATION_LAST: - *(result++) = 0x80 | MHD_WebSocket_Opcode_Continuation; - break; - } - - /* add the length */ - if (126 > payload_len) - { - *(result++) = is_masked | (char) payload_len; - } - else if (65536 > payload_len) - { - *(result++) = is_masked | 126; - *((uint16_t *) result) = MHD_htons ((uint16_t) payload_len); - result += 2; - } - else - { - *(result++) = is_masked | 127; - *((uint64_t *) result) = MHD_htonll ((uint64_t) payload_len); - result += 8; - - } - - /* add the mask */ - if (0 != is_masked) - { - *(result++) = ((char *) &mask)[0]; - *(result++) = ((char *) &mask)[1]; - *(result++) = ((char *) &mask)[2]; - *(result++) = ((char *) &mask)[3]; - } - - /* add the payload */ - if (0 != payload_len) - { - MHD_websocket_copy_payload (result, - payload, - payload_len, - mask, - 0); - } - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Encodes a websocket ping frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_ping (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - char **frame, - size_t *frame_len) -{ - /* encode the ping frame */ - return MHD_websocket_encode_ping_pong (ws, - payload, - payload_len, - frame, - frame_len, - MHD_WebSocket_Opcode_Ping); -} - - -/** - * Encodes a websocket pong frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_pong (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - char **frame, - size_t *frame_len) -{ - /* encode the pong frame */ - return MHD_websocket_encode_ping_pong (ws, - payload, - payload_len, - frame, - frame_len, - MHD_WebSocket_Opcode_Pong); -} - - -/** - * Internal function for encoding ping/pong frames - */ -static enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream *ws, - const char *payload, - size_t payload_len, - char **frame, - size_t *frame_len, - char opcode) -{ - /* initialize output variables for errors cases */ - if (NULL != frame) - *frame = NULL; - if (NULL != frame_len) - *frame_len = 0; - - /* validate the parameters */ - if ((NULL == ws) || - ((0 != payload_len) && (NULL == payload)) || - (NULL == frame) || - (NULL == frame_len) ) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* RFC 6455 5.5: Control frames may only have up to 125 bytes of payload data */ - if (125 < payload_len) - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - - /* calculate length and masking */ - char is_masked = MHD_websocket_encode_is_masked (ws); - size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); - size_t total_len = overhead_len + payload_len; - uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0; - - /* allocate memory */ - char *result = ws->malloc (total_len + 1); - if (NULL == result) - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - result [total_len] = 0; - *frame = result; - *frame_len = total_len; - - /* add the opcode */ - *(result++) = 0x80 | opcode; - - /* add the length */ - *(result++) = is_masked | (char) payload_len; - - /* add the mask */ - if (0 != is_masked) - { - *(result++) = ((char *) &mask)[0]; - *(result++) = ((char *) &mask)[1]; - *(result++) = ((char *) &mask)[2]; - *(result++) = ((char *) &mask)[3]; - } - - /* add the payload */ - if (0 != payload_len) - { - MHD_websocket_copy_payload (result, - payload, - payload_len, - mask, - 0); - } - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Encodes a websocket close frame - */ -_MHD_EXTERN enum MHD_WEBSOCKET_STATUS -MHD_websocket_encode_close (struct MHD_WebSocketStream *ws, - unsigned short reason_code, - const char *reason_utf8, - size_t reason_utf8_len, - char **frame, - size_t *frame_len) -{ - /* initialize output variables for errors cases */ - if (NULL != frame) - *frame = NULL; - if (NULL != frame_len) - *frame_len = 0; - - /* validate the parameters */ - if ((NULL == ws) || - ((0 != reason_utf8_len) && (NULL == reason_utf8)) || - (NULL == frame) || - (NULL == frame_len) || - ((MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) && - (1000 > reason_code)) || - ((0 != reason_utf8_len) && - (MHD_WEBSOCKET_CLOSEREASON_NO_REASON == reason_code)) ) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - /* RFC 6455 5.5: Control frames may only have up to 125 bytes of payload data, */ - /* but in this case only 123 bytes, because 2 bytes are reserved */ - /* for the close reason code. */ - if (123 < reason_utf8_len) - return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; - - /* RFC 6455 5.5.1: If close payload data is given, it must be valid UTF-8 */ - if (0 != reason_utf8_len) - { - int utf8_result = MHD_websocket_check_utf8 (reason_utf8, - reason_utf8_len, - NULL, - NULL); - if (MHD_WebSocket_UTF8Result_Valid != utf8_result) - return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; - } - - /* calculate length and masking */ - char is_masked = MHD_websocket_encode_is_masked (ws); - size_t payload_len = (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code ? - 2 + reason_utf8_len : 0); - size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); - size_t total_len = overhead_len + payload_len; - uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0; - - /* allocate memory */ - char *result = ws->malloc (total_len + 1); - if (NULL == result) - return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; - result [total_len] = 0; - *frame = result; - *frame_len = total_len; - - /* add the opcode */ - *(result++) = 0x88; - - /* add the length */ - *(result++) = is_masked | (char) payload_len; - - /* add the mask */ - if (0 != is_masked) - { - *(result++) = ((char *) &mask)[0]; - *(result++) = ((char *) &mask)[1]; - *(result++) = ((char *) &mask)[2]; - *(result++) = ((char *) &mask)[3]; - } - - /* add the payload */ - if (0 != reason_code) - { - /* close reason code */ - uint16_t reason_code_nb = MHD_htons (reason_code); - MHD_websocket_copy_payload (result, - (const char *) &reason_code_nb, - 2, - mask, - 0); - result += 2; - - /* custom reason payload */ - if (0 != reason_utf8_len) - { - MHD_websocket_copy_payload (result, - reason_utf8, - reason_utf8_len, - mask, - 2); - } - } - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Returns the 0x80 prefix for masked data, 0x00 otherwise - */ -static char -MHD_websocket_encode_is_masked (struct MHD_WebSocketStream *ws) -{ - return (ws->flags & MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT) == - MHD_WEBSOCKET_FLAG_CLIENT ? 0x80 : 0x00; -} - - -/** - * Calculates the size of the overhead in bytes - */ -static char -MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws, - size_t payload_len) -{ - return 2 + (MHD_websocket_encode_is_masked (ws) != 0 ? 4 : 0) + (125 < - payload_len ? - (65535 < - payload_len - ? 8 : 2) : 0); -} - - -/** - * Copies the payload to the destination (using mask) - */ -static void -MHD_websocket_copy_payload (char *dst, - const char *src, - size_t len, - uint32_t mask, - unsigned long mask_offset) -{ - if (0 != len) - { - if (0 == mask) - { - /* when the mask is zero, we can just copy the data */ - memcpy (dst, src, len); - } - else - { - /* mask is used */ - char mask_[4]; - *((uint32_t *) mask_) = mask; - for (size_t i = 0; i < len; ++i) - { - dst[i] = src[i] ^ mask_[(i + mask_offset) & 3]; - } - } - } -} - - -/** - * Checks a UTF-8 sequence - */ -static int -MHD_websocket_check_utf8 (const char *buf, - size_t buf_len, - int *utf8_step, - size_t *buf_offset) -{ - int utf8_step_ = (NULL != utf8_step) ? *utf8_step : - MHD_WEBSOCKET_UTF8STEP_NORMAL; - - for (size_t i = 0; i < buf_len; ++i) - { - unsigned char character = (unsigned char) buf[i]; - switch (utf8_step_) - { - case MHD_WEBSOCKET_UTF8STEP_NORMAL: - if ((0x00 <= character) && (0x7F >= character)) - { - /* RFC 3629 4: single byte UTF-8 sequence */ - /* (nothing to do here) */ - } - else if ((0xC2 <= character) && (0xDF >= character)) - { - /* RFC 3629 4: two byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1; - } - else if (0xE0 == character) - { - /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0xA0-0xBF */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2; - } - else if (0xED == character) - { - /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0x80-0x9F */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2; - } - else if (((0xE1 <= character) && (0xEC >= character)) || - ((0xEE <= character) && (0xEF >= character)) ) - { - /* RFC 3629 4: three byte UTF-8 sequence, both tail bytes must be 0x80-0xBF */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2; - } - else if (0xF0 == character) - { - /* RFC 3629 4: four byte UTF-8 sequence, but the second byte must be 0x90-0xBF */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3; - } - else if (0xF4 == character) - { - /* RFC 3629 4: four byte UTF-8 sequence, but the second byte must be 0x80-0x8F */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3; - } - else if ((0xF1 <= character) && (0xF3 >= character)) - { - /* RFC 3629 4: four byte UTF-8 sequence, all three tail bytes must be 0x80-0xBF */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2: - if ((0xA0 <= character) && (0xBF >= character)) - { - /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2: - if ((0x80 <= character) && (0x9F >= character)) - { - /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2: - if ((0x80 <= character) && (0xBF >= character)) - { - /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3: - if ((0x90 <= character) && (0xBF >= character)) - { - /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3: - if ((0x80 <= character) && (0x8F >= character)) - { - /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3: - if ((0x80 <= character) && (0xBF >= character)) - { - /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3: - if ((0x80 <= character) && (0xBF >= character)) - { - /* RFC 3629 4: Third byte of four byte UTF-8 sequence */ - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - /* RFC 3629 4: Second byte of two byte UTF-8 sequence */ - case MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1: - /* RFC 3629 4: Third byte of three byte UTF-8 sequence */ - case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2: - /* RFC 3629 4: Fourth byte of four byte UTF-8 sequence */ - case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3: - if ((0x80 <= character) && (0xBF >= character)) - { - utf8_step_ = MHD_WEBSOCKET_UTF8STEP_NORMAL; - } - else - { - /* RFC 3629 4: Invalid UTF-8 byte */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - break; - - default: - /* Invalid last step...? */ - if (NULL != buf_offset) - *buf_offset = i; - return MHD_WebSocket_UTF8Result_Invalid; - } - } - - /* return values */ - if (NULL != utf8_step) - *utf8_step = utf8_step_; - if (NULL != buf_offset) - *buf_offset = buf_len; - if (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step_) - { - return MHD_WebSocket_UTF8Result_Incomplete; - } - return MHD_WebSocket_UTF8Result_Valid; -} - - -/** - * Generates a mask for masking by calling - * a random number generator. - */ -static uint32_t -MHD_websocket_generate_mask (struct MHD_WebSocketStream *ws) -{ - unsigned char mask_[4]; - if (NULL != ws->rng) - { - size_t offset = 0; - while (offset < 4) - { - size_t encoded = ws->rng (ws->cls_rng, - mask_ + offset, - 4 - offset); - offset += encoded; - } - } - else - { - /* this case should never happen */ - mask_ [0] = 0; - mask_ [1] = 0; - mask_ [2] = 0; - mask_ [3] = 0; - } - - return *((uint32_t *) mask_); -} - - -/** - * Calls the malloc function associated with the websocket steam - */ -_MHD_EXTERN void * -MHD_websocket_malloc (struct MHD_WebSocketStream *ws, - size_t buf_len) -{ - if (NULL == ws) - { - return NULL; - } - - return ws->malloc (buf_len); -} - - -/** - * Calls the realloc function associated with the websocket steam - */ -_MHD_EXTERN void * -MHD_websocket_realloc (struct MHD_WebSocketStream *ws, - void *buf, - size_t new_buf_len) -{ - if (NULL == ws) - { - return NULL; - } - - return ws->realloc (buf, new_buf_len); -} - - -/** - * Calls the free function associated with the websocket steam - */ -_MHD_EXTERN int -MHD_websocket_free (struct MHD_WebSocketStream *ws, - void *buf) -{ - if (NULL == ws) - { - return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; - } - - ws->free (buf); - - return MHD_WEBSOCKET_STATUS_OK; -} - - -/** - * Converts a 16 bit value into network byte order (MSB first) - * in dependence of the host system - */ -static uint16_t -MHD_htons (uint16_t value) -{ - uint16_t endian = 0x0001; - - if (((char *) &endian)[0] == 0x01) - { - /* least significant byte first */ - ((char *) &endian)[0] = ((char *) &value)[1]; - ((char *) &endian)[1] = ((char *) &value)[0]; - return endian; - } - else - { - /* most significant byte first */ - return value; - } -} - - -/** - * Converts a 64 bit value into network byte order (MSB first) - * in dependence of the host system - */ -static uint64_t -MHD_htonll (uint64_t value) -{ - uint64_t endian = 0x0000000000000001; - - if (((char *) &endian)[0] == 0x01) - { - /* least significant byte first */ - ((char *) &endian)[0] = ((char *) &value)[7]; - ((char *) &endian)[1] = ((char *) &value)[6]; - ((char *) &endian)[2] = ((char *) &value)[5]; - ((char *) &endian)[3] = ((char *) &value)[4]; - ((char *) &endian)[4] = ((char *) &value)[3]; - ((char *) &endian)[5] = ((char *) &value)[2]; - ((char *) &endian)[6] = ((char *) &value)[1]; - ((char *) &endian)[7] = ((char *) &value)[0]; - return endian; - } - else - { - /* most significant byte first */ - return value; - } -} diff --git a/src/microhttpd_ws/sha1.c b/src/microhttpd_ws/sha1.c @@ -1,378 +0,0 @@ -/* - This file is part of libmicrohttpd - Copyright (C) 2019-2021 Karlson2k (Evgeny Grin) - - libmicrohttpd is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. - If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * @file microhttpd/sha1.c - * @brief Calculation of SHA-1 digest as defined in FIPS PUB 180-4 (2015) - * @author Karlson2k (Evgeny Grin) - */ - -#include "sha1.h" - -#include <string.h> -#ifdef HAVE_MEMORY_H -#include <memory.h> -#endif /* HAVE_MEMORY_H */ -#include "mhd_bithelpers.h" -#include "mhd_assert.h" - -/** - * Initialise structure for SHA-1 calculation. - * - * @param ctx_ must be a `struct sha1_ctx *` - */ -void -MHD_SHA1_init (void *ctx_) -{ - struct sha1_ctx *const ctx = ctx_; - /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.1 */ - /* Just some "magic" numbers defined by standard */ - ctx->H[0] = UINT32_C (0x67452301); - ctx->H[1] = UINT32_C (0xefcdab89); - ctx->H[2] = UINT32_C (0x98badcfe); - ctx->H[3] = UINT32_C (0x10325476); - ctx->H[4] = UINT32_C (0xc3d2e1f0); - - /* Initialise number of bytes. */ - ctx->count = 0; -} - - -/** - * Base of SHA-1 transformation. - * Gets full 512 bits / 64 bytes block of data and updates hash values; - * @param H hash values - * @param data data, must be exactly 64 bytes long - */ -static void -sha1_transform (uint32_t H[_SHA1_DIGEST_LENGTH], - const uint8_t data[SHA1_BLOCK_SIZE]) -{ - /* Working variables, - see FIPS PUB 180-4 paragraph 6.1.3 */ - uint32_t a = H[0]; - uint32_t b = H[1]; - uint32_t c = H[2]; - uint32_t d = H[3]; - uint32_t e = H[4]; - - /* Data buffer, used as cyclic buffer. - See FIPS PUB 180-4 paragraphs 5.2.1, 6.1.3 */ - uint32_t W[16]; - - /* 'Ch' and 'Maj' macro functions are defined with - widely-used optimization. - See FIPS PUB 180-4 formulae 4.1. */ -#define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) ) -#define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) ) - /* Unoptimized (original) versions: */ -/* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */ -/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */ -#define Par(x,y,z) ( (x) ^ (y) ^ (z) ) - - /* Single step of SHA-1 computation, - see FIPS PUB 180-4 paragraph 6.1.3 step 3. - * Note: instead of reassigning all working variables on each step, - variables are rotated for each step: - SHA1STEP32 (a, b, c, d, e, func, K00, W[0]); - SHA1STEP32 (e, a, b, c, d, func, K00, W[1]); - so current 'vC' will be used as 'vD' on the next step, - current 'vE' will be used as 'vA' on the next step. - * Note: 'wt' must be used exactly one time in this macro as it change other data as well - every time when used. */ - -#define SHA1STEP32(vA,vB,vC,vD,vE,ft,kt,wt) do { \ - (vE) += _MHD_ROTL32 ((vA), 5) + ft ((vB), (vC), (vD)) + (kt) + (wt); \ - (vB) = _MHD_ROTL32 ((vB), 30); } while (0) - - /* Get value of W(t) from input data buffer, - See FIPS PUB 180-4 paragraph 6.1.3. - Input data must be read in big-endian bytes order, - see FIPS PUB 180-4 paragraph 3.1.2. */ -#define GET_W_FROM_DATA(buf,t) \ - _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD) - -#ifndef _MHD_GET_32BIT_BE_UNALIGNED - if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN)) - { - /* Copy the unaligned input data to the aligned buffer */ - memcpy (W, data, SHA1_BLOCK_SIZE); - /* The W[] buffer itself will be used as the source of the data, - * but data will be reloaded in correct bytes order during - * the next steps */ - data = (uint8_t *) W; - } -#endif /* _MHD_GET_32BIT_BE_UNALIGNED */ - -/* SHA-1 values of Kt for t=0..19, see FIPS PUB 180-4 paragraph 4.2.1. */ -#define K00 UINT32_C(0x5a827999) -/* SHA-1 values of Kt for t=20..39, see FIPS PUB 180-4 paragraph 4.2.1.*/ -#define K20 UINT32_C(0x6ed9eba1) -/* SHA-1 values of Kt for t=40..59, see FIPS PUB 180-4 paragraph 4.2.1.*/ -#define K40 UINT32_C(0x8f1bbcdc) -/* SHA-1 values of Kt for t=60..79, see FIPS PUB 180-4 paragraph 4.2.1.*/ -#define K60 UINT32_C(0xca62c1d6) - - /* During first 16 steps, before making any calculations on each step, - the W element is read from input data buffer as big-endian value and - stored in array of W elements. */ - /* Note: instead of using K constants as array, all K values are specified - individually for each step. */ - SHA1STEP32 (a, b, c, d, e, Ch, K00, W[0] = GET_W_FROM_DATA (data, 0)); - SHA1STEP32 (e, a, b, c, d, Ch, K00, W[1] = GET_W_FROM_DATA (data, 1)); - SHA1STEP32 (d, e, a, b, c, Ch, K00, W[2] = GET_W_FROM_DATA (data, 2)); - SHA1STEP32 (c, d, e, a, b, Ch, K00, W[3] = GET_W_FROM_DATA (data, 3)); - SHA1STEP32 (b, c, d, e, a, Ch, K00, W[4] = GET_W_FROM_DATA (data, 4)); - SHA1STEP32 (a, b, c, d, e, Ch, K00, W[5] = GET_W_FROM_DATA (data, 5)); - SHA1STEP32 (e, a, b, c, d, Ch, K00, W[6] = GET_W_FROM_DATA (data, 6)); - SHA1STEP32 (d, e, a, b, c, Ch, K00, W[7] = GET_W_FROM_DATA (data, 7)); - SHA1STEP32 (c, d, e, a, b, Ch, K00, W[8] = GET_W_FROM_DATA (data, 8)); - SHA1STEP32 (b, c, d, e, a, Ch, K00, W[9] = GET_W_FROM_DATA (data, 9)); - SHA1STEP32 (a, b, c, d, e, Ch, K00, W[10] = GET_W_FROM_DATA (data, 10)); - SHA1STEP32 (e, a, b, c, d, Ch, K00, W[11] = GET_W_FROM_DATA (data, 11)); - SHA1STEP32 (d, e, a, b, c, Ch, K00, W[12] = GET_W_FROM_DATA (data, 12)); - SHA1STEP32 (c, d, e, a, b, Ch, K00, W[13] = GET_W_FROM_DATA (data, 13)); - SHA1STEP32 (b, c, d, e, a, Ch, K00, W[14] = GET_W_FROM_DATA (data, 14)); - SHA1STEP32 (a, b, c, d, e, Ch, K00, W[15] = GET_W_FROM_DATA (data, 15)); - - /* 'W' generation and assignment for 16 <= t <= 79. - See FIPS PUB 180-4 paragraph 6.1.3. - As only last 16 'W' are used in calculations, it is possible to - use 16 elements array of W as cyclic buffer. */ -#define Wgen(w,t) _MHD_ROTL32((w)[(t + 13) & 0xf] ^ (w)[(t + 8) & 0xf] \ - ^ (w)[(t + 2) & 0xf] ^ (w)[t & 0xf], 1) - - /* During last 60 steps, before making any calculations on each step, - W element is generated from W elements of cyclic buffer and generated value - stored back in cyclic buffer. */ - /* Note: instead of using K constants as array, all K values are specified - individually for each step, see FIPS PUB 180-4 paragraph 4.2.1. */ - SHA1STEP32 (e, a, b, c, d, Ch, K00, W[16 & 0xf] = Wgen (W, 16)); - SHA1STEP32 (d, e, a, b, c, Ch, K00, W[17 & 0xf] = Wgen (W, 17)); - SHA1STEP32 (c, d, e, a, b, Ch, K00, W[18 & 0xf] = Wgen (W, 18)); - SHA1STEP32 (b, c, d, e, a, Ch, K00, W[19 & 0xf] = Wgen (W, 19)); - SHA1STEP32 (a, b, c, d, e, Par, K20, W[20 & 0xf] = Wgen (W, 20)); - SHA1STEP32 (e, a, b, c, d, Par, K20, W[21 & 0xf] = Wgen (W, 21)); - SHA1STEP32 (d, e, a, b, c, Par, K20, W[22 & 0xf] = Wgen (W, 22)); - SHA1STEP32 (c, d, e, a, b, Par, K20, W[23 & 0xf] = Wgen (W, 23)); - SHA1STEP32 (b, c, d, e, a, Par, K20, W[24 & 0xf] = Wgen (W, 24)); - SHA1STEP32 (a, b, c, d, e, Par, K20, W[25 & 0xf] = Wgen (W, 25)); - SHA1STEP32 (e, a, b, c, d, Par, K20, W[26 & 0xf] = Wgen (W, 26)); - SHA1STEP32 (d, e, a, b, c, Par, K20, W[27 & 0xf] = Wgen (W, 27)); - SHA1STEP32 (c, d, e, a, b, Par, K20, W[28 & 0xf] = Wgen (W, 28)); - SHA1STEP32 (b, c, d, e, a, Par, K20, W[29 & 0xf] = Wgen (W, 29)); - SHA1STEP32 (a, b, c, d, e, Par, K20, W[30 & 0xf] = Wgen (W, 30)); - SHA1STEP32 (e, a, b, c, d, Par, K20, W[31 & 0xf] = Wgen (W, 31)); - SHA1STEP32 (d, e, a, b, c, Par, K20, W[32 & 0xf] = Wgen (W, 32)); - SHA1STEP32 (c, d, e, a, b, Par, K20, W[33 & 0xf] = Wgen (W, 33)); - SHA1STEP32 (b, c, d, e, a, Par, K20, W[34 & 0xf] = Wgen (W, 34)); - SHA1STEP32 (a, b, c, d, e, Par, K20, W[35 & 0xf] = Wgen (W, 35)); - SHA1STEP32 (e, a, b, c, d, Par, K20, W[36 & 0xf] = Wgen (W, 36)); - SHA1STEP32 (d, e, a, b, c, Par, K20, W[37 & 0xf] = Wgen (W, 37)); - SHA1STEP32 (c, d, e, a, b, Par, K20, W[38 & 0xf] = Wgen (W, 38)); - SHA1STEP32 (b, c, d, e, a, Par, K20, W[39 & 0xf] = Wgen (W, 39)); - SHA1STEP32 (a, b, c, d, e, Maj, K40, W[40 & 0xf] = Wgen (W, 40)); - SHA1STEP32 (e, a, b, c, d, Maj, K40, W[41 & 0xf] = Wgen (W, 41)); - SHA1STEP32 (d, e, a, b, c, Maj, K40, W[42 & 0xf] = Wgen (W, 42)); - SHA1STEP32 (c, d, e, a, b, Maj, K40, W[43 & 0xf] = Wgen (W, 43)); - SHA1STEP32 (b, c, d, e, a, Maj, K40, W[44 & 0xf] = Wgen (W, 44)); - SHA1STEP32 (a, b, c, d, e, Maj, K40, W[45 & 0xf] = Wgen (W, 45)); - SHA1STEP32 (e, a, b, c, d, Maj, K40, W[46 & 0xf] = Wgen (W, 46)); - SHA1STEP32 (d, e, a, b, c, Maj, K40, W[47 & 0xf] = Wgen (W, 47)); - SHA1STEP32 (c, d, e, a, b, Maj, K40, W[48 & 0xf] = Wgen (W, 48)); - SHA1STEP32 (b, c, d, e, a, Maj, K40, W[49 & 0xf] = Wgen (W, 49)); - SHA1STEP32 (a, b, c, d, e, Maj, K40, W[50 & 0xf] = Wgen (W, 50)); - SHA1STEP32 (e, a, b, c, d, Maj, K40, W[51 & 0xf] = Wgen (W, 51)); - SHA1STEP32 (d, e, a, b, c, Maj, K40, W[52 & 0xf] = Wgen (W, 52)); - SHA1STEP32 (c, d, e, a, b, Maj, K40, W[53 & 0xf] = Wgen (W, 53)); - SHA1STEP32 (b, c, d, e, a, Maj, K40, W[54 & 0xf] = Wgen (W, 54)); - SHA1STEP32 (a, b, c, d, e, Maj, K40, W[55 & 0xf] = Wgen (W, 55)); - SHA1STEP32 (e, a, b, c, d, Maj, K40, W[56 & 0xf] = Wgen (W, 56)); - SHA1STEP32 (d, e, a, b, c, Maj, K40, W[57 & 0xf] = Wgen (W, 57)); - SHA1STEP32 (c, d, e, a, b, Maj, K40, W[58 & 0xf] = Wgen (W, 58)); - SHA1STEP32 (b, c, d, e, a, Maj, K40, W[59 & 0xf] = Wgen (W, 59)); - SHA1STEP32 (a, b, c, d, e, Par, K60, W[60 & 0xf] = Wgen (W, 60)); - SHA1STEP32 (e, a, b, c, d, Par, K60, W[61 & 0xf] = Wgen (W, 61)); - SHA1STEP32 (d, e, a, b, c, Par, K60, W[62 & 0xf] = Wgen (W, 62)); - SHA1STEP32 (c, d, e, a, b, Par, K60, W[63 & 0xf] = Wgen (W, 63)); - SHA1STEP32 (b, c, d, e, a, Par, K60, W[64 & 0xf] = Wgen (W, 64)); - SHA1STEP32 (a, b, c, d, e, Par, K60, W[65 & 0xf] = Wgen (W, 65)); - SHA1STEP32 (e, a, b, c, d, Par, K60, W[66 & 0xf] = Wgen (W, 66)); - SHA1STEP32 (d, e, a, b, c, Par, K60, W[67 & 0xf] = Wgen (W, 67)); - SHA1STEP32 (c, d, e, a, b, Par, K60, W[68 & 0xf] = Wgen (W, 68)); - SHA1STEP32 (b, c, d, e, a, Par, K60, W[69 & 0xf] = Wgen (W, 69)); - SHA1STEP32 (a, b, c, d, e, Par, K60, W[70 & 0xf] = Wgen (W, 70)); - SHA1STEP32 (e, a, b, c, d, Par, K60, W[71 & 0xf] = Wgen (W, 71)); - SHA1STEP32 (d, e, a, b, c, Par, K60, W[72 & 0xf] = Wgen (W, 72)); - SHA1STEP32 (c, d, e, a, b, Par, K60, W[73 & 0xf] = Wgen (W, 73)); - SHA1STEP32 (b, c, d, e, a, Par, K60, W[74 & 0xf] = Wgen (W, 74)); - SHA1STEP32 (a, b, c, d, e, Par, K60, W[75 & 0xf] = Wgen (W, 75)); - SHA1STEP32 (e, a, b, c, d, Par, K60, W[76 & 0xf] = Wgen (W, 76)); - SHA1STEP32 (d, e, a, b, c, Par, K60, W[77 & 0xf] = Wgen (W, 77)); - SHA1STEP32 (c, d, e, a, b, Par, K60, W[78 & 0xf] = Wgen (W, 78)); - SHA1STEP32 (b, c, d, e, a, Par, K60, W[79 & 0xf] = Wgen (W, 79)); - - /* Compute intermediate hash. - See FIPS PUB 180-4 paragraph 6.1.3 step 4. */ - H[0] += a; - H[1] += b; - H[2] += c; - H[3] += d; - H[4] += e; -} - - -/** - * Process portion of bytes. - * - * @param ctx_ must be a `struct sha1_ctx *` - * @param data bytes to add to hash - * @param length number of bytes in @a data - */ -void -MHD_SHA1_update (void *ctx_, - const uint8_t *data, - size_t length) -{ - struct sha1_ctx *const ctx = ctx_; - unsigned bytes_have; /**< Number of bytes in buffer */ - - mhd_assert ((data != NULL) || (length == 0)); - - if (0 == length) - return; /* Do nothing */ - - /* Note: (count & (SHA1_BLOCK_SIZE-1)) - equal (count % SHA1_BLOCK_SIZE) for this block size. */ - bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1)); - ctx->count += length; - - if (0 != bytes_have) - { - unsigned bytes_left = SHA1_BLOCK_SIZE - bytes_have; - if (length >= bytes_left) - { /* Combine new data with the data in the buffer and - process the full block. */ - memcpy (ctx->buffer + bytes_have, - data, - bytes_left); - data += bytes_left; - length -= bytes_left; - sha1_transform (ctx->H, ctx->buffer); - bytes_have = 0; - } - } - - while (SHA1_BLOCK_SIZE <= length) - { /* Process any full blocks of new data directly, - without copying to the buffer. */ - sha1_transform (ctx->H, data); - data += SHA1_BLOCK_SIZE; - length -= SHA1_BLOCK_SIZE; - } - - if (0 != length) - { /* Copy incomplete block of new data (if any) - to the buffer. */ - memcpy (ctx->buffer + bytes_have, data, length); - } -} - - -/** - * Size of "length" padding addition in bytes. - * See FIPS PUB 180-4 paragraph 5.1.1. - */ -#define SHA1_SIZE_OF_LEN_ADD (64 / 8) - -/** - * Finalise SHA-1 calculation, return digest. - * - * @param ctx_ must be a `struct sha1_ctx *` - * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes - */ -void -MHD_SHA1_finish (void *ctx_, - uint8_t digest[SHA1_DIGEST_SIZE]) -{ - struct sha1_ctx *const ctx = ctx_; - uint64_t num_bits; /**< Number of processed bits */ - unsigned bytes_have; /**< Number of bytes in buffer */ - - num_bits = ctx->count << 3; - /* Note: (count & (SHA1_BLOCK_SIZE-1)) - equals (count % SHA1_BLOCK_SIZE) for this block size. */ - bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1)); - - /* Input data must be padded with bit "1" and with length of data in bits. - See FIPS PUB 180-4 paragraph 5.1.1. */ - /* Data is always processed in form of bytes (not by individual bits), - therefore position of first padding bit in byte is always predefined (0x80). */ - /* Buffer always have space at least for one byte (as full buffers are - processed immediately). */ - ctx->buffer[bytes_have++] = 0x80; - - if (SHA1_BLOCK_SIZE - bytes_have < SHA1_SIZE_OF_LEN_ADD) - { /* No space in current block to put total length of message. - Pad current block with zeros and process it. */ - if (SHA1_BLOCK_SIZE > bytes_have) - memset (ctx->buffer + bytes_have, 0, SHA1_BLOCK_SIZE - bytes_have); - /* Process full block. */ - sha1_transform (ctx->H, ctx->buffer); - /* Start new block. */ - bytes_have = 0; - } - - /* Pad the rest of the buffer with zeros. */ - memset (ctx->buffer + bytes_have, 0, - SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD - bytes_have); - /* Put the number of bits in the processed message as a big-endian value. */ - _MHD_PUT_64BIT_BE_SAFE (ctx->buffer + SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD, - num_bits); - /* Process the full final block. */ - sha1_transform (ctx->H, ctx->buffer); - - /* Put final hash/digest in BE mode */ -#ifndef _MHD_PUT_32BIT_BE_UNALIGNED - if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN) - { - uint32_t alig_dgst[_SHA1_DIGEST_LENGTH]; - _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]); - _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]); - _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]); - _MHD_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]); - _MHD_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]); - /* Copy result to unaligned destination address */ - memcpy (digest, alig_dgst, SHA1_DIGEST_SIZE); - } - else -#else /* _MHD_PUT_32BIT_BE_UNALIGNED */ - if (1) -#endif /* _MHD_PUT_32BIT_BE_UNALIGNED */ - { - _MHD_PUT_32BIT_BE (digest + 0 * SHA1_BYTES_IN_WORD, ctx->H[0]); - _MHD_PUT_32BIT_BE (digest + 1 * SHA1_BYTES_IN_WORD, ctx->H[1]); - _MHD_PUT_32BIT_BE (digest + 2 * SHA1_BYTES_IN_WORD, ctx->H[2]); - _MHD_PUT_32BIT_BE (digest + 3 * SHA1_BYTES_IN_WORD, ctx->H[3]); - _MHD_PUT_32BIT_BE (digest + 4 * SHA1_BYTES_IN_WORD, ctx->H[4]); - } - - /* Erase potentially sensitive data. */ - memset (ctx, 0, sizeof(struct sha1_ctx)); -} diff --git a/src/microhttpd_ws/sha1.h b/src/microhttpd_ws/sha1.h @@ -1,110 +0,0 @@ -/* - This file is part of libmicrohttpd - Copyright (C) 2019-2021 Karlson2k (Evgeny Grin) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. - If not, see <http://www.gnu.org/licenses/>. -*/ - -/** - * @file microhttpd/sha1.h - * @brief Calculation of SHA-1 digest - * @author Karlson2k (Evgeny Grin) - */ - -#ifndef MHD_SHA1_H -#define MHD_SHA1_H 1 - -#include "mhd_options.h" -#include <stdint.h> -#ifdef HAVE_STDDEF_H -#include <stddef.h> /* for size_t */ -#endif /* HAVE_STDDEF_H */ - -/** - * SHA-1 digest is kept internally as 5 32-bit words. - */ -#define _SHA1_DIGEST_LENGTH 5 - -/** - * Number of bits in single SHA-1 word - */ -#define SHA1_WORD_SIZE_BITS 32 - -/** - * Number of bytes in single SHA-1 word - */ -#define SHA1_BYTES_IN_WORD (SHA1_WORD_SIZE_BITS / 8) - -/** - * Size of SHA-1 digest in bytes - */ -#define SHA1_DIGEST_SIZE (_SHA1_DIGEST_LENGTH * SHA1_BYTES_IN_WORD) - -/** - * Size of SHA-1 digest string in chars including termination NUL - */ -#define SHA1_DIGEST_STRING_SIZE ((SHA1_DIGEST_SIZE) * 2 + 1) - -/** - * Size of single processing block in bits - */ -#define SHA1_BLOCK_SIZE_BITS 512 - -/** - * Size of single processing block in bytes - */ -#define SHA1_BLOCK_SIZE (SHA1_BLOCK_SIZE_BITS / 8) - - -struct sha1_ctx -{ - uint32_t H[_SHA1_DIGEST_LENGTH]; /**< Intermediate hash value / digest at end of calculation */ - uint8_t buffer[SHA1_BLOCK_SIZE]; /**< SHA256 input data buffer */ - uint64_t count; /**< number of bytes, mod 2^64 */ -}; - -/** - * Initialise structure for SHA-1 calculation. - * - * @param ctx must be a `struct sha1_ctx *` - */ -void -MHD_SHA1_init (void *ctx_); - - -/** - * Process portion of bytes. - * - * @param ctx_ must be a `struct sha1_ctx *` - * @param data bytes to add to hash - * @param length number of bytes in @a data - */ -void -MHD_SHA1_update (void *ctx_, - const uint8_t *data, - size_t length); - - -/** - * Finalise SHA-1 calculation, return digest. - * - * @param ctx_ must be a `struct sha1_ctx *` - * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes - */ -void -MHD_SHA1_finish (void *ctx_, - uint8_t digest[SHA1_DIGEST_SIZE]); - -#endif /* MHD_SHA1_H */ diff --git a/src/microhttpd_ws/test_websocket.c b/src/microhttpd_ws/test_websocket.c @@ -1,10105 +0,0 @@ -/* - This file is part of libmicrohttpd - Copyright (C) 2021 David Gausmann - - libmicrohttpd is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - libmicrohttpd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -/** - * @file test_websocket.c - * @brief Testcase for WebSocket decoding/encoding - * @author David Gausmann - */ -#include "microhttpd.h" -#include "microhttpd_ws.h" -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdint.h> -#include <time.h> - -#if SIZE_MAX >= 0x100000000 - #define ENABLE_64BIT_TESTS 1 -#endif - -int disable_alloc = 0; -size_t open_allocs = 0; - -/** - * Custom `malloc()` function used for memory tests - */ -static void * -test_malloc (size_t buf_len) -{ - if (0 != disable_alloc) - return NULL; - void *result = malloc (buf_len); - if (NULL != result) - ++open_allocs; - return result; -} - - -/** - * Custom `realloc()` function used for memory tests - */ -static void * -test_realloc (void *buf, size_t buf_len) -{ - if (0 != disable_alloc) - return NULL; - void *result = realloc (buf, buf_len); - if ((NULL != result) && (NULL == buf)) - ++open_allocs; - return result; -} - - -/** - * Custom `free()` function used for memory tests - */ -static void -test_free (void *buf) -{ - if (NULL != buf) - --open_allocs; - free (buf); -} - - -/** - * Custom `rng()` function used for client mode tests - */ -static size_t -test_rng (void *cls, void *buf, size_t buf_len) -{ - for (size_t i = 0; i < buf_len; ++i) - { - ((char *) buf) [i] = (char) (rand () % 0xFF); - } - - return buf_len; -} - - -/** - * Helper function which allocates a big amount of data - */ -static void -allocate_length_test_data (char **buf1, - char **buf2, - size_t buf_len, - const char *buf1_prefix, - size_t buf1_prefix_len) -{ - if (NULL != *buf1) - free (*buf1); - if (NULL != *buf2) - free (*buf2); - *buf1 = (char *) malloc (buf_len + buf1_prefix_len); - *buf2 = (char *) malloc (buf_len); - if ((NULL == buf1) || (NULL == buf2)) - return; - memcpy (*buf1, - buf1_prefix, - buf1_prefix_len); - for (size_t i = 0; i < buf_len; i += 64) - { - size_t bytes_to_copy = buf_len - i; - if (64 < bytes_to_copy) - bytes_to_copy = 64; - memcpy (*buf1 + i + buf1_prefix_len, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", - bytes_to_copy); - memcpy (*buf2 + i, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", - bytes_to_copy); - } -} - - -/** - * Helper function which performs a single decoder test - */ -static int -test_decode_single (unsigned int test_line, - int flags, size_t max_payload_size, size_t decode_count, - size_t buf_step, - const char *buf, size_t buf_len, - const char *expected_payload, size_t expected_payload_len, - int expected_return, int expected_valid, size_t - expected_streambuf_read_len) -{ - struct MHD_WebSocketStream *ws = NULL; - int ret = MHD_WEBSOCKET_STATUS_OK; - - /* initialize stream */ - ret = MHD_websocket_stream_init2 (&ws, - flags, - max_payload_size, - malloc, - realloc, - free, - NULL, - test_rng); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Allocation failed for decode test in line %u.\n", - (unsigned int) test_line); - return 1; - } - - /* perform decoding in a loop */ - size_t streambuf_read_len = 0; - size_t payload_len = 0; - char *payload = NULL; - for (size_t i = 0; i < decode_count; ++i) - { - size_t streambuf_read_len_ = 0; - size_t bytes_to_take = buf_len - streambuf_read_len; - if ((0 != buf_step) && (buf_step < bytes_to_take)) - bytes_to_take = buf_step; - ret = MHD_websocket_decode (ws, buf + streambuf_read_len, bytes_to_take, - &streambuf_read_len_, &payload, &payload_len); - streambuf_read_len += streambuf_read_len_; - if (i + 1 < decode_count) - { - if (payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - payload_len = 0; - } - } - } - - /* check the (last) result */ - if (ret != expected_return) - { - fprintf (stderr, - "Decode test failed in line %u: The return value should be %d, but is %d\n", - (unsigned int) test_line, - (int) expected_return, - (int) ret); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - if (payload_len != expected_payload_len) - { - fprintf (stderr, - "Decode test failed in line %u: The payload_len should be %u, but is %u\n", - (unsigned int) test_line, - (unsigned int) expected_payload_len, - (unsigned int) payload_len); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - if (0 != payload_len) - { - if (NULL == payload) - { - fprintf (stderr, - "Decode test failed in line %u: The payload is NULL\n", - (unsigned int) test_line); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - else if (NULL == expected_payload) - { - fprintf (stderr, - "Decode test failed in line %u: The expected_payload is NULL (wrong test declaration)\n", - (unsigned int) test_line); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - else if (0 != memcmp (payload, expected_payload, payload_len)) - { - fprintf (stderr, - "Decode test failed in line %u: The payload differs from the expected_payload\n", - (unsigned int) test_line); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - } - else - { - if (NULL != payload) - { - fprintf (stderr, - "Decode test failed in line %u: The payload is not NULL, but payload_len is 0\n", - (unsigned int) test_line); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - else if (NULL != expected_payload) - { - fprintf (stderr, - "Decode test failed in line %u: The expected_payload is not NULL, but expected_payload_len is 0 (wrong test declaration)\n", - (unsigned int) test_line); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - } - if (streambuf_read_len != expected_streambuf_read_len) - { - fprintf (stderr, - "Decode test failed in line %u: The streambuf_read_len should be %u, but is %u\n", - (unsigned int) test_line, - (unsigned int) expected_streambuf_read_len, - (unsigned int) streambuf_read_len); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - ret = MHD_websocket_stream_is_valid (ws); - if (ret != expected_valid) - { - fprintf (stderr, - "Decode test failed in line %u: The stream validity should be %u, but is %u\n", - (unsigned int) test_line, - (int) expected_valid, - (int) ret); - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - return 1; - } - - /* cleanup */ - MHD_websocket_free (ws, payload); - MHD_websocket_stream_free (ws); - - return 0; -} - - -/** - * Test procedure for `MHD_websocket_stream_init()` and - * `MHD_websocket_stream_init2()` - */ -int -test_inits () -{ - int failed = 0; - struct MHD_WebSocketStream *ws; - int ret; - - /* - ------------------------------------------------------------------------------ - All valid flags - ------------------------------------------------------------------------------ - */ - /* Regular test: all valid flags for init (only the even ones work) */ - for (int i = 0; i < 7; ++i) - { - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - i, - 0); - if (((0 == (i & MHD_WEBSOCKET_FLAG_CLIENT)) && - ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws))) || - ((0 != (i & MHD_WEBSOCKET_FLAG_CLIENT)) && - ((MHD_WEBSOCKET_STATUS_OK == ret) || - (NULL != ws)))) - { - fprintf (stderr, - "Init test failed in line %u for flags %d.\n", - (unsigned int) __LINE__, - (int) i); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - } - /* Regular test: all valid flags for init2 */ - for (int i = 0; i < 7; ++i) - { - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - i, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - test_rng); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for flags %d.\n", - (unsigned int) __LINE__, - (int) i); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - } - /* Fail test: Invalid flags for init */ - for (int i = 4; i < 32; ++i) - { - int flags = 1 << i; - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - flags, - 0); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u for invalid flags %d.\n", - (unsigned int) __LINE__, - (int) flags); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - } - /* Fail test: Invalid flag for init2 */ - for (int i = 4; i < 32; ++i) - { - int flags = 1 << i; - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - flags, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u for invalid flags %d.\n", - (unsigned int) __LINE__, - (int) flags); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - } - - /* - ------------------------------------------------------------------------------ - max_payload_size - ------------------------------------------------------------------------------ - */ - /* Regular test: max_payload_size = 0 for init */ - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: max_payload_size = 0 for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Edge test (success): max_payload_size = 1 for init */ - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 1); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 1.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Edge test (success): max_payload_size = 1 for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 1, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 1.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: max_payload_size = 1000 for init */ - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 1000); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 1000.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: max_payload_size = 1000 for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 1000, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 1000.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } -#ifdef ENABLE_64BIT_TESTS - /* Edge test (success): max_payload_size = 0x7FFFFFFFFFFFFFFF for init */ - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - (uint64_t) 0x7FFFFFFFFFFFFFFF); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0x7FFFFFFFFFFFFFFF.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Edge test (success): max_payload_size = 0x7FFFFFFFFFFFFFFF for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - (uint64_t) 0x7FFFFFFFFFFFFFFF, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0x7FFFFFFFFFFFFFFF.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Edge test (fail): max_payload_size = 0x8000000000000000 for init */ - ws = NULL; - ret = MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - (uint64_t) 0x8000000000000000); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0x8000000000000000.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Edge test (fail): max_payload_size = 0x8000000000000000 for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - (uint64_t) 0x8000000000000000, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u for max_payload_size 0x8000000000000000.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } -#endif - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: websocket stream variable missing for init */ - ws = NULL; - ret = MHD_websocket_stream_init (NULL, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Fail test: websocket stream variable missing for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (NULL, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Fail test: malloc missing for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - NULL, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Fail test: realloc missing for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - NULL, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Fail test: free missing for init2 */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - NULL, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: rng given for server mode (will be ignored) */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - test_rng); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: cls_rng given for server mode (will be ignored) */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - (void *) 12345, - test_rng); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Regular test: rng given for client mode */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - test_rng); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL == ws) ) - { - fprintf (stderr, - "Init test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - /* Fail test: rng not given for client mode */ - ws = NULL; - ret = MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != ws) ) - { - fprintf (stderr, - "Init test failed in line %u %u.\n", - (unsigned int) __LINE__, ret); - ++failed; - } - if (NULL != ws) - { - MHD_websocket_stream_free (ws); - ws = NULL; - } - - return failed != 0 ? 0x01 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_create_accept_header()` - */ -int -test_accept () -{ - int failed = 0; - char accept_key[29]; - int ret; - - /* - ------------------------------------------------------------------------------ - accepting - ------------------------------------------------------------------------------ - */ - /* Regular test: Test case from RFC6455 4.2.2 */ - memset (accept_key, 0, 29); - ret = MHD_websocket_create_accept_header ("dGhlIHNhbXBsZSBub25jZQ==", - accept_key); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != memcmp (accept_key, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", 29))) - { - fprintf (stderr, - "Accept test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: missing sec-key value */ - memset (accept_key, 0, 29); - ret = MHD_websocket_create_accept_header (NULL, - accept_key); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "Accept test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: missing accept variable */ - memset (accept_key, 0, 29); - ret = MHD_websocket_create_accept_header ("dGhlIHNhbXBsZSBub25jZQ==", - NULL); - if (MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) - { - fprintf (stderr, - "Accept test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x02 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_decode()` - */ -int -test_decodes () -{ - int failed = 0; - char *buf1 = NULL, *buf2 = NULL; - - /* - ------------------------------------------------------------------------------ - text frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Masked text frame from RFC 6455, must succeed for server */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", - 11, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Unmasked text frame from RFC 6455, must succeed for client */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x05\x48\x65\x6c\x6c\x6f", - 7, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Fail test: Unmasked text frame from RFC 6455, must fail for server */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x05\x48\x65\x6c\x6c\x6f", - 7, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Masked text frame from RFC 6455, must fail for client */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Text frame with UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x90\x00\x00\x00\x00" "This is my n" - "\xC3\xB6" "te", - 22, - "This is my n" "\xC3\xB6" "te", - 16, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 22); - /* Fail test: Text frame with with invalid UTF-8 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8F\x00\x00\x00\x00" "This is my n" "\xFF" - "te", - 21, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 18); - /* Fail test: Text frame with broken UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8F\x00\x00\x00\x00" "This is my n" "\xC3" - "te", - 21, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 19); - /* Regular test: Text frame without payload and mask (caller = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x80\x01\x02\x03\x04", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Fail test: Text frame without payload and no mask (caller = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Text frame without payload and mask (caller = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 2); - /* Fail test: Text frame without payload and no mask (caller = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x80\x01\x02\x03\x04", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - - /* - ------------------------------------------------------------------------------ - binary frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Masked binary frame (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", - 11, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Unmasked binary frame (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x05\x48\x65\x6c\x6c\x6f", - 7, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Fail test: Unmasked binary frame (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x05\x48\x65\x6c\x6c\x6f", - 7, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Masked binary frame (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Binary frame without payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Regular test: Fragmented binary frame without payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 12); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 12); - /* Regular test: Fragmented binary frame with payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", - 18, - "\x01\x02\x03\x04\x05\x06", - 6, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 18); - /* Regular test: Fragmented binary frame with payload, fragments to the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", - 18, - "\x01\x02\x03", - 3, - MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 9); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", - 18, - "\x04\x05\x06", - 3, - MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 18); - /* Regular test: Fragmented binary frame with payload, fragments to the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", - 36, - "\x01\x02\x03", - 3, - MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 9); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", - 36, - "\x04\x05\x06", - 3, - MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 18); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 3rd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 3, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", - 36, - "\x07\x08\x09", - 3, - MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 27); - /* Regular test: Fragmented binary frame without payload, fragments to the caller, 4th call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 4, - 0, - "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", - 36, - "\x0A\x0B\x0C", - 3, - MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 36); - /* Regular test: Binary frame with bytes which look like invalid UTF-8 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x85\x00\x00\x00\x00" "Hell\xf6", - 11, - "Hell\xf6", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Binary frame with bytes which look like broken UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x85\x00\x00\x00\x00" "H\xC3llo", - 11, - "H\xC3llo", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Binary frame with bytes which look like valid UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x82\x85\x00\x00\x00\x00" "H\xC3\xA4lo", - 11, - "H\xC3\xA4lo", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x02\x82\x00\x00\x00\x00" "H\xC3" - "\x80\x83\x00\x00\x00\x00" "\xA4lo", - 17, - "H\xC3\xA4lo", - 5, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence, - fragments to the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x02\x82\x00\x00\x00\x00" "H\xC3" - "\x80\x83\x00\x00\x00\x00" "\xA4lo", - 17, - "H\xC3", - 2, - MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 8); - /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence, - fragments to the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x02\x82\x00\x00\x00\x00" "H\xC3" - "\x80\x83\x00\x00\x00\x00" "\xA4lo", - 17, - "\xA4lo", - 3, - MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - - /* - ------------------------------------------------------------------------------ - close frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Close frame with no payload but with mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 6); - /* Regular test: Close frame with no payload (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 2); - /* Fail test: Close frame with no payload and no mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Close frame with no payload but with mask (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Close frame with 2 byte payload for close reason */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x82\x00\x00\x00\x00\x03\xEB", - 8, - "\x03\xEB", - 2, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 8); - /* Fail test: Close frame with 1 byte payload (no valid close reason) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x81\x00\x00\x00\x00\x03", - 7, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Close frame with close reason and UTF-8 description */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x95\x00\x00\x00\x00\x03\xEB" - "Something was wrong", - 27, - "\x03\xEB" "Something was wrong", - 21, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 27); - /* Regular test: Close frame with close reason and UTF-8 description (with UTF-8 sequence) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x96\x00\x00\x00\x00\x03\xEB" - "Something was wr" "\xC3\xB6" "ng", - 28, - "\x03\xEB" "Something was wr" "\xC3\xB6" "ng", - 22, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 28); - /* Fail test: Close frame with close reason and invalid UTF-8 in description */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x95\x00\x00\x00\x00\x03\xEB" - "Something was wr" "\xFF" "ng", - 27, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 24); - /* Fail test: Close frame with close reason and broken UTF-8 sequence in description */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x95\x00\x00\x00\x00\x03\xEB" - "Something was wr" "\xC3" "ng", - 27, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 25); - /* Edge test (success): Close frame with 125 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFD\x00\x00\x00\x00\x03\xEB" - "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. :-)", - 131, - "\x03\xEB" - "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. :-)", - 125, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 131); - /* Edge test (failure): Close frame with 126 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFE\x00\x7e\x00\x00\x00\x00\x03\xEB" - "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. >:-)", - 134, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Close frame with 500 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFE\x01\xf4\x00\x00\x00\x00\x03\xEB" - "The payload of this test isn't parsed.", - 49, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Edge test (failure): Close frame with 65535 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFE\xff\xff\x00\x00\x00\x00\x03\xEB" - "The payload of this test isn't parsed.", - 49, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Edge test (failure): Close frame with 65536 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFF\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xEB" - "The payload of this test isn't parsed.", - 54, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Close frame with 1000000 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\xFF\x00\x00\x00\x00\x00\x0F\x42\x40\x00\x00\x00\x00\x03\xEB" - "The payload of this test isn't parsed.", - 54, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - - /* - ------------------------------------------------------------------------------ - ping frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Ping frame with no payload but with mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Regular test: Ping frame with no payload (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 2); - /* Fail test: Ping frame with no payload and no mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Ping frame with no payload but with mask (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Ping frame with some (masked) payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x88\x01\x20\x03\x40\xFF\xFF\xFF\xFF\x00\x00\x00\x00", - 14, - "\xFE\xDF\xFC\xBF\x01\x20\x03\x40", - 8, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 14); - /* Edge test (success): Ping frame with one byte of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x81\x00\x00\x00\x00" "a", - 7, - "a", - 1, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Edge test (success): Ping frame with 125 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\xFD\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 131, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 131); - /* Edge test (fail): Ping frame with 126 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\xFE\x00\x7E\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 134, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Ping frame with UTF-8 data */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x90\x00\x00\x00\x00" "Ping is bin" - "\xC3\xA4" "ry.", - 22, - "Ping is bin" "\xC3\xA4" "ry.", - 16, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 22); - /* Regular test: Ping frame with invalid UTF-8 data */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x8F\x00\x00\x00\x00" "Ping is bin" "\xFF" - "ry.", - 21, - "Ping is bin" "\xFF" "ry.", - 15, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 21); - /* Regular test: Ping frame with broken UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x8F\x00\x00\x00\x00" "Ping is bin" "\xC3" - "ry.", - 21, - "Ping is bin" "\xC3" "ry.", - 15, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 21); - - /* - ------------------------------------------------------------------------------ - pong frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Pong frame with no payload but with mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Regular test: Pong frame with no payload (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 2); - /* Fail test: Pong frame with no payload and no mask (decoder = server) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x00", - 2, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Fail test: Pong frame with no payload but with mask (decoder = client) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_CLIENT - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Pong frame with some (masked) payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x88\x01\x20\x03\x40\xFF\xFF\xFF\xFF\x00\x00\x00\x00", - 14, - "\xFE\xDF\xFC\xBF\x01\x20\x03\x40", - 8, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 14); - /* Edge test (success): Pong frame with one byte of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x81\x00\x00\x00\x00" "a", - 7, - "a", - 1, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Edge test (success): Pong frame with 125 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\xFD\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 131, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 131); - /* Edge test (fail): Pong frame with 126 bytes of payload */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\xFE\x00\x7E\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 134, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 1); - /* Regular test: Pong frame with UTF-8 data */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x90\x00\x00\x00\x00" "Pong is bin" - "\xC3\xA4" "ry.", - 22, - "Pong is bin" "\xC3\xA4" "ry.", - 16, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 22); - /* Regular test: Pong frame with invalid UTF-8 data */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x8F\x00\x00\x00\x00" "Pong is bin" "\xFF" - "ry.", - 21, - "Pong is bin" "\xFF" "ry.", - 15, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 21); - /* Regular test: Pong frame with broken UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8A\x8F\x00\x00\x00\x00" "Pong is bin" "\xC3" - "ry.", - 21, - "Pong is bin" "\xC3" "ry.", - 15, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 21); - - /* - ------------------------------------------------------------------------------ - fragmentation - ------------------------------------------------------------------------------ - */ - /* Regular test: Fragmented, masked text frame, we are the server and don't want fragments as caller */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", - 17, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented, masked text frame, we are the server and don't want fragments as caller, but call decode two times */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, one call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", - 17, - "Hel", - 3, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 9); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, second call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", - 17, - "lo", - 2, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, third call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 3, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", - 23, - "Hel", - 3, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 9); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", - 23, - "l", - 1, - MHD_WEBSOCKET_STATUS_TEXT_NEXT_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 3rd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 3, - 0, - "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", - 23, - "o", - 1, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 23); - - - /* - ------------------------------------------------------------------------------ - invalid flags - ------------------------------------------------------------------------------ - */ - /* Regular test: Template with valid data for the next tests (this one must succeed) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Fail test: RSV1 flag set */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x91\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: RSV2 flag set */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\xA1\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: RSV3 flag set */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\xC1\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - - /* - ------------------------------------------------------------------------------ - invalid opcodes - ------------------------------------------------------------------------------ - */ - /* Fail test: Invalid opcode 0 (0 is usually valid, but only if there was a data frame before) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x80\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 3 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x83\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 4 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x84\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 5 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x85\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 6 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x86\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 7 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x87\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 0x0B */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8B\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 0x0C */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8c\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 0x0D */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8d\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 0x0E */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8e\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Invalid opcode 0x0F */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x8f\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - - - /* - ------------------------------------------------------------------------------ - control frames without FIN flag - ------------------------------------------------------------------------------ - */ - /* Fail test: Close frame without FIN flag */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x08\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Ping frame without FIN flag */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x09\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Fail test: Pong frame without FIN flag */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x0a\x85\x00\x00\x00\x00Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - - /* - ------------------------------------------------------------------------------ - length checks (without max_payload_len) - ------------------------------------------------------------------------------ - */ - /* Edge test (success): 0 bytes of payload (requires 1 byte length) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x80\x00\x00\x00\x00", - 6, - NULL, - 0, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 6); - /* Edge test (success): 1 byte of payload (requires 1 byte length) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x81\x00\x00\x00\x00" "a", - 7, - "a", - 1, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Edge test (success): 125 bytes of payload (requires 1 byte length) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xfd\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 131, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 131); - /* Edge test (success): 126 bytes of payload (requires 2 byte length) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xfe\x00\x7e\x00\x00\x00\x00" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 134, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 126, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 134); - /* Edge test (success): 65535 bytes of payload (requires 2 byte length) */ - allocate_length_test_data (&buf1, - &buf2, - 65535, - "\x81\xfe\xff\xff\x00\x00\x00\x00", - 8); - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - buf1, - 65535 + 8, - buf2, - 65535, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 65535 + 8); - /* Edge test (success): 65536 bytes of payload (requires 8 byte length) */ - allocate_length_test_data (&buf1, - &buf2, - 65536, - "\x81\xff\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00", - 14); - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - buf1, - 65536 + 14, - buf2, - 65536, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 65536 + 14); - /* Regular test: 1 MB of payload */ - allocate_length_test_data (&buf1, - &buf2, - 1048576, - "\x81\xff\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00", - 14); - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - buf1, - 1048576 + 14, - buf2, - 1048576, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 1048576 + 14); - /* Regular test: 100 MB of payload */ - allocate_length_test_data (&buf1, - &buf2, - 104857600, - "\x81\xff\x00\x00\x00\x00\x06\x40\x00\x00\x00\x00\x00\x00", - 14); - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - buf1, - 104857600 + 14, - buf2, - 104857600, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 104857600 + 14); - if (NULL != buf1) - { - free (buf1); - buf1 = NULL; - } - if (NULL != buf2) - { - free (buf2); - buf2 = NULL; - } -#ifdef ENABLE_64BIT_TESTS - /* Edge test (success): Maximum allowed length (here is only the header checked) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\x7f\xff\xff\xff\xff\xff\xff\xff", - 10, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 10); -#else - /* Edge test (fail): Maximum allowed length - (the size is allowed, but the system cannot handle this amount of memory) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\x7f\xff\xff\xff\xff\xff\xff\xff", - 10, - NULL, - 0, - MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); -#endif - /* Edge test (fail): Too big payload length */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\x80\x00\x00\x00\x00\x00\x00\x00", - 10, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - /* Edge test (fail): Too big payload length */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff", - 10, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - /* Fail test: Not the smallest payload length syntax used (2 byte instead of 1 byte) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xfe\x00\x05\x00\x00\x00\x00" "abcde", - 13, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 4); - /* Fail test: Not the smallest payload length syntax used (8 byte instead of 1 byte) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00" - "abcde", - 13, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - /* Fail test: Not the smallest payload length syntax used (8 byte instead of 2 byte) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\xff\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00" - "abcde", - 13, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - - /* - ------------------------------------------------------------------------------ - length checks (with max_payload_len) - ------------------------------------------------------------------------------ - */ - /* Regular test: Frame with less payload than specified as limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 100, - 1, - 0, - "\x81\x85\x00\x00\x00\x00" "Hello", - 11, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Edge test (success): Frame with the same payload as the specified limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 5, - 1, - 0, - "\x81\x85\x00\x00\x00\x00" "Hello", - 11, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Edge test (fail): Frame with more payload than specified as limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 4, - 1, - 0, - "\x81\x85\x00\x00\x00\x00" "Hello", - 11, - NULL, - 0, - MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, - MHD_WEBSOCKET_VALIDITY_INVALID, - 2); - /* Regular test: Fragmented frames with the sum of payload less than specified as limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 100, - 1, - 0, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Edge test (success): Fragmented frames with the sum of payload equal to the specified limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 5, - 1, - 0, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Edge test (fail): Fragmented frames with the sum of payload more than specified as limit */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 4, - 1, - 0, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, - MHD_WEBSOCKET_VALIDITY_INVALID, - 15); - /* Edge test (success): Fragmented frames with the sum of payload greater than - the specified limit, but we take fragments (one call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 5, - 1, - 0, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - "Hel", - 3, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 9); - /* Edge test (success): Fragmented frames with the sum of payload greater than - the specified limit, but we take fragments (two calls) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 5, - 2, - 0, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - "lo", - 2, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - - /* - ------------------------------------------------------------------------------ - UTF-8 sequences - ------------------------------------------------------------------------------ - */ - /* Regular test: No UTF-8 characters */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 a ", - 16, - " a ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Fail test: A UTF-8 tail character without sequence start character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xA4 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Regular test: A two byte UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xC3\xA4 ", - 16, - " \xC3\xA4 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Fail test: A broken two byte UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xC3 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Fail test: A two byte UTF-8 sequence with one UTF-8 tail too much */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xC3\xA4\xA4 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 9); - /* Regular test: A three byte UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\x8F\x8F ", - 16, - " \xEF\x8F\x8F ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Fail test: A broken byte UTF-8 sequence (two of three bytes) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 9); - /* Fail test: A broken byte UTF-8 sequence (one of three bytes) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Fail test: A three byte UTF-8 sequence followed by one UTF-8 tail byte */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - /* Regular test: A four byte UTF-8 sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F\x8F ", - 16, - " \xF2\x8F\x8F\x8F ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Fail test: A broken four byte UTF-8 sequence (three of four bytes) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 10); - /* Fail test: A broken four byte UTF-8 sequence (two of four bytes) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF2\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 9); - /* Fail test: A broken four byte UTF-8 sequence (one of four bytes) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF2 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Fail test: A four byte UTF-8 sequence followed by UTF-8 tail */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 11); - /* Fail test: A five byte UTF-8 sequence (only up to four bytes allowed) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xFB\x8F\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Fail test: A six byte UTF-8 sequence (only up to four bytes allowed) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xFD\x8F\x8F\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Fail test: A seven byte UTF-8 sequence (only up to four bytes allowed) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xFE\x8F\x8F\x8F\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Fail test: A eight byte UTF-8 sequence (only up to four bytes allowed) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xFF\x8F\x8F\x8F\x8F\x8F\x8F\x8F ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Edge test (success): The maximum allowed UTF-8 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF4\x8F\xBF\xBF ", - 16, - " \xF4\x8F\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The maximum allowed UTF-8 character + 1 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF4\x90\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The last valid UTF8-1 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \x7F ", - 16, - " \x7F ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the last valid UTF8-1 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Edge test (fail): The value before the first valid UTF8-2 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xC1\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Edge test (success): The first valid UTF8-2 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xC2\x80 ", - 16, - " \xC2\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-2 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xDF\xBF ", - 16, - " \xDF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the lst valid UTF8-2 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE0\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): The value before the first valid UTF8-3 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE0\x9F\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-3 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE0\xA0\x80 ", - 16, - " \xE0\xA0\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-3 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE0\xBF\xBF ", - 16, - " \xE0\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the first valid UTF8-3 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE0\xC0\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-3 character (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xE1\x80\x80 ", - 16, - " \xE1\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-3 character (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEC\xBF\xBF ", - 16, - " \xEC\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the last valid UTF8-3 character (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEC\xC0\xBF ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): The value before the first valid UTF8-3 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xED\x7F\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-3 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xED\x80\x80 ", - 16, - " \xED\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-3 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xED\x9F\xBF ", - 16, - " \xED\x9F\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the last valid UTF8-3 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xED\xA0\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): The value before the first valid UTF8-3 character (tail 4) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEE\x7F\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-3 character (tail 4) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEE\x80\x80 ", - 16, - " \xEE\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-3 character (tail 4) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\xBF\xBF ", - 16, - " \xEF\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the last valid UTF8-3 character (tail 4) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\xBF\xC0 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 9); - /* Edge test (fail): The value after the last valid UTF8-3 character (tail 4) #2 */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xEF\xC0\xBF ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): The value before the first valid UTF8-4 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF0\x8F\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-4 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF0\x90\x80\x80 ", - 16, - " \xF0\x90\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-4 character (tail 1) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF0\xBF\xBF\xBF ", - 16, - " \xF0\xBF\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The first valid UTF8-4 character (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF1\x80\x80\x80 ", - 16, - " \xF1\x80\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-4 character (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF3\xBF\xBF\xBF ", - 16, - " \xF3\xBF\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): A value before the last valid UTF8-4 character in the second byte (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF3\x7F\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): A value after the last valid UTF8-4 character in the second byte (tail 2) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF3\xC0\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (success): The first valid UTF8-4 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF4\x80\x80\x80 ", - 16, - " \xF4\x80\x80\x80 ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (success): The last valid UTF8-4 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF4\x8F\xBF\xBF ", - 16, - " \xF4\x8F\xBF\xBF ", - 10, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 16); - /* Edge test (fail): The value after the last valid UTF8-4 character (tail 3) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF4\x90\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 8); - /* Edge test (fail): The first byte value the last valid UTF8-4 character */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x8A\x00\x00\x00\x00 \xF5\x90\x80\x80 ", - 16, - NULL, - 0, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - - /* - ------------------------------------------------------------------------------ - Unfinished UTF-8 sequence between fragmented text frame - ------------------------------------------------------------------------------ - */ - /* Regular test: UTF-8 sequence between fragments, no fragmentation for the caller */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x8D\x00\x00\x00\x00" "This is my n" - "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", - 28, - "This is my n" "\xC3\xB6" "te", - 16, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 28); - /* Regular test: UTF-8 sequence between fragments, fragmentation for the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x8D\x00\x00\x00\x00" "This is my n" - "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", - 28, - "This is my n", - 12, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 19); - /* Regular test: UTF-8 sequence between fragments, fragmentation for the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x8D\x00\x00\x00\x00" "This is my n" - "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", - 28, - "\xC3\xB6" "te", - 4, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 28); - /* Edge test (success): UTF-8 sequence between fragments, but nothing before, fragmentation for the caller, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x81\x00\x00\x00\x00\xC3\x80\x81\x00\x00\x00\x00\xB6", - 14, - NULL, - 0, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 7); - /* Edge test (success): UTF-8 sequence between fragments, but nothing before, fragmentation for the caller, 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x81\x00\x00\x00\x00\xC3\x80\x81\x00\x00\x00\x00\xB6", - 14, - "\xC3\xB6", - 2, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 14); - - /* - ------------------------------------------------------------------------------ - Decoding with broken stream - ------------------------------------------------------------------------------ - */ - /* Failure test: Invalid sequence */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\xFF\x81\x85\x00\x00\x00\x00" "Hello", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Failure test: Call after invalidated stream */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\xFF\x81\x85\x00\x00\x00\x00" "Hello", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_STREAM_BROKEN, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Failure test: Call after invalidated stream (but with different buffer) */ - { - struct MHD_WebSocketStream *ws; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0)) - { - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - ret = MHD_websocket_decode (ws, - "\xFF", - 1, - &streambuf_read_len, - &payload, - &payload_len); - if (MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR != ret) - { - fprintf (stderr, - "Test failed in line %u: The return value should be -1, but is %d\n", - (unsigned int) __LINE__, - (int) ret); - ++failed; - } - else - { - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00" "Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if (MHD_WEBSOCKET_STATUS_STREAM_BROKEN != ret) - { - fprintf (stderr, - "Test failed in line %u: The return value should be -2, but is %d\n", - (unsigned int) __LINE__, - (int) ret); - ++failed; - } - } - MHD_websocket_stream_free (ws); - } - else - { - fprintf (stderr, - "Individual test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - /* - ------------------------------------------------------------------------------ - frame after close frame - ------------------------------------------------------------------------------ - */ - /* Regular test: Close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x88\x80\x00\x00\x00\x00\x81\x85\x00\x00\x00\x00" - "Hello", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 6); - /* Failure test: Text frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x81\x85\x00\x00\x00\x00" - "Hello", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 6); - /* Failure test: Binary frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x82\x85\x00\x00\x00\x00" - "Hello", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 6); - /* Failure test: Continue frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x80\x85\x00\x00\x00\x00" - "Hello", - 17, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 6); - /* Regular test: Ping frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x89\x85\x00\x00\x00\x00" - "Hello", - 17, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 17); - /* Regular test: Pong frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x8A\x85\x00\x00\x00\x00" - "Hello", - 17, - "Hello", - 5, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 17); - /* Regular test: Close frame after close frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x88\x80\x00\x00\x00\x00\x88\x80\x00\x00\x00\x00", - 12, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 12); - - /* - ------------------------------------------------------------------------------ - decoding byte-by-byte - ------------------------------------------------------------------------------ - */ - /* Regular test: Text frame, 2 bytes per loop, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 2, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 2); - /* Regular test: Text frame, 2 bytes per loop, 11th call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 11, - 2, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 22); - /* Regular test: Text frame, 2 bytes per loop, 12th call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 12, - 2, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - "This is the test.", - 17, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 23); - /* Regular test: Text frame, 1 byte per loop, 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 1, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 1); - /* Regular test: Text frame, 1 byte per loop, 22nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 22, - 1, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - NULL, - 0, - MHD_WEBSOCKET_STATUS_OK, - MHD_WEBSOCKET_VALIDITY_VALID, - 22); - /* Regular test: Text frame, 1 byte per loop, 23rd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 23, - 1, - "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", - 23, - "This is the test.", - 17, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 23); - - /* - ------------------------------------------------------------------------------ - mix of fragmented data frames and control frames - ------------------------------------------------------------------------------ - */ - /* Regular test: Fragmented text frame mixed with one ping frame (1st call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x89\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented text frame mixed with one ping frame (2nd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x89\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - "This is the test.", - 17, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 35); - /* Regular test: Fragmented text frame mixed with one close frame (1st call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x88\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 17); - /* Fail test: Fragmented text frame mixed with one ping frame (2nd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x88\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 17); - /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (1st call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x89\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - "This ", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (2nd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x89\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 17); - /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (3rd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 3, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x89\x80\x00\x00\x00\x00" - "\x80\x8C\x00\x00\x00\x00" "is the test.", - 35, - "is the test.", - 12, - MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 35); - - /* - ------------------------------------------------------------------------------ - mix of fragmented data frames and data frames - ------------------------------------------------------------------------------ - */ - /* Fail test: Fragmented text frame mixed with one non-fragmented binary frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x82\x81\x00\x00\x00\x00" - "a\x80\x8C\x00\x00\x00\x00" "is the test.", - 36, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 11); - /* Regular test: Fragmented text frame mixed with one non-fragmented binary frame; the caller wants fragments; 1st call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x82\x81\x00\x00\x00\x00" - "a\x80\x8C\x00\x00\x00\x00" "is the test.", - 36, - "This ", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Fail test: Fragmented text frame mixed with one non-fragmented binary frame; the caller wants fragments; 2nd call */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0, - 2, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x82\x81\x00\x00\x00\x00" - "a\x80\x8C\x00\x00\x00\x00" "is the test.", - 36, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 11); - /* Fail test: Fragmented text frame mixed with one fragmented binary frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x02\x81\x00\x00\x00\x00" - "a\x80\x8C\x00\x00\x00\x00" "is the test.", - 36, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 11); - /* Fail test: Fragmented text frame, continue frame, non-fragmented binary frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x00\x8C\x00\x00\x00\x00" - "is the test.\x82\x81\x00\x00\x00\x00" "a", - 36, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 29); - /* Fail test: Fragmented text frame, continue frame, fragmented binary frame */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x01\x85\x00\x00\x00\x00" - "This \x00\x8C\x00\x00\x00\x00" - "is the test.\x02\x81\x00\x00\x00\x00" "a", - 36, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 29); - - /* - ------------------------------------------------------------------------------ - multiple data frames - ------------------------------------------------------------------------------ - */ - /* Regular test: Text frame, binary frame, text frame (1st call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x81\x85\x00\x00\x00\x00" - "This \x82\x87\x00\x00\x00\x00" - "is the \x81\x85\x00\x00\x00\x00" "test.", - 35, - "This ", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Text frame, binary frame, text frame (2nd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x81\x85\x00\x00\x00\x00" - "This \x82\x87\x00\x00\x00\x00" - "is the \x81\x85\x00\x00\x00\x00" "test.", - 35, - "is the ", - 7, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 24); - /* Regular test: Text frame, binary frame, text frame (3rd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 3, - 0, - "\x81\x85\x00\x00\x00\x00" - "This \x82\x87\x00\x00\x00\x00" - "is the \x81\x85\x00\x00\x00\x00" "test.", - 35, - "test.", - 5, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 35); - /* - ------------------------------------------------------------------------------ - multiple control frames - ------------------------------------------------------------------------------ - */ - /* Regular test: Ping frame, pong frame, close frame (1st call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - "\x89\x85\x00\x00\x00\x00" - "This \x8A\x87\x00\x00\x00\x00" - "is the \x88\x85\x00\x00\x00\x00" "test.", - 35, - "This ", - 5, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 11); - /* Regular test: Ping frame, pong frame, close frame (2nd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 2, - 0, - "\x89\x85\x00\x00\x00\x00" - "This \x8A\x87\x00\x00\x00\x00" - "is the \x88\x85\x00\x00\x00\x00" "test.", - 35, - "is the ", - 7, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - 24); - /* Regular test: Ping frame, pong frame, close frame (3rd call) */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 3, - 0, - "\x89\x85\x00\x00\x00\x00" - "This \x8A\x87\x00\x00\x00\x00" - "is the \x88\x85\x00\x00\x00\x00" "test.", - 35, - "test.", - 5, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - 35); - - /* - ------------------------------------------------------------------------------ - generated close frames for errors - ------------------------------------------------------------------------------ - */ - /* Regular test: Close frame generated for protocol error */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS - | - MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, - 0, - 1, - 0, - "\xFF", - 1, - "\x88\x02\x03\xEA", - 4, - MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 0); - /* Regular test: Close frame generated for UTF-8 sequence error */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS - | - MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, - 0, - 1, - 0, - "\x81\x85\x00\x00\x00\x00T\xFFst.", - 11, - "\x88\x02\x03\xEF", - 4, - MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, - MHD_WEBSOCKET_VALIDITY_INVALID, - 7); - /* Regular test: Close frame generated for message size exceeded */ - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS - | - MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, - 3, - 1, - 0, - "\x81\x85\x00\x00\x00\x00T\xFFst.", - 11, - "\x88\x02\x03\xF1", - 4, - MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, - MHD_WEBSOCKET_VALIDITY_INVALID, - 2); - - /* - ------------------------------------------------------------------------------ - terminating NUL character - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *ws; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0)) - { - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - - /* Regular test: text frame */ - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00" "Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || - (5 != payload_len) || - (NULL == payload) || - (0 != memcmp ("Hello", payload, 5 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: text frame fragment */ - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || - (5 != payload_len) || - (NULL == payload) || - (0 != memcmp ("Hello", payload, 5 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: binary frame */ - ret = MHD_websocket_decode (ws, - "\x82\x85\x00\x00\x00\x00" "Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_BINARY_FRAME != ret) || - (5 != payload_len) || - (NULL == payload) || - (0 != memcmp ("Hello", payload, 5 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: binary frame fragment */ - ret = MHD_websocket_decode (ws, - "\x02\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_BINARY_FRAME != ret) || - (5 != payload_len) || - (NULL == payload) || - (0 != memcmp ("Hello", payload, 5 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - MHD_websocket_stream_free (ws); - } - else - { - fprintf (stderr, - "Individual decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - { - struct MHD_WebSocketStream *ws; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, - 0)) - { - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - - /* Regular test: text frame fragment (caller wants fragment, 1st call) */ - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo", - 17, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT != ret) || - (3 != payload_len) || - (NULL == payload) || - (0 != memcmp ("Hel", payload, 3 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: text frame fragment (caller wants fragment, 2nd call) */ - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" - "Hel\x80\x82\x00\x00\x00\x00" "lo" - + streambuf_read_len, - 17 - streambuf_read_len, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT != ret) || - (2 != payload_len) || - (NULL == payload) || - (0 != memcmp ("lo", payload, 2 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: text frame fragment with broken UTF-8 sequence (caller wants fragment, 1st call) */ - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" - "He\xC3\x80\x82\x00\x00\x00\x00" "\xB6o", - 17, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT != ret) || - (2 != payload_len) || - (NULL == payload) || - (0 != memcmp ("He", payload, 2 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - /* Regular test: text frame fragment with broken UTF-8 sequence (caller wants fragment, 2nd call) */ - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" - "He\xC3\x80\x82\x00\x00\x00\x00" "\xB6o" - + streambuf_read_len, - 17 - streambuf_read_len, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT != ret) || - (3 != payload_len) || - (NULL == payload) || - (0 != memcmp ("\xC3\xB6o", payload, 3 + 1))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - payload = NULL; - } - - MHD_websocket_stream_free (ws); - } - else - { - fprintf (stderr, - "Individual decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - - /* - ------------------------------------------------------------------------------ - invalid parameters - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *ws; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0)) - { - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - - /* Failure test: `ws` is NULL */ - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (NULL, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != payload) || - (0 != payload_len) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Failure test: `buf` is NULL, while `buf_len` != 0 */ - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - NULL, - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != payload) || - (0 != payload_len) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Failure test: `streambuf_read_len` is NULL */ - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - NULL, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != payload) || - (0 != payload_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Failure test: `payload` is NULL */ - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - NULL, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != payload_len) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Failure test: `payload_len` is NULL */ - payload = (char *) (uintptr_t) 0xBAADF00D; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != payload) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Regular test: `buf` is NULL and `buf_len` is 0 */ - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - NULL, - 0, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL != payload) || - (0 != payload_len) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Regular test: `buf` is not NULL and `buf_len` is 0 */ - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hello", - 0, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL != payload) || - (0 != payload_len) || - (0 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - - MHD_websocket_stream_free (ws); - } - else - { - fprintf (stderr, - "Parameter decode tests failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *ws; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - - /* Failure test: No memory allocation at the start */ - disable_alloc = 1; - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (NULL != payload) || - (0 != payload_len) || - (1000 == streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Failure test: No memory allocation after fragmented frame */ - disable_alloc = 0; - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x01\x83\x00\x00\x00\x00" "Hel", - 9, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (NULL != payload) || - (0 != payload_len) || - (9 != streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( - ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - disable_alloc = 1; - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - streambuf_read_len = 1000; - ret = MHD_websocket_decode (ws, - "\x80\x82\x00\x00\x00\x00" "lo", - 8, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (NULL != payload) || - (0 != payload_len) || - (1000 == streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( - ws))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - /* Regular test: Success after memory allocation ok again */ - /* (streambuf_read_len may not be overwritten for this test) */ - disable_alloc = 0; - payload = (char *) (uintptr_t) 0xBAADF00D; - payload_len = 0x87654321; - size_t old_streambuf_read_len = streambuf_read_len; - ret = MHD_websocket_decode (ws, - "\x80\x82\x00\x00\x00\x00lo" - + old_streambuf_read_len, - 8 - old_streambuf_read_len, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || - (NULL == payload) || - (5 != payload_len) || - (8 != streambuf_read_len + old_streambuf_read_len) || - (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( - ws)) || - (0 != memcmp ("Hello", payload, 5))) - { - fprintf (stderr, - "Decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == payload) - { - payload = NULL; - } - if (NULL != payload) - { - MHD_websocket_free (ws, payload); - } - - MHD_websocket_stream_free (ws); - } - else - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory decode tests failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - /* - ------------------------------------------------------------------------------ - memory leak test, when freeing while decoding - ------------------------------------------------------------------------------ - */ - { - disable_alloc = 0; - struct MHD_WebSocketStream *ws; - size_t streambuf_read_len = 0; - char *payload = NULL; - size_t payload_len = 0; - int ret = 0; - - /* Regular test: Free while decoding of data frame */ - open_allocs = 0; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - ret = MHD_websocket_decode (ws, - "\x81\x85\x00\x00\x00\x00Hel", - 9, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (9 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (0 != open_allocs) - { - fprintf (stderr, - "Memory decode test failed in line %u (memory leak detected)\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - - /* Regular test: Free while decoding of control frame */ - open_allocs = 0; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - ret = MHD_websocket_decode (ws, - "\x88\x85\x00\x00\x00\x00Hel", - 9, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (9 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (0 != open_allocs) - { - fprintf (stderr, - "Memory decode test failed in line %u (memory leak detected)\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - - /* Regular test: Free while decoding of fragmented data frame */ - open_allocs = 0; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - ret = MHD_websocket_decode (ws, - "\x01\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (11 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (0 != open_allocs) - { - fprintf (stderr, - "Memory decode test failed in line %u (memory leak detected)\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: Free while decoding of continued fragmented data frame */ - open_allocs = 0; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - ret = MHD_websocket_decode (ws, - "\x01\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (11 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_decode (ws, - "\x80\x85\x00\x00\x00\x00Hel", - 9, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (9 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (0 != open_allocs) - { - fprintf (stderr, - "Memory decode test failed in line %u (memory leak detected)\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: Free while decoding of control frame during fragmented data frame */ - open_allocs = 0; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, - MHD_WEBSOCKET_FLAG_SERVER - | - MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - ret = MHD_websocket_decode (ws, - "\x01\x85\x00\x00\x00\x00Hello", - 11, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (11 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_decode (ws, - "\x88\x85\x00\x00\x00\x00Hel", - 9, - &streambuf_read_len, - &payload, - &payload_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (0 != payload_len) || - (NULL != payload) || - (9 != streambuf_read_len) ) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - ret = MHD_websocket_stream_free (ws); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "Memory decode test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (0 != open_allocs) - { - fprintf (stderr, - "Memory decode test failed in line %u (memory leak detected)\n", - (unsigned int) __LINE__); - ++failed; - } - } - else - { - fprintf (stderr, - "Memory test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - { - free (buf1); - buf1 = NULL; - } - if (NULL != buf2) - { - free (buf2); - buf2 = NULL; - } - return failed != 0 ? 0x04 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_encode_text()` - */ -int -test_encodes_text () -{ - int failed = 0; - struct MHD_WebSocketStream *wss; - struct MHD_WebSocketStream *wsc; - int ret; - char *buf1 = NULL, *buf2 = NULL; - char *frame = NULL; - size_t frame_len = 0; - int utf8_step = 0; - - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, - MHD_WEBSOCKET_FLAG_CLIENT, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode text tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - return 0x08; - } - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, - MHD_WEBSOCKET_FLAG_SERVER, - 0)) - { - fprintf (stderr, - "No encode text tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - return 0x08; - } - - /* - ------------------------------------------------------------------------------ - Encoding - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data without UTF-8, we are server */ - ret = MHD_websocket_encode_text (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data without UTF-8, we are client */ - ret = MHD_websocket_encode_text (wsc, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (15 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "blablabla", - 9, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Some data with UTF-8, we are server */ - ret = MHD_websocket_encode_text (wss, - "bla" "\xC3\xA4" "blabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x0B" "bla" "\xC3\xA4" "blabla", 13))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data with UTF-8, we are client */ - ret = MHD_websocket_encode_text (wsc, - "bla" "\xC3\xA4" "blabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (17 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "bla" "\xC3\xA4" "blabla", - 11, - MHD_WEBSOCKET_STATUS_TEXT_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Edge test (success): Some data with NUL characters, we are server */ - ret = MHD_websocket_encode_text (wss, - "bla" "\0\0\0" "bla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x09" "bla" "\0\0\0" "bla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: Some data with broken UTF-8, we are server */ - ret = MHD_websocket_encode_text (wss, - "bla" "\xC3" "blabla", - 10, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Fragmentation - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data without UTF-8 */ - ret = MHD_websocket_encode_text (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x81\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: First fragment without UTF-8 */ - ret = MHD_websocket_encode_text (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_FIRST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x01\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Middle fragment without UTF-8 */ - ret = MHD_websocket_encode_text (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x00\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment without UTF-8 */ - ret = MHD_websocket_encode_text (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): First fragment with UTF-8 on the edge */ - ret = MHD_websocket_encode_text (wss, - "blablabl\xC3", - 9, - MHD_WEBSOCKET_FRAGMENTATION_FIRST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 != utf8_step) || - (0 != memcmp (frame, "\x01\x09" "blablabl\xC3", 11))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Last fragment with UTF-8 on the edge */ - ret = MHD_websocket_encode_text (wss, - "\xA4" "blablabla", - 10, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (12 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0A" "\xA4" "blablabla", 12))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: Last fragment with UTF-8 on the edge (here with wrong old utf8_step) */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; - ret = MHD_websocket_encode_text (wss, - "\xA4" "blablabla", - 10, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF2TAIL_1OF1 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1; - ret = MHD_websocket_encode_text (wss, - "\xA4" "blablabla", - 10, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (12 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0A" "\xA4" "blablabla", 12))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL1_1OF2 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2; - ret = MHD_websocket_encode_text (wss, - "\xA0\x80" "blablabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0B" "\xA0\x80" "blablabla", 13))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL2_1OF2 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2; - ret = MHD_websocket_encode_text (wss, - "\x80\x80" "blablabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0B" "\x80\x80" "blablabla", 13))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL_1OF2 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2; - ret = MHD_websocket_encode_text (wss, - "\x80\x80" "blablabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0B" "\x80\x80" "blablabla", 13))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL_2OF2 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; - ret = MHD_websocket_encode_text (wss, - "\x80" " blablabla", - 11, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0B" "\x80" " blablabla", 13))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL1_1OF3 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3; - ret = MHD_websocket_encode_text (wss, - "\x90\x80\x80" "blablabla", - 12, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (14 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0C" "\x90\x80\x80" "blablabla", 14))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL2_1OF3 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3; - ret = MHD_websocket_encode_text (wss, - "\x80\x80\x80" "blablabla", - 12, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (14 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0C" "\x80\x80\x80" "blablabla", 14))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_1OF3 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3; - ret = MHD_websocket_encode_text (wss, - "\x80\x80\x80" "blablabla", - 12, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (14 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0C" "\x80\x80\x80" "blablabla", 14))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_2OF3 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; - ret = MHD_websocket_encode_text (wss, - "\x80\x80" " blablabla", - 12, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (14 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0C" "\x80\x80" " blablabla", 14))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_3OF3 */ - utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3; - ret = MHD_websocket_encode_text (wss, - "\x80" " blablabla", - 12, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (14 != frame_len) || - (NULL == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x0C" "\x80" " blablabla", 14))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Length checks - ------------------------------------------------------------------------------ - */ - /* Edge test (success): Text frame without data */ - ret = MHD_websocket_encode_text (wss, - NULL, - 0, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x00", 2))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Text frame with 1 byte of data */ - ret = MHD_websocket_encode_text (wss, - "a", - 1, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (3 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x01" "a", 3))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Text frame with 125 bytes of data */ - ret = MHD_websocket_encode_text (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (127 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x7D" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 127))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Text frame with 126 bytes of data */ - ret = MHD_websocket_encode_text (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 126, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (130 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x7E\x00\x7E" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 130))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Text frame with 65535 bytes of data */ - allocate_length_test_data (&buf1, - &buf2, - 65535, - "\x81\x7E\xFF\xFF", - 4); - ret = MHD_websocket_encode_text (wss, - buf2, - 65535, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (65535 + 4 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 65535 + 4))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Text frame with 65536 bytes of data */ - allocate_length_test_data (&buf1, - &buf2, - 65536, - "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", - 10); - ret = MHD_websocket_encode_text (wss, - buf2, - 65536, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (65536 + 10 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 65536 + 10))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Text frame with 100 MB of data */ - allocate_length_test_data (&buf1, - &buf2, - 104857600, - "\x81\x7F\x00\x00\x00\x00\x06\x40\x00\x00", - 10); - ret = MHD_websocket_encode_text (wss, - buf2, - 104857600, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (104857600 + 10 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 104857600 + 10))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - if (NULL != buf1) - { - free (buf1); - buf1 = NULL; - } - if (NULL != buf2) - { - free (buf2); - buf2 = NULL; - } -#ifdef ENABLE_64BIT_TESTS - /* Fail test: frame_len is greater than 0x7FFFFFFFFFFFFFFF - (this is the maximum allowed payload size) */ - frame_len = 0; - ret = MHD_websocket_encode_text (wss, - "abc", - (uint64_t) 0x8000000000000000, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } -#endif - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `ws` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (NULL, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `payload_utf8` not passed, but `payload_utf8_len` != 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - NULL, - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `payload_utf8` passed, but `payload_utf8_len` == 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - "abc", - 0, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x81\x00", 2))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `frame` not passed */ - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - NULL, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: `frame_len` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - NULL, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `utf8_step` passed for non-fragmentation - (is allowed and `utf8_step` will be filled then) */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = -99; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x81\x03" "abc", 5))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `utf8_step` passed for non-fragmentation with invalid UTF-8 - (is allowed and `utf8_step` will be filled then) */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = -99; - ret = MHD_websocket_encode_text (wss, - "ab\xC3", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) || - (MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 != utf8_step) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `utf8_step` not passed for fragmentation #1 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_FIRST, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `utf8_step` not passed for fragmentation #2 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `utf8_step` not passed for fragmentation #3 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `utf8_step` passed for fragmentation #1 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = -99; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_FIRST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x01\x03" "abc", 5))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `utf8_step` passed for fragmentation #2 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x00\x03" "abc", 5))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `utf8_step` passed for fragmentation #3 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || - (0 != memcmp (frame, "\x80\x03" "abc", 5))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `fragmentation` has an invalid value */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - utf8_step = -99; - ret = MHD_websocket_encode_text (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_LAST + 1, - &frame, - &frame_len, - &utf8_step); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) || - (-99 != utf8_step) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *wsx; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Fail test: allocation while no memory available */ - disable_alloc = 1; - ret = MHD_websocket_encode_text (wsx, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - /* Regular test: allocation while memory is available again */ - disable_alloc = 0; - ret = MHD_websocket_encode_text (wsx, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x81\x03" "abc", 5))) - { - fprintf (stderr, - "Encode text test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - - MHD_websocket_stream_free (wsx); - } - else - { - fprintf (stderr, - "Couldn't perform memory test for text encoding in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - free (buf1); - if (NULL != buf2) - free (buf2); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - if (NULL != wss) - MHD_websocket_stream_free (wss); - - return failed != 0 ? 0x08 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_encode_binary()` - */ -int -test_encodes_binary () -{ - int failed = 0; - struct MHD_WebSocketStream *wss; - struct MHD_WebSocketStream *wsc; - int ret; - char *buf1 = NULL, *buf2 = NULL; - char *frame = NULL; - size_t frame_len = 0; - - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, - MHD_WEBSOCKET_FLAG_CLIENT, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode binary tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - return 0x10; - } - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, - MHD_WEBSOCKET_FLAG_SERVER, - 0)) - { - fprintf (stderr, - "No encode binary tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - return 0x10; - } - - /* - ------------------------------------------------------------------------------ - Encoding - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data, we are server */ - ret = MHD_websocket_encode_binary (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data, we are client */ - ret = MHD_websocket_encode_binary (wsc, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (15 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "blablabla", - 9, - MHD_WEBSOCKET_STATUS_BINARY_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Edge test (success): Some data with NUL characters, we are server */ - ret = MHD_websocket_encode_binary (wss, - "bla" "\0\0\0" "bla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x09" "bla" "\0\0\0" "bla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data which looks like broken UTF-8, we are server */ - ret = MHD_websocket_encode_binary (wss, - "bla" "\xC3" "blabla", - 10, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (12 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x0A" "bla" "\xC3" "blabla", 12))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Fragmentation - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data */ - ret = MHD_websocket_encode_binary (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: First fragment */ - ret = MHD_websocket_encode_binary (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_FIRST, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x02\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Middle fragment */ - ret = MHD_websocket_encode_binary (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x00\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Last fragment */ - ret = MHD_websocket_encode_binary (wss, - "blablabla", - 9, - MHD_WEBSOCKET_FRAGMENTATION_LAST, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x80\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Length checks - ------------------------------------------------------------------------------ - */ - /* Edge test (success): Binary frame without data */ - ret = MHD_websocket_encode_binary (wss, - NULL, - 0, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x00", 2))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Binary frame with 1 byte of data */ - ret = MHD_websocket_encode_binary (wss, - "a", - 1, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (3 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x01" "a", 3))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Binary frame with 125 bytes of data */ - ret = MHD_websocket_encode_binary (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (127 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x7D" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 127))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Binary frame with 126 bytes of data */ - ret = MHD_websocket_encode_binary (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 126, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (130 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x7E\x00\x7E" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 130))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Binary frame with 65535 bytes of data */ - allocate_length_test_data (&buf1, - &buf2, - 65535, - "\x82\x7E\xFF\xFF", - 4); - ret = MHD_websocket_encode_binary (wss, - buf2, - 65535, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (65535 + 4 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 65535 + 4))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Binary frame with 65536 bytes of data */ - allocate_length_test_data (&buf1, - &buf2, - 65536, - "\x82\x7F\x00\x00\x00\x00\x00\x01\x00\x00", - 10); - ret = MHD_websocket_encode_binary (wss, - buf2, - 65536, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (65536 + 10 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 65536 + 10))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Binary frame with 100 MB of data */ - allocate_length_test_data (&buf1, - &buf2, - 104857600, - "\x82\x7F\x00\x00\x00\x00\x06\x40\x00\x00", - 10); - ret = MHD_websocket_encode_binary (wss, - buf2, - 104857600, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (104857600 + 10 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, buf1, 104857600 + 10))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - if (NULL != buf1) - { - free (buf1); - buf1 = NULL; - } - if (NULL != buf2) - { - free (buf2); - buf2 = NULL; - } -#ifdef ENABLE_64BIT_TESTS - /* Fail test: `frame_len` is greater than 0x7FFFFFFFFFFFFFFF - (this is the maximum allowed payload size) */ - frame_len = 0; - ret = MHD_websocket_encode_binary (wss, - "abc", - (uint64_t) 0x8000000000000000, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } -#endif - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `ws` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_binary (NULL, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `payload` not passed, but `payload_len` != 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_binary (wss, - NULL, - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `payload` passed, but `payload_len` == 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_binary (wss, - "abc", - 0, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x82\x00", 2))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `frame` not passed */ - frame_len = 0x87654321; - ret = MHD_websocket_encode_binary (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - NULL, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: `frame_len` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - ret = MHD_websocket_encode_binary (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `fragmentation` has an invalid value */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_binary (wss, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_LAST + 1, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *wsx; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Fail test: allocation while no memory available */ - disable_alloc = 1; - ret = MHD_websocket_encode_binary (wsx, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - /* Regular test: allocation while memory is available again */ - disable_alloc = 0; - ret = MHD_websocket_encode_binary (wsx, - "abc", - 3, - MHD_WEBSOCKET_FRAGMENTATION_NONE, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x82\x03" "abc", 5))) - { - fprintf (stderr, - "Encode binary test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - - MHD_websocket_stream_free (wsx); - } - else - { - fprintf (stderr, - "Couldn't perform memory test for binary encoding in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - free (buf1); - if (NULL != buf2) - free (buf2); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - if (NULL != wss) - MHD_websocket_stream_free (wss); - - return failed != 0 ? 0x10 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_encode_close()` - */ -int -test_encodes_close () -{ - int failed = 0; - struct MHD_WebSocketStream *wss; - struct MHD_WebSocketStream *wsc; - int ret; - char *buf1 = NULL, *buf2 = NULL; - char *frame = NULL; - size_t frame_len = 0; - - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, - MHD_WEBSOCKET_FLAG_CLIENT, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode close tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - return 0x10; - } - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wss, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode close tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - return 0x10; - } - - /* - ------------------------------------------------------------------------------ - Encoding - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data, we are server */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x0B\x03\xE8" "blablabla", 13))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data, we are client */ - ret = MHD_websocket_encode_close (wsc, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (17 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "\x03\xE8" "blablabla", - 11, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Close reason without text, we are server */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (4 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Close reason without text, we are client */ - ret = MHD_websocket_encode_close (wsc, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (8 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "\x03\xE8", - 2, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Close without reason, we are server */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_NO_REASON, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x00", 2))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Close without reason, we are client */ - ret = MHD_websocket_encode_close (wsc, - MHD_WEBSOCKET_CLOSEREASON_NO_REASON, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (6 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - NULL, - 0, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Close with UTF-8 sequence in reason, we are client */ - ret = MHD_websocket_encode_close (wsc, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "bla" "\xC3\xA4" "blabla", - 11, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (19 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "\x03\xE8" "bla" "\xC3\xA4" "blabla", - 13, - MHD_WEBSOCKET_STATUS_CLOSE_FRAME, - MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Edge test (success): Close reason with NUL characters, we are server */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY, - "bla" "\0\0\0" "bla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (13 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x0B\x03\xE9" "bla" "\0\0\0" "bla", 13))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: Some data with broken UTF-8, we are server */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "bla" "\xC3" "blabla", - 10, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Length checks - ------------------------------------------------------------------------------ - */ - /* Edge test (success): Close frame without payload */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_NO_REASON, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x00", 2))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Close frame only reason code */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (4 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Close frame with 1 bytes of reason text */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "a", - 1, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x03\x03\xE8" "a", 5))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Close frame with 123 bytes of reason text */ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456", - 123, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (127 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x7D\x03\xE8" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456", - 127))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (fail): Close frame with 124 bytes of reason text*/ - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567", - 124, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `ws` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (NULL, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `payload` not passed, but `payload_len` != 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - NULL, - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `payload` passed, but `payload_len` == 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (4 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `frame` not passed */ - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 3, - NULL, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: `frame_len` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 3, - &frame, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: no reason code passed, but reason text */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - MHD_WEBSOCKET_CLOSEREASON_NO_REASON, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (fail): Invalid reason code */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - 1, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (fail): Invalid reason code */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - 999, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Custom reason code */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_close (wss, - 2000, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (7 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x88\x05\x07\xD0" "abc", 7))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *wsx; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Fail test: allocation while no memory available */ - disable_alloc = 1; - ret = MHD_websocket_encode_close (wsx, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - /* Regular test: allocation while memory is available again */ - disable_alloc = 0; - ret = MHD_websocket_encode_close (wsx, - MHD_WEBSOCKET_CLOSEREASON_REGULAR, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (7 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x88\x05\x03\xE8" "abc", 7))) - { - fprintf (stderr, - "Encode close test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - - MHD_websocket_stream_free (wsx); - } - else - { - fprintf (stderr, - "Couldn't perform memory test for close encoding in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - free (buf1); - if (NULL != buf2) - free (buf2); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - if (NULL != wss) - MHD_websocket_stream_free (wss); - - return failed != 0 ? 0x20 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_encode_ping()` - */ -int -test_encodes_ping () -{ - int failed = 0; - struct MHD_WebSocketStream *wss; - struct MHD_WebSocketStream *wsc; - int ret; - char *buf1 = NULL, *buf2 = NULL; - char *frame = NULL; - size_t frame_len = 0; - - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, - MHD_WEBSOCKET_FLAG_CLIENT, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode ping tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - return 0x10; - } - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, - MHD_WEBSOCKET_FLAG_SERVER, - 0)) - { - fprintf (stderr, - "No encode ping tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - return 0x10; - } - - /* - ------------------------------------------------------------------------------ - Encoding - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data, we are server */ - ret = MHD_websocket_encode_ping (wss, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data, we are client */ - ret = MHD_websocket_encode_ping (wsc, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (15 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "blablabla", - 9, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Ping without payload, we are server */ - ret = MHD_websocket_encode_ping (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x00", 2))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Ping without payload, we are client */ - ret = MHD_websocket_encode_ping (wsc, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (6 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Ping with something like UTF-8 sequence in payload, we are client */ - ret = MHD_websocket_encode_ping (wsc, - "bla" "\xC3\xA4" "blabla", - 11, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (17 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "bla" "\xC3\xA4" "blabla", - 11, - MHD_WEBSOCKET_STATUS_PING_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Edge test (success): Ping payload with NUL characters, we are server */ - ret = MHD_websocket_encode_ping (wss, - "bla" "\0\0\0" "bla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x09" "bla" "\0\0\0" "bla", 11))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Ping payload with with something which looks like broken UTF-8, we are server */ - ret = MHD_websocket_encode_ping (wss, - "bla" "\xC3" "blabla", - 10, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (12 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x0A" "bla" "\xC3" "blabla", 12))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Length checks - ------------------------------------------------------------------------------ - */ - /* Edge test (success): Ping frame without payload */ - ret = MHD_websocket_encode_ping (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x00", 2))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Ping frame with one byte of payload */ - ret = MHD_websocket_encode_ping (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x00", 2))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Ping frame with 125 bytes of payload */ - ret = MHD_websocket_encode_ping (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (127 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x7D" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 127))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (fail): Ping frame with 126 bytes of payload */ - ret = MHD_websocket_encode_ping (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 126, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `ws` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_ping (NULL, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `payload` not passed, but `payload_len` != 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_ping (wss, - NULL, - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `payload` passed, but `payload_len` == 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_ping (wss, - "abc", - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x89\x00", 2))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `frame` not passed */ - frame_len = 0x87654321; - ret = MHD_websocket_encode_ping (wss, - "abc", - 3, - NULL, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: `frame_len` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - ret = MHD_websocket_encode_ping (wss, - "abc", - 3, - &frame, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *wsx; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Fail test: allocation while no memory available */ - disable_alloc = 1; - ret = MHD_websocket_encode_ping (wsx, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - /* Regular test: allocation while memory is available again */ - disable_alloc = 0; - ret = MHD_websocket_encode_ping (wsx, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x89\x03" "abc", 5))) - { - fprintf (stderr, - "Encode ping test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - - MHD_websocket_stream_free (wsx); - } - else - { - fprintf (stderr, - "Couldn't perform memory test for ping encoding in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - free (buf1); - if (NULL != buf2) - free (buf2); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - if (NULL != wss) - MHD_websocket_stream_free (wss); - - return failed != 0 ? 0x40 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_encode_pong()` - */ -int -test_encodes_pong () -{ - int failed = 0; - struct MHD_WebSocketStream *wss; - struct MHD_WebSocketStream *wsc; - int ret; - char *buf1 = NULL, *buf2 = NULL; - char *frame = NULL; - size_t frame_len = 0; - - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, - MHD_WEBSOCKET_FLAG_CLIENT, - 0, - malloc, - realloc, - free, - NULL, - test_rng)) - { - fprintf (stderr, - "No encode pong tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - return 0x10; - } - if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, - MHD_WEBSOCKET_FLAG_SERVER, - 0)) - { - fprintf (stderr, - "No encode pong tests possible due to failed stream init in line %u\n", - (unsigned int) __LINE__); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - return 0x10; - } - - /* - ------------------------------------------------------------------------------ - Encoding - ------------------------------------------------------------------------------ - */ - /* Regular test: Some data, we are server */ - ret = MHD_websocket_encode_pong (wss, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x09" "blablabla", 11))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Some data, we are client */ - ret = MHD_websocket_encode_pong (wsc, - "blablabla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (15 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "blablabla", - 9, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Pong without payload, we are server */ - ret = MHD_websocket_encode_pong (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x00", 2))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Pong without payload, we are client */ - ret = MHD_websocket_encode_pong (wsc, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (6 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - NULL, - 0, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Regular test: Pong with something like UTF-8 sequence in payload, we are client */ - ret = MHD_websocket_encode_pong (wsc, - "bla" "\xC3\xA4" "blabla", - 11, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (17 != frame_len) || - (NULL == frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - else - { - failed += test_decode_single (__LINE__, - MHD_WEBSOCKET_FLAG_SERVER - | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, - 0, - 1, - 0, - frame, - frame_len, - "bla" "\xC3\xA4" "blabla", - 11, - MHD_WEBSOCKET_STATUS_PONG_FRAME, - MHD_WEBSOCKET_VALIDITY_VALID, - frame_len); - } - if (NULL != frame) - { - MHD_websocket_free (wsc, frame); - frame = NULL; - } - /* Edge test (success): Pong payload with NUL characters, we are server */ - ret = MHD_websocket_encode_pong (wss, - "bla" "\0\0\0" "bla", - 9, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (11 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x09" "bla" "\0\0\0" "bla", 11))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: Pong payload with with something which looks like broken UTF-8, we are server */ - ret = MHD_websocket_encode_pong (wss, - "bla" "\xC3" "blabla", - 10, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (12 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x0A" "bla" "\xC3" "blabla", 12))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Length checks - ------------------------------------------------------------------------------ - */ - /* Edge test (success): Pong frame without payload */ - ret = MHD_websocket_encode_pong (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x00", 2))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Pong frame with one byte of payload */ - ret = MHD_websocket_encode_pong (wss, - NULL, - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x00", 2))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (success): Pong frame with 125 bytes of payload */ - ret = MHD_websocket_encode_pong (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 125, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (127 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x7D" - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", - 127))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Edge test (fail): Pong frame with 126 bytes of payload */ - ret = MHD_websocket_encode_pong (wss, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", - 126, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `ws` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_pong (NULL, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `payload` not passed, but `payload_len` != 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_pong (wss, - NULL, - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Regular test: `payload` passed, but `payload_len` == 0 */ - frame = (char *) (uintptr_t) 0xBAADF00D; - frame_len = 0x87654321; - ret = MHD_websocket_encode_pong (wss, - "abc", - 0, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (2 != frame_len) || - (NULL == frame) || - (((char *) (uintptr_t) 0xBAADF00D) == frame) || - (0 != memcmp (frame, "\x8A\x00", 2))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - /* Fail test: `frame` not passed */ - frame_len = 0x87654321; - ret = MHD_websocket_encode_pong (wss, - "abc", - 3, - NULL, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (0 != frame_len) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: `frame_len` not passed */ - frame = (char *) (uintptr_t) 0xBAADF00D; - ret = MHD_websocket_encode_pong (wss, - "abc", - 3, - &frame, - NULL); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (((char *) (uintptr_t) 0xBAADF00D) == frame) - { - frame = NULL; - } - if (NULL != frame) - { - MHD_websocket_free (wss, frame); - frame = NULL; - } - - /* - ------------------------------------------------------------------------------ - validity after temporary out-of-memory - ------------------------------------------------------------------------------ - */ - { - struct MHD_WebSocketStream *wsx; - if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, - MHD_WEBSOCKET_FLAG_SERVER, - 0, - test_malloc, - test_realloc, - test_free, - NULL, - NULL)) - { - /* Fail test: allocation while no memory available */ - disable_alloc = 1; - ret = MHD_websocket_encode_pong (wsx, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || - (0 != frame_len) || - (NULL != frame) ) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - /* Regular test: allocation while memory is available again */ - disable_alloc = 0; - ret = MHD_websocket_encode_pong (wsx, - "abc", - 3, - &frame, - &frame_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (5 != frame_len) || - (NULL == frame) || - (0 != memcmp (frame, "\x8A\x03" "abc", 5))) - { - fprintf (stderr, - "Encode pong test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - if (NULL != frame) - { - MHD_websocket_free (wsx, frame); - frame = NULL; - } - - MHD_websocket_stream_free (wsx); - } - else - { - fprintf (stderr, - "Couldn't perform memory test for pong encoding in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - } - - if (NULL != buf1) - free (buf1); - if (NULL != buf2) - free (buf2); - if (NULL != wsc) - MHD_websocket_stream_free (wsc); - if (NULL != wss) - MHD_websocket_stream_free (wss); - - return failed != 0 ? 0x80 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_split_close_reason()` - */ -int -test_split_close_reason () -{ - int failed = 0; - const char *payload; - unsigned short reason_code; - const char *reason_utf8; - size_t reason_utf8_len; - int ret; - - /* - ------------------------------------------------------------------------------ - Normal splits - ------------------------------------------------------------------------------ - */ - /* Regular test: Reason code + Reason text */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = "\x03\xE8" "abc"; - ret = MHD_websocket_split_close_reason (payload, - 5, - &reason_code, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || - (3 != reason_utf8_len) || - (payload + 2 != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: Reason code */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = "\x03\xE8"; - ret = MHD_websocket_split_close_reason (payload, - 2, - &reason_code, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || - (0 != reason_utf8_len) || - (NULL != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: No payload */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = NULL; - ret = MHD_websocket_split_close_reason (payload, - 0, - &reason_code, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || - (0 != reason_utf8_len) || - (NULL != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: `payload` is not NULL given, but `payload_len` == 0 */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = "abc"; - ret = MHD_websocket_split_close_reason (payload, - 0, - &reason_code, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || - (0 != reason_utf8_len) || - (NULL != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Wrong parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: `payload` not passed, but `payload_len` != 0 */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = NULL; - ret = MHD_websocket_split_close_reason (payload, - 3, - &reason_code, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || - (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || - (0 != reason_utf8_len) || - (NULL != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: `reason_code` not passed */ - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - reason_utf8_len = 12345; - payload = "\x03\xE8" "abc"; - ret = MHD_websocket_split_close_reason (payload, - 5, - NULL, - &reason_utf8, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (3 != reason_utf8_len) || - (payload + 2 != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: `reason_utf8` not passed */ - reason_code = 9999; - reason_utf8_len = 12345; - payload = "\x03\xE8" "abc"; - ret = MHD_websocket_split_close_reason (payload, - 5, - &reason_code, - NULL, - &reason_utf8_len); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || - (3 != reason_utf8_len) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: `reason_utf8_len` not passed */ - reason_code = 9999; - reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; - payload = "\x03\xE8" "abc"; - ret = MHD_websocket_split_close_reason (payload, - 5, - &reason_code, - &reason_utf8, - NULL); - if ((MHD_WEBSOCKET_STATUS_OK != ret) || - (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || - (payload + 2 != reason_utf8) ) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: `reason_code`, `reason_utf8` and `reason_utf8_len` not passed */ - /* (this is not prohibited, although it doesn't really make sense) */ - payload = "\x03\xE8" "abc"; - ret = MHD_websocket_split_close_reason (payload, - 5, - NULL, - NULL, - NULL); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "split close reason test failed in line %u\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x100 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_check_http_version()` - */ -int -test_check_http_version () -{ - int failed = 0; - int ret; - - /* - ------------------------------------------------------------------------------ - Version check with valid HTTP version syntax - ------------------------------------------------------------------------------ - */ - /* Regular test: HTTP/1.1 */ - ret = MHD_websocket_check_http_version ("HTTP/1.1"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: HTTP/1.2 */ - ret = MHD_websocket_check_http_version ("HTTP/1.2"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: HTTP/1.10 */ - ret = MHD_websocket_check_http_version ("HTTP/1.10"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: HTTP/2.0 */ - ret = MHD_websocket_check_http_version ("HTTP/2.0"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: HTTP/3.0 */ - ret = MHD_websocket_check_http_version ("HTTP/3.0"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: HTTP/1.0 */ - ret = MHD_websocket_check_http_version ("HTTP/1.0"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: HTTP/0.9 */ - ret = MHD_websocket_check_http_version ("HTTP/0.9"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Version check edge cases - ------------------------------------------------------------------------------ - */ - /* Edge test (success): HTTP/123.45 */ - ret = MHD_websocket_check_http_version ("HTTP/123.45"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/1.45 */ - ret = MHD_websocket_check_http_version ("HTTP/1.45"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/01.1 */ - ret = MHD_websocket_check_http_version ("HTTP/01.1"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/0001.1 */ - ret = MHD_websocket_check_http_version ("HTTP/0001.1"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/1.01 */ - ret = MHD_websocket_check_http_version ("HTTP/1.01"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/1.0001 */ - ret = MHD_websocket_check_http_version ("HTTP/1.0001"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/0001.0001 */ - ret = MHD_websocket_check_http_version ("HTTP/0001.0001"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/2.000 */ - ret = MHD_websocket_check_http_version ("HTTP/2.000"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): HTTP/0.0 */ - ret = MHD_websocket_check_http_version ("HTTP/0.0"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): HTTP/00.0 */ - ret = MHD_websocket_check_http_version ("HTTP/00.0"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): HTTP/00.0 */ - ret = MHD_websocket_check_http_version ("HTTP/0.00"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Invalid version syntax - ------------------------------------------------------------------------------ - */ - /* Fail test: (empty string) */ - ret = MHD_websocket_check_http_version (""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: http/1.1 */ - ret = MHD_websocket_check_http_version ("http/1.1"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: "HTTP / 1.1" */ - ret = MHD_websocket_check_http_version ("HTTP / 1.1"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: NULL as version */ - ret = MHD_websocket_check_http_version (NULL); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_http_version test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x200 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_check_connection_header()` - */ -int -test_check_connection_header () -{ - int failed = 0; - int ret; - - /* - ------------------------------------------------------------------------------ - Check with valid Connection header syntax - ------------------------------------------------------------------------------ - */ - /* Regular test: Upgrade */ - ret = MHD_websocket_check_connection_header ("Upgrade"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Regular test: keep-alive, Upgrade */ - ret = MHD_websocket_check_connection_header ("keep-alive, Upgrade"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: keep-alive */ - ret = MHD_websocket_check_connection_header ("keep-alive"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: close */ - ret = MHD_websocket_check_connection_header ("close"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Connection check edge cases - ------------------------------------------------------------------------------ - */ - /* Edge test (success): keep-alive,Upgrade */ - ret = MHD_websocket_check_connection_header ("keep-alive,Upgrade"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Upgrade, keep-alive */ - ret = MHD_websocket_check_connection_header ("Upgrade, keep-alive"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Upgrade,keep-alive */ - ret = MHD_websocket_check_connection_header ("Upgrade,keep-alive"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Transfer-Encoding,Upgrade,keep-alive */ - ret = MHD_websocket_check_connection_header ( - "Transfer-Encoding,Upgrade,keep-alive"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Transfer-Encoding , Upgrade , keep-alive */ - ret = MHD_websocket_check_connection_header ( - "Transfer-Encoding , Upgrade , keep-alive"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): upgrade */ - ret = MHD_websocket_check_connection_header ("upgrade"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): UPGRADE */ - ret = MHD_websocket_check_connection_header ("UPGRADE"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): All allowed token characters, then upgrade token */ - ret = MHD_websocket_check_connection_header ( - "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,Upgrade"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Different, allowed whitespaces */ - ret = MHD_websocket_check_connection_header (" \tUpgrade \t"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_connection_header ("\rUpgrade"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_connection_header ("\nUpgrade"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_connection_header ("\vUpgrade"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_connection_header ("\fUpgrade"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Invalid header syntax - ------------------------------------------------------------------------------ - */ - /* Fail test: (empty string) */ - ret = MHD_websocket_check_connection_header (""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: (Disallowed) multiple word token with the term "Upgrade" in it */ - ret = MHD_websocket_check_connection_header ("Upgrade or Downgrade"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: Invalid characters */ - ret = MHD_websocket_check_connection_header ("\"Upgrade\""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: NULL as connection */ - ret = MHD_websocket_check_connection_header (NULL); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_connection_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x400 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_check_upgrade_header()` - */ -int -test_check_upgrade_header () -{ - int failed = 0; - int ret; - - /* - ------------------------------------------------------------------------------ - Check with valid Upgrade header syntax - ------------------------------------------------------------------------------ - */ - /* Regular test: websocket */ - ret = MHD_websocket_check_upgrade_header ("websocket"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: HTTP/2.0 */ - ret = MHD_websocket_check_upgrade_header ("HTTP/2.0"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Upgrade check edge cases - ------------------------------------------------------------------------------ - */ - /* Edge test (success): websocket,HTTP/2.0 */ - ret = MHD_websocket_check_upgrade_header ("websocket,HTTP/2.0"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): websocket ,HTTP/2.0 */ - ret = MHD_websocket_check_upgrade_header (" websocket ,HTTP/2.0"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): HTTP/2.0, websocket */ - ret = MHD_websocket_check_upgrade_header ("HTTP/2.0, websocket "); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): websocket/13 */ - ret = MHD_websocket_check_upgrade_header ("websocket/13"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): WeBsOcKeT */ - ret = MHD_websocket_check_upgrade_header ("WeBsOcKeT"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): WEBSOCKET */ - ret = MHD_websocket_check_upgrade_header ("WEBSOCKET"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): All allowed token characters plus /, then websocket keyword */ - ret = MHD_websocket_check_upgrade_header ( - "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/,websocket"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (success): Different, allowed whitespaces */ - ret = MHD_websocket_check_upgrade_header (" \twebsocket \t"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_upgrade_header ("\rwebsocket"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_upgrade_header ("\nwebsocket"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_upgrade_header ("\vwebsocket"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): Different, disallowed whitespaces */ - ret = MHD_websocket_check_upgrade_header ("\fwebsocket"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Invalid header syntax - ------------------------------------------------------------------------------ - */ - /* Fail test: (empty string) */ - ret = MHD_websocket_check_upgrade_header (""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: (Disallowed) multiple word token with the term "websocket" in it */ - ret = MHD_websocket_check_upgrade_header ("websocket or something"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: Invalid characters */ - ret = MHD_websocket_check_upgrade_header ("\"websocket\""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: NULL as upgrade */ - ret = MHD_websocket_check_upgrade_header (NULL); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_upgrade_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x800 : 0x00; -} - - -/** - * Test procedure for `MHD_websocket_check_version_header()` - */ -int -test_check_version_header () -{ - int failed = 0; - int ret; - - /* - ------------------------------------------------------------------------------ - Check with valid Upgrade header syntax - ------------------------------------------------------------------------------ - */ - /* Regular test: 13 */ - ret = MHD_websocket_check_version_header ("13"); - if (MHD_WEBSOCKET_STATUS_OK != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Version check edge cases - ------------------------------------------------------------------------------ - */ - /* Edge test (fail): 14 */ - ret = MHD_websocket_check_version_header ("14"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): 12 */ - ret = MHD_websocket_check_version_header ("12"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): 0 */ - ret = MHD_websocket_check_version_header ("1"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): 1 */ - ret = MHD_websocket_check_version_header ("1"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): 130 */ - ret = MHD_websocket_check_version_header ("130"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Edge test (fail): " 13" */ - ret = MHD_websocket_check_version_header (" 13"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Invalid header syntax - ------------------------------------------------------------------------------ - */ - /* Fail test: (empty string) */ - ret = MHD_websocket_check_version_header (""); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - /* Fail test: Invalid characters */ - ret = MHD_websocket_check_version_header ("abc"); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - /* - ------------------------------------------------------------------------------ - Missing parameters - ------------------------------------------------------------------------------ - */ - /* Fail test: NULL as version */ - ret = MHD_websocket_check_version_header (NULL); - if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) - { - fprintf (stderr, - "check_version_header test failed in line %u.\n", - (unsigned int) __LINE__); - ++failed; - } - - return failed != 0 ? 0x1000 : 0x00; -} - - -int -main (int argc, char *const *argv) -{ - unsigned int errorCount = 0; - (void) argc; (void) argv; /* Unused. Silent compiler warning. */ - - /* seed random number generator */ - srand ((unsigned long) time (NULL)); - - /* perform tests */ - errorCount += test_inits (); - errorCount += test_accept (); - errorCount += test_decodes (); - errorCount += test_encodes_text (); - errorCount += test_encodes_binary (); - errorCount += test_encodes_close (); - errorCount += test_encodes_ping (); - errorCount += test_encodes_pong (); - errorCount += test_split_close_reason (); - errorCount += test_check_http_version (); - errorCount += test_check_connection_header (); - errorCount += test_check_upgrade_header (); - errorCount += test_check_version_header (); - - /* output result */ - if (errorCount != 0) - fprintf (stderr, "Error (code: %u)\n", errorCount); - - return errorCount != 0; /* 0 == pass */ -} diff --git a/src/microhttpd_ws/test_websocket_browser.c b/src/microhttpd_ws/test_websocket_browser.c @@ -1,567 +0,0 @@ -/* - This file is part of libmicrohttpd - Copyright (C) 2021 David Gausmann - - libmicrohttpd is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - libmicrohttpd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libmicrohttpd; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ -/** - * @file test_websocket_browser.c - * @brief Testcase for WebSocket decoding/encoding with external browser - * @author David Gausmann - */ -#include <sys/types.h> -#ifndef _WIN32 -#include <sys/select.h> -#include <sys/socket.h> -#include <fcntl.h> -#else -#include <winsock2.h> -#endif -#include "microhttpd.h" -#include "microhttpd_ws.h" -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdint.h> -#include <time.h> -#include <errno.h> - -#define PORT 80 - -#define PAGE \ - "<!DOCTYPE html>\n" \ - "<html>\n" \ - "<head>\n" \ - "<meta charset=\"UTF-8\">\n" \ - "<title>Websocket External Test with Webbrowser</title>\n" \ - "<script>\n" \ - "\n" \ - "let current_mode = 0;\n" \ - "let current_step = 0;\n" \ - "let sent_payload = null;\n" \ - "let charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_!@%&/\\\\';\n" \ - "let step_to_bytes = [ 0, 1, 2, 3, 122, 123, 124, 125, 126, 127, 128, 32766, 32767, 32768, 65534, 65535, 65536, 65537, 1048576, 10485760 ];\n" \ - "let url = 'ws' + (window.location.protocol === 'https:' ? 's' : '')" \ - " + ':/" "/' +\n" \ - " window.location.host + '/websocket';\n" \ - "let socket = null;\n" \ - "\n" \ - "window.onload = function (event) {\n" \ - " if (!window.WebSocket) {\n" \ - " document.write ('ERROR: The WebSocket class is not supported by your browser.<br>');\n" \ - " }\n" \ - " if (!window.fetch) {\n" \ - " document.write ('ERROR: The fetch-API is not supported by your browser.<br>');\n" \ - " }\n" \ - " document.write ('Starting tests.<br>');\n" \ - " runTest ();\n" \ - "}\n" \ - "\n" \ - "function runTest () {\n" \ - " switch (current_mode) {\n" \ - " case 0:\n" \ - " document.write ('TEXT');\n" \ - " break;\n" \ - " case 1:\n" \ - " document.write ('BINARY');\n" \ - " break;\n" \ - " }\n" \ - " document.write (', ' + step_to_bytes[current_step] + ' Bytes: ');\n" \ - " socket = new WebSocket(url);\n" \ - " socket.binaryType = 'arraybuffer';\n" \ - " socket.onopen = function (event) {\n" \ - " switch (current_mode) {\n" \ - " case 0:\n" \ - " sent_payload = randomText (step_to_bytes[current_step]);\n" \ - " socket.send (sent_payload);\n" \ - " break;\n" \ - " case 1:\n" \ - " sent_payload = randomBinary (step_to_bytes[current_step]);\n" \ - " socket.send (sent_payload);\n" \ - " break;\n" \ - " }\n" \ - " }\n" \ - "\n" \ - " socket.onclose = function (event) {\n" \ - " socket.onmessage = null;\n" \ - " socket.onclose = null;\n" \ - " socket.onerror = null;\n" \ - " document.write ('CLOSED unexpectedly.<br>');\n" \ - " notifyError ();\n" \ - " }\n" \ - "\n" \ - " socket.onerror = function (event) {\n" \ - " socket.onmessage = null;\n" \ - " socket.onclose = null;\n" \ - " socket.onerror = null;\n" \ - " document.write ('ERROR.<br>');\n" \ - " notifyError ();\n" \ - " }\n" \ - "\n" \ - " socket.onmessage = async function (event) {\n" \ - " if (compareData (event.data, sent_payload)) {\n" \ - " document.write ('SUCCESS.<br>');\n" \ - " socket.onmessage = null;\n" \ - " socket.onclose = null;\n" \ - " socket.onerror = null;\n" \ - " socket.close();\n" \ - " socket = null;\n" \ - " if (step_to_bytes.length <= ++current_step) {\n" \ - " current_step = 0;\n" \ - " if (1 < ++current_mode) {\n" \ - " document.write ('FINISHED ALL TESTS.<br>');\n" \ - " return;\n" \ - " }\n" \ - " }\n" \ - " runTest ();\n" \ - " }" \ - " }\n" \ - "}\n" \ - "\n" \ - "function compareData (data, data2) {\n" \ - " if (typeof (data) === 'string' && typeof (data2) === 'string') {\n" \ - " return (data === data2); \n" \ - " } \n" \ - " else if ((data instanceof ArrayBuffer) && (data2 instanceof ArrayBuffer)) {\n" \ - " let view1 = new Uint8Array (data);\n" \ - " let view2 = new Uint8Array (data2);\n" \ - " if (view1.length != view2.length)\n" \ - " return false;\n" \ - " for (let i = 0; i < view1.length; ++i) {\n" \ - " if (view1[i] !== view2[i])\n" \ - " return false;\n" \ - " }\n" \ - " return true;\n" \ - " }\n" \ - " else\n" \ - " {\n" \ - " return false;\n" \ - " }\n" \ - "}\n" \ - "\n" \ - "function randomText (length) {\n" \ - " let result = new Array (length);\n" \ - " for (let i = 0; i < length; ++i)\n" \ - " result [i] = charset [~~(Math.random () * charset.length)];\n" \ - " return result.join ('');\n" \ - "}\n" \ - "\n" \ - "function randomBinary (length) {\n" \ - " let buffer = new ArrayBuffer (length);\n" \ - " let view = new Uint8Array (buffer);\n" \ - " for (let i = 0; i < length; ++i)\n" \ - " view [i] = ~~(Math.random () * 256);\n" \ - " return buffer;\n" \ - "}\n" \ - "\n" \ - "function notifyError () {\n" \ - " fetch('error/' + (0 == current_mode ? 'text' : 'binary') + '/' + step_to_bytes[current_step]);\n" \ - "}\n" \ - "\n" \ - "</script>\n" \ - "</head>\n" \ - "<body>\n" \ - "</body>\n" \ - "</html>" - -#define PAGE_NOT_FOUND \ - "404 Not Found" - -#define PAGE_INVALID_WEBSOCKET_REQUEST \ - "Invalid WebSocket request!" - -static void -send_all (MHD_socket fd, - const char *buf, - size_t len); - -static void -make_blocking (MHD_socket fd); - -static void -upgrade_handler (void *cls, - struct MHD_Connection *connection, - void *req_cls, - const char *extra_in, - size_t extra_in_size, - MHD_socket fd, - struct MHD_UpgradeResponseHandle *urh) -{ - /* make the socket blocking (operating-system-dependent code) */ - make_blocking (fd); - - /* create a websocket stream for this connection */ - struct MHD_WebSocketStream *ws; - int result = MHD_websocket_stream_init (&ws, - 0, - 0); - if (0 != result) - { - /* Couldn't create the websocket stream. - * So we close the socket and leave - */ - MHD_upgrade_action (urh, - MHD_UPGRADE_ACTION_CLOSE); - return; - } - - /* Let's wait for incoming data */ - const size_t buf_len = 256; - char buf[buf_len]; - ssize_t got; - while (MHD_WEBSOCKET_VALIDITY_VALID == MHD_websocket_stream_is_valid (ws)) - { - got = recv (fd, - buf, - sizeof (buf), - 0); - if (0 >= got) - { - /* the TCP/IP socket has been closed */ - fprintf (stderr, - "Error (The socket has been closed unexpectedly)\n"); - break; - } - - /* parse the entire received data */ - size_t buf_offset = 0; - while (buf_offset < (size_t) got) - { - size_t new_offset = 0; - char *payload_data = NULL; - size_t payload_len = 0; - char *frame_data = NULL; - size_t frame_len = 0; - int status = MHD_websocket_decode (ws, - buf + buf_offset, - ((size_t) got) - buf_offset, - &new_offset, - &payload_data, - &payload_len); - if (0 > status) - { - /* an error occurred and the connection must be closed */ - printf ("Decoding failed: status=%d, passed=%u\n", status, - ((size_t) got) - buf_offset); - if (NULL != payload_data) - { - MHD_websocket_free (ws, payload_data); - } - break; - } - else - { - buf_offset += new_offset; - if (0 < status) - { - /* the frame is complete */ - printf ( - "Decoding succeeded: type=%d, passed=%u, parsed=%u, payload_len=%d\n", - status, ((size_t) got) - buf_offset, new_offset, payload_len); - switch (status) - { - case MHD_WEBSOCKET_STATUS_TEXT_FRAME: - case MHD_WEBSOCKET_STATUS_BINARY_FRAME: - /* The client has sent some data. */ - if ((NULL != payload_data) || (0 == payload_len)) - { - /* Send the received data back to the client */ - if (MHD_WEBSOCKET_STATUS_TEXT_FRAME == status) - { - result = MHD_websocket_encode_text (ws, - payload_data, - payload_len, - 0, - &frame_data, - &frame_len, - NULL); - } - else - { - result = MHD_websocket_encode_binary (ws, - payload_data, - payload_len, - 0, - &frame_data, - &frame_len); - } - if (0 == result) - { - send_all (fd, - frame_data, - frame_len); - } - } - else - { - /* should never happen */ - fprintf (stderr, - "Error (Empty buffer with payload_len != 0)\n"); - } - break; - - default: - /* Other frame types are ignored - * in this test script. - */ - break; - } - } - if (NULL != payload_data) - { - MHD_websocket_free (ws, payload_data); - } - if (NULL != frame_data) - { - MHD_websocket_free (ws, frame_data); - } - } - } - } - - /* free the websocket stream */ - MHD_websocket_stream_free (ws); - - /* close the socket when it is not needed anymore */ - MHD_upgrade_action (urh, - MHD_UPGRADE_ACTION_CLOSE); -} - - -/* This helper function is used for the case that - * we need to resend some data - */ -static void -send_all (MHD_socket fd, - const char *buf, - size_t len) -{ - ssize_t ret; - size_t off; - - for (off = 0; off < len; off += ret) - { - ret = send (fd, - &buf[off], - (int) (len - off), - 0); - if (0 > ret) - { - if (EAGAIN == errno) - { - ret = 0; - continue; - } - break; - } - if (0 == ret) - break; - } -} - - -/* This helper function contains operating-system-dependent code and - * is used to make a socket blocking. - */ -static void -make_blocking (MHD_socket fd) -{ -#ifndef _WIN32 - int flags; - - flags = fcntl (fd, F_GETFL); - if (-1 == flags) - return; - if ((flags & ~O_NONBLOCK) != flags) - if (-1 == fcntl (fd, F_SETFL, flags & ~O_NONBLOCK)) - abort (); -#else - unsigned long flags = 0; - - ioctlsocket (fd, FIONBIO, &flags); -#endif -} - - -static enum MHD_Result -access_handler (void *cls, - struct MHD_Connection *connection, - const char *url, - const char *method, - const char *version, - const char *upload_data, - size_t *upload_data_size, - void **req_cls) -{ - static int aptr; - struct MHD_Response *response; - int ret; - - (void) cls; /* Unused. Silent compiler warning. */ - (void) upload_data; /* Unused. Silent compiler warning. */ - (void) upload_data_size; /* Unused. Silent compiler warning. */ - - if (0 != strcmp (method, "GET")) - return MHD_NO; /* unexpected method */ - if (&aptr != *req_cls) - { - /* do never respond on first call */ - *req_cls = &aptr; - return MHD_YES; - } - *req_cls = NULL; /* reset when done */ - - if (0 == strcmp (url, "/")) - { - /* Default page for visiting the server */ - struct MHD_Response *response = MHD_create_response_from_buffer ( - strlen (PAGE), - PAGE, - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (connection, - MHD_HTTP_OK, - response); - MHD_destroy_response (response); - } - else if (0 == strncmp (url, "/error/", 7)) - { - /* Report error */ - fprintf (stderr, "Error in test (%s)\n", url + 7); - - struct MHD_Response *response = MHD_create_response_from_buffer ( - 0, - "", - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (connection, - MHD_HTTP_OK, - response); - MHD_destroy_response (response); - } - else if (0 == strcmp (url, "/websocket")) - { - char is_valid = 1; - const char *value = NULL; - char sec_websocket_accept[29]; - - if (0 != MHD_websocket_check_http_version (version)) - { - is_valid = 0; - } - value = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_CONNECTION); - if (0 != MHD_websocket_check_connection_header (value)) - { - is_valid = 0; - } - value = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_UPGRADE); - if (0 != MHD_websocket_check_upgrade_header (value)) - { - is_valid = 0; - } - value = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION); - if (0 != MHD_websocket_check_version_header (value)) - { - is_valid = 0; - } - value = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY); - if (0 != MHD_websocket_create_accept_header (value, sec_websocket_accept)) - { - is_valid = 0; - } - - if (1 == is_valid) - { - /* upgrade the connection */ - response = MHD_create_response_for_upgrade (&upgrade_handler, - NULL); - MHD_add_response_header (response, - MHD_HTTP_HEADER_UPGRADE, - "websocket"); - MHD_add_response_header (response, - MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT, - sec_websocket_accept); - ret = MHD_queue_response (connection, - MHD_HTTP_SWITCHING_PROTOCOLS, - response); - MHD_destroy_response (response); - } - else - { - /* return error page */ - struct MHD_Response *response = MHD_create_response_from_buffer ( - strlen (PAGE_INVALID_WEBSOCKET_REQUEST), - PAGE_INVALID_WEBSOCKET_REQUEST, - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (connection, - MHD_HTTP_BAD_REQUEST, - response); - MHD_destroy_response (response); - } - } - else - { - struct MHD_Response *response = MHD_create_response_from_buffer ( - strlen (PAGE_NOT_FOUND), - PAGE_NOT_FOUND, - MHD_RESPMEM_PERSISTENT); - ret = MHD_queue_response (connection, - MHD_HTTP_NOT_FOUND, - response); - MHD_destroy_response (response); - } - - return ret; -} - - -int -main (int argc, - char *const *argv) -{ - (void) argc; /* Unused. Silent compiler warning. */ - (void) argv; /* Unused. Silent compiler warning. */ - struct MHD_Daemon *daemon; - - daemon = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD - | MHD_USE_THREAD_PER_CONNECTION - | MHD_ALLOW_UPGRADE - | MHD_USE_ERROR_LOG, - PORT, NULL, NULL, - &access_handler, NULL, - MHD_OPTION_END); - - if (NULL == daemon) - { - fprintf (stderr, "Error (Couldn't start daemon for testing)\n"); - return 1; - } - printf ("The server is listening now.\n"); - printf ("Access the server now with a websocket-capable webbrowser.\n\n"); - printf ("Press return to close.\n"); - - (void) getc (stdin); - - MHD_stop_daemon (daemon); - - return 0; -}