From 10ab0ba87b4c886ef7433efb0b6175e47abc3c50 Mon Sep 17 00:00:00 2001 From: Longjun Luo Date: Wed, 12 Nov 2025 16:28:46 +0800 Subject: [PATCH] upgrade to 1.0.2 and fix CVE-2025-62689 Signed-off-by: Longjun Luo --- 3001-remove-broken-experimental-code.patch | 13147 +++++++++++++++++++ gnutls-utilize-system-crypto-policy.patch | 11 - libmicrohttpd.spec | 11 +- sources | 2 +- 4 files changed, 13156 insertions(+), 15 deletions(-) create mode 100644 3001-remove-broken-experimental-code.patch delete mode 100644 gnutls-utilize-system-crypto-policy.patch diff --git a/3001-remove-broken-experimental-code.patch b/3001-remove-broken-experimental-code.patch new file mode 100644 index 0000000..d8178b2 --- /dev/null +++ b/3001-remove-broken-experimental-code.patch @@ -0,0 +1,13147 @@ +From 2bfc271483da2f23d635cae2f5424d3760348edb Mon Sep 17 00:00:00 2001 +From: Longjun Luo +Date: Wed, 12 Nov 2025 17:34:59 +0800 +Subject: [PATCH] remove broken experimental code + +--- + src/Makefile.am | 5 - + src/microhttpd_ws/Makefile.am | 43 - + src/microhttpd_ws/mhd_websocket.c | 2443 ------- + src/microhttpd_ws/sha1.c | 378 - + src/microhttpd_ws/sha1.h | 110 - + src/microhttpd_ws/test_websocket.c | 10105 --------------------------- + 6 files changed, 13084 deletions(-) + delete mode 100644 src/microhttpd_ws/Makefile.am + delete mode 100644 src/microhttpd_ws/mhd_websocket.c + delete mode 100644 src/microhttpd_ws/sha1.c + delete mode 100644 src/microhttpd_ws/sha1.h + delete mode 100644 src/microhttpd_ws/test_websocket.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index d02ab8f..07d8f3d 100644 +--- 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 +deleted file mode 100644 +index 3ce8a9f..0000000 +--- a/src/microhttpd_ws/Makefile.am ++++ /dev/null +@@ -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 +deleted file mode 100644 +index 935deee..0000000 +--- a/src/microhttpd_ws/mhd_websocket.c ++++ /dev/null +@@ -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 +deleted file mode 100644 +index 1e9da5c..0000000 +--- a/src/microhttpd_ws/sha1.c ++++ /dev/null +@@ -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 . +-*/ +- +-/** +- * @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 +-#ifdef HAVE_MEMORY_H +-#include +-#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 +deleted file mode 100644 +index 851a442..0000000 +--- a/src/microhttpd_ws/sha1.h ++++ /dev/null +@@ -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 . +-*/ +- +-/** +- * @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 +-#ifdef HAVE_STDDEF_H +-#include /* 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 +deleted file mode 100644 +index b824b9c..0000000 +--- a/src/microhttpd_ws/test_websocket.c ++++ /dev/null +@@ -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 +-#include +-#include +-#include +-#include +- +-#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 */ +-} +-- +2.43.7 + diff --git a/gnutls-utilize-system-crypto-policy.patch b/gnutls-utilize-system-crypto-policy.patch deleted file mode 100644 index 4f024a4..0000000 --- a/gnutls-utilize-system-crypto-policy.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- libmicrohttpd-0.9.67/src/microhttpd/daemon.c.orig 2019-10-18 08:14:27.591969227 +0200 -+++ libmicrohttpd-0.9.67/src/microhttpd/daemon.c 2019-10-18 08:15:20.306963570 +0200 -@@ -5779,7 +5779,7 @@ - if (0 != (*pflags & MHD_USE_TLS)) - { - gnutls_priority_init (&daemon->priority_cache, -- "NORMAL", -+ "@SYSTEM", - NULL); - } - #endif /* HTTPS_SUPPORT */ diff --git a/libmicrohttpd.spec b/libmicrohttpd.spec index 7482633..ba855a0 100644 --- a/libmicrohttpd.spec +++ b/libmicrohttpd.spec @@ -1,11 +1,12 @@ Summary: Lightweight library for embedding a webserver in applications Name: libmicrohttpd -Version: 0.9.77 -Release: 4%{?dist} +Version: 1.0.2 +Release: 1%{?dist} License: LGPLv2+ URL: http://www.gnu.org/software/libmicrohttpd/ Source0: https://ftp.gnu.org/gnu/libmicrohttpd/%{name}-%{version}.tar.gz -Patch3000: gnutls-utilize-system-crypto-policy.patch + +Patch3001: 3001-remove-broken-experimental-code.patch BuildRequires: make BuildRequires: libtool gnutls-devel @@ -85,6 +86,10 @@ fi %{_mandir}/man3/libmicrohttpd.3.gz %changelog +* Wed Nov 12 2025 anatasluo - 1.0.2-1 +- [Type] security +- [DESC] fix CVE-2025-62689, upgrade to 1.0.2 + * Thu Sep 26 2024 OpenCloudOS Release Engineering - 0.9.77-4 - Rebuilt for clarifying the packages requirement in BaseOS and AppStream diff --git a/sources b/sources index 1b1acd9..92815f5 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (libmicrohttpd-0.9.77.tar.gz) = 001025c023dd94c4a0cf017ed575e65a577b5ce595e7e450346bfb75def77eaa8a4cfbeffb9f4b912e34165c2cfca147c02c895e067a4f6c5a321a12035758a5 +SHA512 (libmicrohttpd-1.0.2.tar.gz) = 7092f307a00ba04b539be79a7c94ddf9b4b6e43343a66da49c6602fa860f77cf7f9017d7e40f9b7400d85a828a503248eb12dd121413aad68133003a20bb2c4a -- Gitee