File CVE-2025-59777.patch of Package libmicrohttpd.41785

diff --git a/src/microhttpd_ws/mhd_websocket.c b/src/microhttpd_ws/mhd_websocket.c
deleted file mode 100644
index 935deee6..00000000
--- 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 1e9da5c7..00000000
--- 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha1.c
- * @brief  Calculation of SHA-1 digest as defined in FIPS PUB 180-4 (2015)
- * @author Karlson2k (Evgeny Grin)
- */
-
-#include "sha1.h"
-
-#include <string.h>
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif /* HAVE_MEMORY_H */
-#include "mhd_bithelpers.h"
-#include "mhd_assert.h"
-
-/**
- * Initialise structure for SHA-1 calculation.
- *
- * @param ctx_ must be a `struct sha1_ctx *`
- */
-void
-MHD_SHA1_init (void *ctx_)
-{
-  struct sha1_ctx *const ctx = ctx_;
-  /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.1 */
-  /* Just some "magic" numbers defined by standard */
-  ctx->H[0] = UINT32_C (0x67452301);
-  ctx->H[1] = UINT32_C (0xefcdab89);
-  ctx->H[2] = UINT32_C (0x98badcfe);
-  ctx->H[3] = UINT32_C (0x10325476);
-  ctx->H[4] = UINT32_C (0xc3d2e1f0);
-
-  /* Initialise number of bytes. */
-  ctx->count = 0;
-}
-
-
-/**
- * Base of SHA-1 transformation.
- * Gets full 512 bits / 64 bytes block of data and updates hash values;
- * @param H     hash values
- * @param data  data, must be exactly 64 bytes long
- */
-static void
-sha1_transform (uint32_t H[_SHA1_DIGEST_LENGTH],
-                const uint8_t data[SHA1_BLOCK_SIZE])
-{
-  /* Working variables,
-     see FIPS PUB 180-4 paragraph 6.1.3 */
-  uint32_t a = H[0];
-  uint32_t b = H[1];
-  uint32_t c = H[2];
-  uint32_t d = H[3];
-  uint32_t e = H[4];
-
-  /* Data buffer, used as cyclic buffer.
-     See FIPS PUB 180-4 paragraphs 5.2.1, 6.1.3 */
-  uint32_t W[16];
-
-  /* 'Ch' and 'Maj' macro functions are defined with
-     widely-used optimization.
-     See FIPS PUB 180-4 formulae 4.1. */
-#define Ch(x,y,z)     ( (z) ^ ((x) & ((y) ^ (z))) )
-#define Maj(x,y,z)    ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
-  /* Unoptimized (original) versions: */
-/* #define Ch(x,y,z)  ( ( (x) & (y) ) ^ ( ~(x) & (z) ) )          */
-/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
-#define Par(x,y,z)    ( (x) ^ (y) ^ (z) )
-
-  /* Single step of SHA-1 computation,
-     see FIPS PUB 180-4 paragraph 6.1.3 step 3.
-   * Note: instead of reassigning all working variables on each step,
-           variables are rotated for each step:
-             SHA1STEP32 (a, b, c, d, e, func, K00, W[0]);
-             SHA1STEP32 (e, a, b, c, d, func, K00, W[1]);
-           so current 'vC' will be used as 'vD' on the next step,
-           current 'vE' will be used as 'vA' on the next step.
-   * Note: 'wt' must be used exactly one time in this macro as it change other data as well
-           every time when used. */
-
-#define SHA1STEP32(vA,vB,vC,vD,vE,ft,kt,wt) do {                         \
-    (vE) += _MHD_ROTL32 ((vA), 5) + ft ((vB), (vC), (vD)) + (kt) + (wt); \
-    (vB) = _MHD_ROTL32 ((vB), 30); } while (0)
-
-  /* Get value of W(t) from input data buffer,
-     See FIPS PUB 180-4 paragraph 6.1.3.
-     Input data must be read in big-endian bytes order,
-     see FIPS PUB 180-4 paragraph 3.1.2. */
-#define GET_W_FROM_DATA(buf,t) \
-  _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD)
-
-#ifndef _MHD_GET_32BIT_BE_UNALIGNED
-  if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN))
-  {
-    /* Copy the unaligned input data to the aligned buffer */
-    memcpy (W, data, SHA1_BLOCK_SIZE);
-    /* The W[] buffer itself will be used as the source of the data,
-     * but data will be reloaded in correct bytes order during
-     * the next steps */
-    data = (uint8_t *) W;
-  }
-#endif /* _MHD_GET_32BIT_BE_UNALIGNED */
-
-/* SHA-1 values of Kt for t=0..19, see FIPS PUB 180-4 paragraph 4.2.1. */
-#define K00      UINT32_C(0x5a827999)
-/* SHA-1 values of Kt for t=20..39, see FIPS PUB 180-4 paragraph 4.2.1.*/
-#define K20      UINT32_C(0x6ed9eba1)
-/* SHA-1 values of Kt for t=40..59, see FIPS PUB 180-4 paragraph 4.2.1.*/
-#define K40      UINT32_C(0x8f1bbcdc)
-/* SHA-1 values of Kt for t=60..79, see FIPS PUB 180-4 paragraph 4.2.1.*/
-#define K60      UINT32_C(0xca62c1d6)
-
-  /* During first 16 steps, before making any calculations on each step,
-     the W element is read from input data buffer as big-endian value and
-     stored in array of W elements. */
-  /* Note: instead of using K constants as array, all K values are specified
-     individually for each step. */
-  SHA1STEP32 (a, b, c, d, e, Ch, K00, W[0] = GET_W_FROM_DATA (data, 0));
-  SHA1STEP32 (e, a, b, c, d, Ch, K00, W[1] = GET_W_FROM_DATA (data, 1));
-  SHA1STEP32 (d, e, a, b, c, Ch, K00, W[2] = GET_W_FROM_DATA (data, 2));
-  SHA1STEP32 (c, d, e, a, b, Ch, K00, W[3] = GET_W_FROM_DATA (data, 3));
-  SHA1STEP32 (b, c, d, e, a, Ch, K00, W[4] = GET_W_FROM_DATA (data, 4));
-  SHA1STEP32 (a, b, c, d, e, Ch, K00, W[5] = GET_W_FROM_DATA (data, 5));
-  SHA1STEP32 (e, a, b, c, d, Ch, K00, W[6] = GET_W_FROM_DATA (data, 6));
-  SHA1STEP32 (d, e, a, b, c, Ch, K00, W[7] = GET_W_FROM_DATA (data, 7));
-  SHA1STEP32 (c, d, e, a, b, Ch, K00, W[8] = GET_W_FROM_DATA (data, 8));
-  SHA1STEP32 (b, c, d, e, a, Ch, K00, W[9] = GET_W_FROM_DATA (data, 9));
-  SHA1STEP32 (a, b, c, d, e, Ch, K00, W[10] = GET_W_FROM_DATA (data, 10));
-  SHA1STEP32 (e, a, b, c, d, Ch, K00, W[11] = GET_W_FROM_DATA (data, 11));
-  SHA1STEP32 (d, e, a, b, c, Ch, K00, W[12] = GET_W_FROM_DATA (data, 12));
-  SHA1STEP32 (c, d, e, a, b, Ch, K00, W[13] = GET_W_FROM_DATA (data, 13));
-  SHA1STEP32 (b, c, d, e, a, Ch, K00, W[14] = GET_W_FROM_DATA (data, 14));
-  SHA1STEP32 (a, b, c, d, e, Ch, K00, W[15] = GET_W_FROM_DATA (data, 15));
-
-  /* 'W' generation and assignment for 16 <= t <= 79.
-     See FIPS PUB 180-4 paragraph 6.1.3.
-     As only last 16 'W' are used in calculations, it is possible to
-     use 16 elements array of W as cyclic buffer. */
-#define Wgen(w,t) _MHD_ROTL32((w)[(t + 13) & 0xf] ^ (w)[(t + 8) & 0xf] \
-                              ^ (w)[(t + 2) & 0xf] ^ (w)[t & 0xf], 1)
-
-  /* During last 60 steps, before making any calculations on each step,
-     W element is generated from W elements of cyclic buffer and generated value
-     stored back in cyclic buffer. */
-  /* Note: instead of using K constants as array, all K values are specified
-     individually for each step, see FIPS PUB 180-4 paragraph 4.2.1. */
-  SHA1STEP32 (e, a, b, c, d, Ch, K00, W[16 & 0xf] = Wgen (W, 16));
-  SHA1STEP32 (d, e, a, b, c, Ch, K00, W[17 & 0xf] = Wgen (W, 17));
-  SHA1STEP32 (c, d, e, a, b, Ch, K00, W[18 & 0xf] = Wgen (W, 18));
-  SHA1STEP32 (b, c, d, e, a, Ch, K00, W[19 & 0xf] = Wgen (W, 19));
-  SHA1STEP32 (a, b, c, d, e, Par, K20, W[20 & 0xf] = Wgen (W, 20));
-  SHA1STEP32 (e, a, b, c, d, Par, K20, W[21 & 0xf] = Wgen (W, 21));
-  SHA1STEP32 (d, e, a, b, c, Par, K20, W[22 & 0xf] = Wgen (W, 22));
-  SHA1STEP32 (c, d, e, a, b, Par, K20, W[23 & 0xf] = Wgen (W, 23));
-  SHA1STEP32 (b, c, d, e, a, Par, K20, W[24 & 0xf] = Wgen (W, 24));
-  SHA1STEP32 (a, b, c, d, e, Par, K20, W[25 & 0xf] = Wgen (W, 25));
-  SHA1STEP32 (e, a, b, c, d, Par, K20, W[26 & 0xf] = Wgen (W, 26));
-  SHA1STEP32 (d, e, a, b, c, Par, K20, W[27 & 0xf] = Wgen (W, 27));
-  SHA1STEP32 (c, d, e, a, b, Par, K20, W[28 & 0xf] = Wgen (W, 28));
-  SHA1STEP32 (b, c, d, e, a, Par, K20, W[29 & 0xf] = Wgen (W, 29));
-  SHA1STEP32 (a, b, c, d, e, Par, K20, W[30 & 0xf] = Wgen (W, 30));
-  SHA1STEP32 (e, a, b, c, d, Par, K20, W[31 & 0xf] = Wgen (W, 31));
-  SHA1STEP32 (d, e, a, b, c, Par, K20, W[32 & 0xf] = Wgen (W, 32));
-  SHA1STEP32 (c, d, e, a, b, Par, K20, W[33 & 0xf] = Wgen (W, 33));
-  SHA1STEP32 (b, c, d, e, a, Par, K20, W[34 & 0xf] = Wgen (W, 34));
-  SHA1STEP32 (a, b, c, d, e, Par, K20, W[35 & 0xf] = Wgen (W, 35));
-  SHA1STEP32 (e, a, b, c, d, Par, K20, W[36 & 0xf] = Wgen (W, 36));
-  SHA1STEP32 (d, e, a, b, c, Par, K20, W[37 & 0xf] = Wgen (W, 37));
-  SHA1STEP32 (c, d, e, a, b, Par, K20, W[38 & 0xf] = Wgen (W, 38));
-  SHA1STEP32 (b, c, d, e, a, Par, K20, W[39 & 0xf] = Wgen (W, 39));
-  SHA1STEP32 (a, b, c, d, e, Maj, K40, W[40 & 0xf] = Wgen (W, 40));
-  SHA1STEP32 (e, a, b, c, d, Maj, K40, W[41 & 0xf] = Wgen (W, 41));
-  SHA1STEP32 (d, e, a, b, c, Maj, K40, W[42 & 0xf] = Wgen (W, 42));
-  SHA1STEP32 (c, d, e, a, b, Maj, K40, W[43 & 0xf] = Wgen (W, 43));
-  SHA1STEP32 (b, c, d, e, a, Maj, K40, W[44 & 0xf] = Wgen (W, 44));
-  SHA1STEP32 (a, b, c, d, e, Maj, K40, W[45 & 0xf] = Wgen (W, 45));
-  SHA1STEP32 (e, a, b, c, d, Maj, K40, W[46 & 0xf] = Wgen (W, 46));
-  SHA1STEP32 (d, e, a, b, c, Maj, K40, W[47 & 0xf] = Wgen (W, 47));
-  SHA1STEP32 (c, d, e, a, b, Maj, K40, W[48 & 0xf] = Wgen (W, 48));
-  SHA1STEP32 (b, c, d, e, a, Maj, K40, W[49 & 0xf] = Wgen (W, 49));
-  SHA1STEP32 (a, b, c, d, e, Maj, K40, W[50 & 0xf] = Wgen (W, 50));
-  SHA1STEP32 (e, a, b, c, d, Maj, K40, W[51 & 0xf] = Wgen (W, 51));
-  SHA1STEP32 (d, e, a, b, c, Maj, K40, W[52 & 0xf] = Wgen (W, 52));
-  SHA1STEP32 (c, d, e, a, b, Maj, K40, W[53 & 0xf] = Wgen (W, 53));
-  SHA1STEP32 (b, c, d, e, a, Maj, K40, W[54 & 0xf] = Wgen (W, 54));
-  SHA1STEP32 (a, b, c, d, e, Maj, K40, W[55 & 0xf] = Wgen (W, 55));
-  SHA1STEP32 (e, a, b, c, d, Maj, K40, W[56 & 0xf] = Wgen (W, 56));
-  SHA1STEP32 (d, e, a, b, c, Maj, K40, W[57 & 0xf] = Wgen (W, 57));
-  SHA1STEP32 (c, d, e, a, b, Maj, K40, W[58 & 0xf] = Wgen (W, 58));
-  SHA1STEP32 (b, c, d, e, a, Maj, K40, W[59 & 0xf] = Wgen (W, 59));
-  SHA1STEP32 (a, b, c, d, e, Par, K60, W[60 & 0xf] = Wgen (W, 60));
-  SHA1STEP32 (e, a, b, c, d, Par, K60, W[61 & 0xf] = Wgen (W, 61));
-  SHA1STEP32 (d, e, a, b, c, Par, K60, W[62 & 0xf] = Wgen (W, 62));
-  SHA1STEP32 (c, d, e, a, b, Par, K60, W[63 & 0xf] = Wgen (W, 63));
-  SHA1STEP32 (b, c, d, e, a, Par, K60, W[64 & 0xf] = Wgen (W, 64));
-  SHA1STEP32 (a, b, c, d, e, Par, K60, W[65 & 0xf] = Wgen (W, 65));
-  SHA1STEP32 (e, a, b, c, d, Par, K60, W[66 & 0xf] = Wgen (W, 66));
-  SHA1STEP32 (d, e, a, b, c, Par, K60, W[67 & 0xf] = Wgen (W, 67));
-  SHA1STEP32 (c, d, e, a, b, Par, K60, W[68 & 0xf] = Wgen (W, 68));
-  SHA1STEP32 (b, c, d, e, a, Par, K60, W[69 & 0xf] = Wgen (W, 69));
-  SHA1STEP32 (a, b, c, d, e, Par, K60, W[70 & 0xf] = Wgen (W, 70));
-  SHA1STEP32 (e, a, b, c, d, Par, K60, W[71 & 0xf] = Wgen (W, 71));
-  SHA1STEP32 (d, e, a, b, c, Par, K60, W[72 & 0xf] = Wgen (W, 72));
-  SHA1STEP32 (c, d, e, a, b, Par, K60, W[73 & 0xf] = Wgen (W, 73));
-  SHA1STEP32 (b, c, d, e, a, Par, K60, W[74 & 0xf] = Wgen (W, 74));
-  SHA1STEP32 (a, b, c, d, e, Par, K60, W[75 & 0xf] = Wgen (W, 75));
-  SHA1STEP32 (e, a, b, c, d, Par, K60, W[76 & 0xf] = Wgen (W, 76));
-  SHA1STEP32 (d, e, a, b, c, Par, K60, W[77 & 0xf] = Wgen (W, 77));
-  SHA1STEP32 (c, d, e, a, b, Par, K60, W[78 & 0xf] = Wgen (W, 78));
-  SHA1STEP32 (b, c, d, e, a, Par, K60, W[79 & 0xf] = Wgen (W, 79));
-
-  /* Compute intermediate hash.
-     See FIPS PUB 180-4 paragraph 6.1.3 step 4. */
-  H[0] += a;
-  H[1] += b;
-  H[2] += c;
-  H[3] += d;
-  H[4] += e;
-}
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx_ must be a `struct sha1_ctx *`
- * @param data bytes to add to hash
- * @param length number of bytes in @a data
- */
-void
-MHD_SHA1_update (void *ctx_,
-                 const uint8_t *data,
-                 size_t length)
-{
-  struct sha1_ctx *const ctx = ctx_;
-  unsigned bytes_have; /**< Number of bytes in buffer */
-
-  mhd_assert ((data != NULL) || (length == 0));
-
-  if (0 == length)
-    return; /* Do nothing */
-
-  /* Note: (count & (SHA1_BLOCK_SIZE-1))
-           equal (count % SHA1_BLOCK_SIZE) for this block size. */
-  bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1));
-  ctx->count += length;
-
-  if (0 != bytes_have)
-  {
-    unsigned bytes_left = SHA1_BLOCK_SIZE - bytes_have;
-    if (length >= bytes_left)
-    {     /* Combine new data with the data in the buffer and
-             process the full block. */
-      memcpy (ctx->buffer + bytes_have,
-              data,
-              bytes_left);
-      data += bytes_left;
-      length -= bytes_left;
-      sha1_transform (ctx->H, ctx->buffer);
-      bytes_have = 0;
-    }
-  }
-
-  while (SHA1_BLOCK_SIZE <= length)
-  {   /* Process any full blocks of new data directly,
-         without copying to the buffer. */
-    sha1_transform (ctx->H, data);
-    data += SHA1_BLOCK_SIZE;
-    length -= SHA1_BLOCK_SIZE;
-  }
-
-  if (0 != length)
-  {   /* Copy incomplete block of new data (if any)
-         to the buffer. */
-    memcpy (ctx->buffer + bytes_have, data, length);
-  }
-}
-
-
-/**
- * Size of "length" padding addition in bytes.
- * See FIPS PUB 180-4 paragraph 5.1.1.
- */
-#define SHA1_SIZE_OF_LEN_ADD (64 / 8)
-
-/**
- * Finalise SHA-1 calculation, return digest.
- *
- * @param ctx_ must be a `struct sha1_ctx *`
- * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes
- */
-void
-MHD_SHA1_finish (void *ctx_,
-                 uint8_t digest[SHA1_DIGEST_SIZE])
-{
-  struct sha1_ctx *const ctx = ctx_;
-  uint64_t num_bits;   /**< Number of processed bits */
-  unsigned bytes_have; /**< Number of bytes in buffer */
-
-  num_bits = ctx->count << 3;
-  /* Note: (count & (SHA1_BLOCK_SIZE-1))
-           equals (count % SHA1_BLOCK_SIZE) for this block size. */
-  bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1));
-
-  /* Input data must be padded with bit "1" and with length of data in bits.
-     See FIPS PUB 180-4 paragraph 5.1.1. */
-  /* Data is always processed in form of bytes (not by individual bits),
-     therefore position of first padding bit in byte is always predefined (0x80). */
-  /* Buffer always have space at least for one byte (as full buffers are
-     processed immediately). */
-  ctx->buffer[bytes_have++] = 0x80;
-
-  if (SHA1_BLOCK_SIZE - bytes_have < SHA1_SIZE_OF_LEN_ADD)
-  {   /* No space in current block to put total length of message.
-         Pad current block with zeros and process it. */
-    if (SHA1_BLOCK_SIZE > bytes_have)
-      memset (ctx->buffer + bytes_have, 0, SHA1_BLOCK_SIZE - bytes_have);
-    /* Process full block. */
-    sha1_transform (ctx->H, ctx->buffer);
-    /* Start new block. */
-    bytes_have = 0;
-  }
-
-  /* Pad the rest of the buffer with zeros. */
-  memset (ctx->buffer + bytes_have, 0,
-          SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD - bytes_have);
-  /* Put the number of bits in the processed message as a big-endian value. */
-  _MHD_PUT_64BIT_BE_SAFE (ctx->buffer + SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD,
-                          num_bits);
-  /* Process the full final block. */
-  sha1_transform (ctx->H, ctx->buffer);
-
-  /* Put final hash/digest in BE mode */
-#ifndef _MHD_PUT_32BIT_BE_UNALIGNED
-  if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN)
-  {
-    uint32_t alig_dgst[_SHA1_DIGEST_LENGTH];
-    _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]);
-    _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]);
-    _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]);
-    _MHD_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]);
-    _MHD_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]);
-    /* Copy result to unaligned destination address */
-    memcpy (digest, alig_dgst, SHA1_DIGEST_SIZE);
-  }
-  else
-#else  /* _MHD_PUT_32BIT_BE_UNALIGNED */
-  if (1)
-#endif /* _MHD_PUT_32BIT_BE_UNALIGNED */
-  {
-    _MHD_PUT_32BIT_BE (digest + 0 * SHA1_BYTES_IN_WORD, ctx->H[0]);
-    _MHD_PUT_32BIT_BE (digest + 1 * SHA1_BYTES_IN_WORD, ctx->H[1]);
-    _MHD_PUT_32BIT_BE (digest + 2 * SHA1_BYTES_IN_WORD, ctx->H[2]);
-    _MHD_PUT_32BIT_BE (digest + 3 * SHA1_BYTES_IN_WORD, ctx->H[3]);
-    _MHD_PUT_32BIT_BE (digest + 4 * SHA1_BYTES_IN_WORD, ctx->H[4]);
-  }
-
-  /* Erase potentially sensitive data. */
-  memset (ctx, 0, sizeof(struct sha1_ctx));
-}
diff --git a/src/microhttpd_ws/sha1.h b/src/microhttpd_ws/sha1.h
deleted file mode 100644
index 851a4429..00000000
--- 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file microhttpd/sha1.h
- * @brief  Calculation of SHA-1 digest
- * @author Karlson2k (Evgeny Grin)
- */
-
-#ifndef MHD_SHA1_H
-#define MHD_SHA1_H 1
-
-#include "mhd_options.h"
-#include <stdint.h>
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>  /* for size_t */
-#endif /* HAVE_STDDEF_H */
-
-/**
- *  SHA-1 digest is kept internally as 5 32-bit words.
- */
-#define _SHA1_DIGEST_LENGTH 5
-
-/**
- * Number of bits in single SHA-1 word
- */
-#define SHA1_WORD_SIZE_BITS 32
-
-/**
- * Number of bytes in single SHA-1 word
- */
-#define SHA1_BYTES_IN_WORD (SHA1_WORD_SIZE_BITS / 8)
-
-/**
- * Size of SHA-1 digest in bytes
- */
-#define SHA1_DIGEST_SIZE (_SHA1_DIGEST_LENGTH * SHA1_BYTES_IN_WORD)
-
-/**
- * Size of SHA-1 digest string in chars including termination NUL
- */
-#define SHA1_DIGEST_STRING_SIZE ((SHA1_DIGEST_SIZE) * 2 + 1)
-
-/**
- * Size of single processing block in bits
- */
-#define SHA1_BLOCK_SIZE_BITS 512
-
-/**
- * Size of single processing block in bytes
- */
-#define SHA1_BLOCK_SIZE (SHA1_BLOCK_SIZE_BITS / 8)
-
-
-struct sha1_ctx
-{
-  uint32_t H[_SHA1_DIGEST_LENGTH];    /**< Intermediate hash value / digest at end of calculation */
-  uint8_t buffer[SHA1_BLOCK_SIZE];    /**< SHA256 input data buffer */
-  uint64_t count;                     /**< number of bytes, mod 2^64 */
-};
-
-/**
- * Initialise structure for SHA-1 calculation.
- *
- * @param ctx must be a `struct sha1_ctx *`
- */
-void
-MHD_SHA1_init (void *ctx_);
-
-
-/**
- * Process portion of bytes.
- *
- * @param ctx_ must be a `struct sha1_ctx *`
- * @param data bytes to add to hash
- * @param length number of bytes in @a data
- */
-void
-MHD_SHA1_update (void *ctx_,
-                 const uint8_t *data,
-                 size_t length);
-
-
-/**
- * Finalise SHA-1 calculation, return digest.
- *
- * @param ctx_ must be a `struct sha1_ctx *`
- * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes
- */
-void
-MHD_SHA1_finish (void *ctx_,
-                 uint8_t digest[SHA1_DIGEST_SIZE]);
-
-#endif /* MHD_SHA1_H */
openSUSE Build Service is sponsored by