| /* |
| This file is part of libmicrohttpd |
| Copyright (C) 2021 Christian Grothoff (and other contributing authors) |
| |
| 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.h |
| * @brief interface for experimental web socket extension to libmicrohttpd |
| * @author David Gausmann |
| */ |
| /* |
| * *** WARNING! *** |
| * * The websockets interface is currently in "experimental" stage. * |
| * * It does not work on architectures with endianness different from * |
| * * big endian and little endian and may have some portability issues.* |
| * * API and ABI are not yet stable. * |
| */ |
| #ifndef MHD_MICROHTTPD_WS_H |
| #define MHD_MICROHTTPD_WS_H |
| |
| |
| #ifdef __cplusplus |
| extern "C" |
| { |
| #if 0 /* keep Emacsens' auto-indent happy */ |
| } |
| #endif |
| #endif |
| |
| |
| /** |
| * @brief Handle for the encoding/decoding of websocket data |
| * (one stream is used per websocket) |
| * @ingroup websocket |
| */ |
| struct MHD_WebSocketStream; |
| |
| /** |
| * @brief Flags for the initialization of a websocket stream |
| * `struct MHD_WebSocketStream` used by |
| * #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_FLAG |
| { |
| /** |
| * The websocket stream is initialized in server mode (default). |
| * Thus all outgoing payload will not be "masked". |
| * All incoming payload must be masked. |
| * This flag cannot be used together with #MHD_WEBSOCKET_FLAG_CLIENT |
| */ |
| MHD_WEBSOCKET_FLAG_SERVER = 0, |
| /** |
| * The websocket stream is initialized in client mode. |
| * You will usually never use that mode in combination with libmicrohttpd, |
| * because libmicrohttpd provides a server and not a client. |
| * In client mode all outgoing payload will be "masked" |
| * (XOR-ed with random values). |
| * All incoming payload must be unmasked. |
| * If you use this mode, you must always call #MHD_websocket_stream_init2() |
| * instead of #MHD_websocket_stream_init(), because you need |
| * to pass a random number generator callback function for masking. |
| * This flag cannot be used together with #MHD_WEBSOCKET_FLAG_SERVER |
| */ |
| MHD_WEBSOCKET_FLAG_CLIENT = 1, |
| /** |
| * You don't want to get fragmented data while decoding (default). |
| * Fragmented frames will be internally put together until |
| * they are complete. |
| * Whether or not data is fragmented is decided |
| * by the sender of the data during encoding. |
| * This cannot be used together with #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| */ |
| MHD_WEBSOCKET_FLAG_NO_FRAGMENTS = 0, |
| /** |
| * You want fragmented data, if it appears while decoding. |
| * You will receive the content of the fragmented frame, |
| * but if you are decoding text, you will never get an unfinished |
| * UTF-8 sequence (if the sequence appears between two fragments). |
| * Instead the text will end before the unfinished UTF-8 sequence. |
| * With the next fragment, which finishes the UTF-8 sequence, |
| * you will get the complete UTF-8 sequence. |
| * This cannot be used together with #MHD_WEBSOCKET_FLAG_NO_FRAGMENTS |
| */ |
| MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS = 2, |
| /** |
| * If the websocket stream becomes invalid during decoding due to |
| * protocol errors, a matching close frame will automatically |
| * be generated. |
| * The close frame will be returned via the parameters |
| * `payload` and `payload_len` of #MHD_websocket_decode() and |
| * the return value is negative |
| * (a value of `enum MHD_WEBSOCKET_STATUS`). |
| * The generated close frame must be freed by the caller |
| * with #MHD_websocket_free(). |
| */ |
| MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR = 4 |
| }; |
| |
| /** |
| * @brief Enum to specify the fragmenting behavior |
| * while encoding with #MHD_websocket_encode_text() or |
| * #MHD_websocket_encode_binary(). |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_FRAGMENTATION |
| { |
| /** |
| * You don't want to use fragmentation. |
| * The encoded frame consists of only one frame. |
| */ |
| MHD_WEBSOCKET_FRAGMENTATION_NONE = 0, |
| /** |
| * You want to use fragmentation. |
| * The encoded frame is the first frame of |
| * a series of data frames of the same type |
| * (text or binary). |
| * You may send control frames (ping, pong or close) |
| * between these data frames. |
| */ |
| MHD_WEBSOCKET_FRAGMENTATION_FIRST = 1, |
| /** |
| * You want to use fragmentation. |
| * The encoded frame is not the first frame of |
| * the series of data frames, but also not the last one. |
| * You may send control frames (ping, pong or close) |
| * between these data frames. |
| */ |
| MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING = 2, |
| /** |
| * You want to use fragmentation. |
| * The encoded frame is the last frame of |
| * the series of data frames, but also not the first one. |
| * After this frame, you may send all types of frames again. |
| */ |
| MHD_WEBSOCKET_FRAGMENTATION_LAST = 3 |
| }; |
| |
| /** |
| * @brief Enum of the return value for almost every MHD_websocket function. |
| * Errors are negative and values equal to or above zero mean a success. |
| * Positive values are only used by #MHD_websocket_decode(). |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_STATUS |
| { |
| /** |
| * The call succeeded. |
| * For #MHD_websocket_decode() this means that no error occurred, |
| * but also no frame has been completed yet. |
| * For other functions this means simply a success. |
| */ |
| MHD_WEBSOCKET_STATUS_OK = 0, |
| /** |
| * #MHD_websocket_decode() has decoded a text frame. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded text (if any). |
| */ |
| MHD_WEBSOCKET_STATUS_TEXT_FRAME = 0x1, |
| /** |
| * #MHD_websocket_decode() has decoded a binary frame. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded binary data (if any). |
| */ |
| MHD_WEBSOCKET_STATUS_BINARY_FRAME = 0x2, |
| /** |
| * #MHD_websocket_decode() has decoded a close frame. |
| * This means you must close the socket using #MHD_upgrade_action() |
| * with #MHD_UPGRADE_ACTION_CLOSE. |
| * You may respond with a close frame before closing. |
| * The parameters `payload` and `payload_len` are filled with |
| * the close reason (if any). |
| * The close reason starts with a two byte sequence of close code |
| * in network byte order (see `enum MHD_WEBSOCKET_CLOSEREASON`). |
| * After these two bytes a UTF-8 encoded close reason may follow. |
| * You can call #MHD_websocket_split_close_reason() to split that |
| * close reason. |
| */ |
| MHD_WEBSOCKET_STATUS_CLOSE_FRAME = 0x8, |
| /** |
| * #MHD_websocket_decode() has decoded a ping frame. |
| * You should respond to this with a pong frame. |
| * The pong frame must contain the same binary data as |
| * the corresponding ping frame (if it had any). |
| * The parameters `payload` and `payload_len` are filled with |
| * the binary ping data (if any). |
| */ |
| MHD_WEBSOCKET_STATUS_PING_FRAME = 0x9, |
| /** |
| * #MHD_websocket_decode() has decoded a pong frame. |
| * You should usually only receive pong frames if you sent |
| * a ping frame before. |
| * The binary data should be equal to your ping frame and can be |
| * used to distinguish the response if you sent multiple ping frames. |
| * The parameters `payload` and `payload_len` are filled with |
| * the binary pong data (if any). |
| */ |
| MHD_WEBSOCKET_STATUS_PONG_FRAME = 0xA, |
| /** |
| * #MHD_websocket_decode() has decoded a text frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded text (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_TEXT_FRAME, but it can only |
| * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during |
| * the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT = 0x11, |
| /** |
| * #MHD_websocket_decode() has decoded a binary frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded binary data (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_BINARY_FRAME, but it can only |
| * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during |
| * the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT = 0x12, |
| /** |
| * #MHD_websocket_decode() has decoded the next text frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded text (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, but it appears |
| * only after the first and before the last fragment of a series of fragments. |
| * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| * during the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_TEXT_NEXT_FRAGMENT = 0x21, |
| /** |
| * #MHD_websocket_decode() has decoded the next binary frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded binary data (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, but it appears |
| * only after the first and before the last fragment of a series of fragments. |
| * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| * during the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT = 0x22, |
| /** |
| * #MHD_websocket_decode() has decoded the last text frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded text (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, but it appears |
| * only for the last fragment of a series of fragments. |
| * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| * during the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT = 0x41, |
| /** |
| * #MHD_websocket_decode() has decoded the last binary frame fragment. |
| * The parameters `payload` and `payload_len` are filled with |
| * the decoded binary data (if any). |
| * This is like #MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, but it appears |
| * only for the last fragment of a series of fragments. |
| * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| * during the call of #MHD_websocket_stream_init() or |
| * #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT = 0x42, |
| /** |
| * The call failed and the stream is invalid now for decoding. |
| * You must close the websocket now using #MHD_upgrade_action() |
| * with #MHD_UPGRADE_ACTION_CLOSE. |
| * You may send a close frame before closing. |
| * This is only used by #MHD_websocket_decode() and happens |
| * if the stream contains errors (i. e. invalid byte data). |
| */ |
| MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR = -1, |
| /** |
| * You tried to decode something, but the stream has already |
| * been marked invalid. |
| * You must close the websocket now using #MHD_upgrade_action() |
| * with #MHD_UPGRADE_ACTION_CLOSE. |
| * You may send a close frame before closing. |
| * This is only used by #MHD_websocket_decode() and happens |
| * if you call #MDM_websocket_decode() again after |
| * has been invalidated. |
| * You can call #MHD_websocket_stream_is_valid() at any time |
| * to check whether a stream is invalid or not. |
| */ |
| MHD_WEBSOCKET_STATUS_STREAM_BROKEN = -2, |
| /** |
| * A memory allocation failed. The stream remains valid. |
| * If this occurred while decoding, the decoding could be |
| * possible later if enough memory is available. |
| * This could happen while decoding if you received a too big data frame. |
| * You could try to specify max_payload_size during the call of |
| * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2() to |
| * avoid this and close the websocket instead. |
| */ |
| MHD_WEBSOCKET_STATUS_MEMORY_ERROR = -3, |
| /** |
| * You passed invalid parameters during the function call |
| * (i. e. a NULL pointer for a required parameter). |
| * The stream remains valid. |
| */ |
| MHD_WEBSOCKET_STATUS_PARAMETER_ERROR = -4, |
| /** |
| * The maximum payload size has been exceeded. |
| * If you got this return code from #MHD_websocket_decode() then |
| * the stream becomes invalid and the websocket must be closed |
| * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. |
| * You may send a close frame before closing. |
| * The maximum payload size is specified during the call of |
| * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). |
| * This can also appear if you specified 0 as maximum payload size |
| * when the message is greater than the maximum allocatable memory size |
| * (i. e. more than 4 GiB on 32 bit systems). |
| * If you got this return code from #MHD_websocket_encode_close(), |
| * #MHD_websocket_encode_ping() or #MHD_websocket_encode_pong() then |
| * you passed to much payload data. The stream remains valid then. |
| */ |
| MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED = -5, |
| /** |
| * An UTF-8 sequence is invalid. |
| * If you got this return code from #MHD_websocket_decode() then |
| * the stream becomes invalid and you must close the websocket |
| * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. |
| * You may send a close frame before closing. |
| * If you got this from #MHD_websocket_encode_text() or |
| * #MHD_websocket_encode_close() then you passed invalid UTF-8 text. |
| * The stream remains valid then. |
| */ |
| MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR = -6, |
| /** |
| * A check routine for the HTTP headers came to the conclusion that |
| * the header value isn't valid for a websocket handshake request. |
| * This value can only be returned from the following functions: |
| * * #MHD_websocket_check_http_version() |
| * * #MHD_websocket_check_connection_header() |
| * * #MHD_websocket_check_upgrade_header() |
| * * #MHD_websocket_check_version_header() |
| * * #MHD_websocket_create_accept_header() |
| */ |
| MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER = -7 |
| }; |
| |
| /** |
| * @brief Enumeration of possible close reasons for close frames. |
| * |
| * The possible values are specified in RFC 6455 7.4.1 |
| * These close reasons here are the default set specified by RFC 6455, |
| * but also other close reasons could be used. |
| * |
| * The definition is for short: |
| * 0-999 are never used (if you pass 0 in |
| * #MHD_websocket_encode_close() then no close reason is used). |
| * 1000-2999 are specified by RFC 6455. |
| * 3000-3999 are specified by libraries, etc. but must be registered by IANA. |
| * 4000-4999 are reserved for private use. |
| * |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_CLOSEREASON |
| { |
| /** |
| * This value is used as placeholder for #MHD_websocket_encode_close() |
| * to tell that you don't want to specify any reason. |
| * If you use this value then no reason text may be used. |
| * This value cannot be a result of decoding, because this value |
| * is not a valid close reason for the websocket protocol. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_NO_REASON = 0, |
| /** |
| * You close the websocket because it fulfilled its purpose and shall |
| * now be closed in a normal, planned way. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_REGULAR = 1000, |
| /** |
| * You close the websocket because you are shutting down the server or |
| * something similar. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY = 1001, |
| /** |
| * You close the websocket because a protocol error occurred |
| * during decoding (i. e. invalid byte data). |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR = 1002, |
| /** |
| * You close the websocket because you received data which you don't accept. |
| * For example if you received a binary frame, |
| * but your application only expects text frames. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_UNSUPPORTED_DATATYPE = 1003, |
| /** |
| * You close the websocket because it contains malformed UTF-8. |
| * The UTF-8 validity is automatically checked by #MHD_websocket_decode(), |
| * so you don't need to check it on your own. |
| * UTF-8 is specified in RFC 3629. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8 = 1007, |
| /** |
| * You close the websocket because of any reason. |
| * Usually this close reason is used if no other close reason |
| * is more specific or if you don't want to use any other close reason. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_POLICY_VIOLATED = 1008, |
| /** |
| * You close the websocket because you received a frame which is too big |
| * to process. |
| * You can specify the maximum allowed payload size during the call of |
| * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED = 1009, |
| /** |
| * This status code can be sent by the client if it |
| * expected a specific extension, but this extension hasn't been negotiated. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_MISSING_EXTENSION = 1010, |
| /** |
| * The server closes the websocket because it encountered |
| * an unexpected condition that prevented it from fulfilling the request. |
| */ |
| MHD_WEBSOCKET_CLOSEREASON_UNEXPECTED_CONDITION = 1011 |
| }; |
| |
| /** |
| * @brief Enumeration of possible UTF-8 check steps |
| * |
| * These values are used during the encoding of fragmented text frames |
| * or for error analysis while encoding text frames. |
| * Its values specify the next step of the UTF-8 check. |
| * UTF-8 sequences consist of one to four bytes. |
| * This enumeration just says how long the current UTF-8 sequence is |
| * and what is the next expected byte. |
| * |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_UTF8STEP |
| { |
| /** |
| * There is no open UTF-8 sequence. |
| * The next byte must be 0x00-0x7F or 0xC2-0xF4. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_NORMAL = 0, |
| /** |
| * The second byte of a two byte UTF-8 sequence. |
| * The first byte was 0xC2-0xDF. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 = 1, |
| /** |
| * The second byte of a three byte UTF-8 sequence. |
| * The first byte was 0xE0. |
| * The next byte must be 0xA0-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2 = 2, |
| /** |
| * The second byte of a three byte UTF-8 sequence. |
| * The first byte was 0xED. |
| * The next byte must by 0x80-0x9F. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2 = 3, |
| /** |
| * The second byte of a three byte UTF-8 sequence. |
| * The first byte was 0xE1-0xEC or 0xEE-0xEF. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2 = 4, |
| /** |
| * The third byte of a three byte UTF-8 sequence. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2 = 5, |
| /** |
| * The second byte of a four byte UTF-8 sequence. |
| * The first byte was 0xF0. |
| * The next byte must be 0x90-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3 = 6, |
| /** |
| * The second byte of a four byte UTF-8 sequence. |
| * The first byte was 0xF4. |
| * The next byte must be 0x80-0x8F. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3 = 7, |
| /** |
| * The second byte of a four byte UTF-8 sequence. |
| * The first byte was 0xF1-0xF3. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3 = 8, |
| /** |
| * The third byte of a four byte UTF-8 sequence. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3 = 9, |
| /** |
| * The fourth byte of a four byte UTF-8 sequence. |
| * The next byte must be 0x80-0xBF. |
| */ |
| MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3 = 10 |
| }; |
| |
| /** |
| * @brief Enumeration of validity values |
| * |
| * These values are used for #MHD_websocket_stream_is_valid() |
| * and specify the validity status. |
| * |
| * @ingroup websocket |
| */ |
| enum MHD_WEBSOCKET_VALIDITY |
| { |
| /** |
| * The stream is invalid. |
| * It cannot be used for decoding anymore. |
| */ |
| MHD_WEBSOCKET_VALIDITY_INVALID = 0, |
| /** |
| * The stream is valid. |
| * Decoding works as expected. |
| */ |
| MHD_WEBSOCKET_VALIDITY_VALID = 1, |
| /** |
| * The stream has received a close frame and |
| * is partly invalid. |
| * You can still use the stream for decoding, |
| * but if a data frame is received an error will be reported. |
| * After a close frame has been sent, no data frames |
| * may follow from the sender of the close frame. |
| */ |
| MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES = 2 |
| }; |
| /** |
| * This callback function is used internally by many websocket functions |
| * for allocating data. |
| * By default `malloc()` is used. |
| * You can use your own allocation function with |
| * #MHD_websocket_stream_init2() if you wish to. |
| * This can be useful for operating systems like Windows |
| * where `malloc()`, `realloc()` and `free()` are compiler-dependent. |
| * You can call the associated `malloc()` callback of |
| * a websocket stream with #MHD_websocket_malloc(). |
| * |
| * @param buf_len buffer size in bytes |
| * @return allocated memory |
| * @ingroup websocket |
| */ |
| typedef void * |
| (*MHD_WebSocketMallocCallback) (size_t buf_len); |
| /** |
| * This callback function is used internally by many websocket |
| * functions for reallocating data. |
| * By default `realloc()` is used. |
| * You can use your own reallocation function with |
| * #MHD_websocket_stream_init2() if you wish to. |
| * This can be useful for operating systems like Windows |
| * where `malloc()`, `realloc()` and `free()` are compiler-dependent. |
| * You can call the associated `realloc()` callback of |
| * a websocket stream with #MHD_websocket_realloc(). |
| * |
| * @param buf buffer |
| * @param new_buf_len new buffer size in bytes |
| * @return reallocated memory |
| * @ingroup websocket |
| */ |
| typedef void * |
| (*MHD_WebSocketReallocCallback) (void *buf, size_t new_buf_len); |
| /** |
| * This callback function is used internally by many websocket |
| * functions for freeing data. |
| * By default `free()` is used. |
| * You can use your own free function with |
| * #MHD_websocket_stream_init2() if you wish to. |
| * This can be useful for operating systems like Windows |
| * where `malloc()`, `realloc()` and `free()` are compiler-dependent. |
| * You can call the associated `free()` callback of |
| * a websocket stream with #MHD_websocket_free(). |
| * |
| * @param buf buffer |
| * @ingroup websocket |
| */ |
| typedef void |
| (*MHD_WebSocketFreeCallback) (void *buf); |
| /** |
| * This callback function is used for generating random numbers |
| * for masking payload data in client mode. |
| * If you use websockets in server mode with libmicrohttpd then |
| * you don't need a random number generator, because |
| * the server doesn't mask its outgoing messageses. |
| * However if you wish to use a websocket stream in client mode, |
| * you must pass this callback function to #MHD_websocket_stream_init2(). |
| * |
| * @param cls closure specified in #MHD_websocket_stream_init2() |
| * @param buf buffer to fill with random values |
| * @param buf_len size of buffer in bytes |
| * @return The number of generated random bytes. |
| * Should usually equal to buf_len. |
| * @ingroup websocket |
| */ |
| typedef size_t |
| (*MHD_WebSocketRandomNumberGenerator) (void *cls, void *buf, size_t buf_len); |
| |
| /** |
| * Checks the HTTP version of the incoming request. |
| * Websocket requests are only allowed for HTTP/1.1 or above. |
| * |
| * @param http_version The value of the 'version' parameter of your |
| * access_handler callback |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * 0 means the HTTP version is correct for a websocket request, |
| * a value less than zero means that the HTTP version isn't |
| * valid for a websocket request. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_check_http_version (const char *http_version); |
| |
| /** |
| * Checks the value of the 'Connection' HTTP request header. |
| * Websocket requests require the token 'Upgrade' in |
| * the 'Connection' HTTP request header. |
| * |
| * @param connection_header The value of the 'Connection' request header. |
| * You can get this request header value by passing |
| * #MHD_HTTP_HEADER_CONNECTION to |
| * #MHD_lookup_connection_value(). |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * 0 means the 'Connection' request header is correct |
| * for a websocket request, |
| * a value less than zero means that the 'Connection' header isn't |
| * valid for a websocket request. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_check_connection_header (const char *connection_header); |
| |
| /** |
| * Checks the value of the 'Upgrade' HTTP request header. |
| * Websocket requests require the value 'websocket' in |
| * the 'Upgrade' HTTP request header. |
| * |
| * @param upgrade_header The value of the 'Upgrade' request header. |
| * You can get this request header value by passing |
| * #MHD_HTTP_HEADER_UPGRADE to |
| * #MHD_lookup_connection_value(). |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * 0 means the 'Upgrade' request header is correct |
| * for a websocket request, |
| * a value less than zero means that the 'Upgrade' header isn't |
| * valid for a websocket request. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_check_upgrade_header (const char *upgrade_header); |
| |
| /** |
| * Checks the value of the 'Sec-WebSocket-Version' HTTP request header. |
| * Websocket requests require the value '13' |
| * in the 'Sec-WebSocket-Version' HTTP request header. |
| * |
| * @param version_header The value of the 'Sec-WebSocket-Version' |
| * request header. |
| * You can get this request header value by passing |
| * #MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION to |
| * #MHD_lookup_connection_value(). |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * 0 means the 'Sec-WebSocket-Version' request header is correct |
| * for a websocket request, |
| * a value less than zero means that the 'Sec-WebSocket-Version' |
| * header isn't valid for a websocket request. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_check_version_header (const char *version_header); |
| |
| /** |
| * Creates the response value for the 'Sec-WebSocket-Key' HTTP request header. |
| * The generated value must be sent to the client |
| * as 'Sec-WebSocket-Accept' HTTP response header. |
| * |
| * @param sec_websocket_key The value of the 'Sec-WebSocket-Key' |
| * request header. |
| * You can get this request header value by passing |
| * #MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY to |
| * #MHD_lookup_connection_value(). |
| * @param[out] sec_websocket_accept The response buffer, which will receive |
| * the generated 'Sec-WebSocket-Accept' header. |
| * This buffer must be at least 29 bytes long and |
| * will contain the response value plus |
| * a terminating NUL on success. |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * Typically 0 on success or less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_create_accept_header (const char *sec_websocket_key, |
| char *sec_websocket_accept); |
| |
| /** |
| * Creates a new websocket stream, used for decoding/encoding. |
| * |
| * @param[out] ws The websocket stream |
| * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values |
| * to modify the behavior of the websocket stream. |
| * @param max_payload_size The maximum size for incoming payload |
| * data in bytes. Use 0 to allow each size. |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * Typically 0 on success or less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_stream_init (struct MHD_WebSocketStream **ws, |
| int flags, |
| size_t max_payload_size); |
| |
| /** |
| * Creates a new websocket stream, used for decoding/encoding, |
| * but with custom memory functions for malloc, realloc and free. |
| * Also a random number generator can be specified for client mode. |
| * |
| * @param[out] ws The websocket stream |
| * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values |
| * to modify the behavior of the websocket stream. |
| * @param max_payload_size The maximum size for incoming payload |
| * data in bytes. Use 0 to allow each size. |
| * @param callback_malloc The callback function for `malloc()`. |
| * @param callback_realloc The callback function for `realloc()`. |
| * @param callback_free The callback function for `free()`. |
| * @param cls_rng A closure for the random number generator callback. |
| * This is only required when |
| * MHD_WEBSOCKET_FLAG_CLIENT is passed in `flags`. |
| * The given value is passed to |
| * the random number generator. |
| * May be NULL if not needed. |
| * Should be NULL when you are |
| * not using MHD_WEBSOCKET_FLAG_CLIENT. |
| * @param callback_rng A callback function for a |
| * secure random number generator. |
| * This is only required when |
| * MHD_WEBSOCKET_FLAG_CLIENT is passed in `flags`. |
| * Should be NULL otherwise. |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * Typically 0 on success or less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Frees a websocket stream |
| * |
| * @param ws The websocket stream. This value may be NULL. |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * Typically 0 on success or less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_stream_free (struct MHD_WebSocketStream *ws); |
| |
| /** |
| * Invalidates a websocket stream. |
| * After invalidation a websocket stream cannot be used for decoding anymore. |
| * Encoding is still possible. |
| * |
| * @param ws The websocket stream. |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * Typically 0 on success or less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_STATUS |
| MHD_websocket_stream_invalidate (struct MHD_WebSocketStream *ws); |
| |
| /** |
| * Queries whether a websocket stream is valid. |
| * Invalidated websocket streams cannot be used for decoding anymore. |
| * Encoding is still possible. |
| * |
| * @param ws The websocket stream. |
| * @return A value of `enum MHD_WEBSOCKET_VALIDITY`. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN enum MHD_WEBSOCKET_VALIDITY |
| MHD_websocket_stream_is_valid (struct MHD_WebSocketStream *ws); |
| |
| /** |
| * Decodes a byte sequence for a websocket stream. |
| * Decoding is done until either a frame is complete or |
| * the end of the byte sequence is reached. |
| * |
| * @param ws The websocket stream. |
| * @param streambuf The byte sequence for decoding. |
| * Typically that what you received via `recv()`. |
| * @param streambuf_len The length of the byte sequence @a streambuf |
| * @param[out] streambuf_read_len The number of bytes which has been processed |
| * by this call. This value may be less |
| * than @a streambuf_len when a frame is decoded |
| * before the end of the buffer is reached. |
| * The remaining bytes of @a buf must be passed |
| * to the next call of this function. |
| * @param[out] payload Pointer to a variable, which receives a buffer |
| * with the decoded payload data. |
| * If no decoded data is available this is NULL. |
| * When the returned value is not NULL then |
| * the buffer contains always @a payload_len bytes plus |
| * one terminating NUL character. |
| * The caller must free this buffer |
| * using #MHD_websocket_free(). |
| * If you passed the flag |
| * #MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR |
| * upon creation of this websocket stream and |
| * a decoding error occurred |
| * (function return value less than 0), then this |
| * buffer contains a generated close frame |
| * which must be sent via the socket to the recipient. |
| * If you passed the flag #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS |
| * upon creation of the websocket stream then |
| * this payload may only be a part of the complete message. |
| * Only complete UTF-8 sequences are returned |
| * for fragmented text frames. |
| * If necessary the UTF-8 sequence will be completed |
| * with the next text fragment. |
| * @param[out] payload_len The length of the result payload buffer in bytes. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is greater than 0 if a frame has is complete, |
| * equal to 0 if more data is needed an less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Splits the payload of a decoded close frame. |
| * |
| * @param payload The payload of the close frame. |
| * This parameter may only be NULL if @a payload_len is 0. |
| * @param payload_len The length of @a payload. |
| * @param[out] reason_code The numeric close reason. |
| * If there was no close reason, this is |
| * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON. |
| * Compare with `enum MHD_WEBSOCKET_CLOSEREASON`. |
| * This parameter is optional and may be NULL. |
| * @param[out] reason_utf8 The literal close reason. |
| * If there was no literal close reason, this is NULL. |
| * This parameter is optional and may be NULL. |
| * Please note that no memory is allocated |
| * in this function. |
| * If not NULL the returned value of this parameter |
| * points to a position in the specified @a payload. |
| * @param[out] reason_utf8_len The length of the literal close reason. |
| * If there was no literal close reason, this is 0. |
| * This parameter is optional and may be NULL. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Encodes an UTF-8 encoded text into websocket text frame. |
| * |
| * @param ws The websocket stream. |
| * @param payload_utf8 The UTF-8 encoded text to send. |
| * This may be NULL if payload_utf8_len is 0. |
| * @param payload_utf8_len The length of the UTF-8 encoded text in bytes. |
| * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` |
| * to specify the fragmentation behavior. |
| * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE |
| * if you don't want to use fragmentation. |
| * @param[out] frame This variable receives a buffer with the encoded frame. |
| * This is what you typically send via `send()` to the recipient. |
| * If no encoded data is available this is NULL. |
| * When this variable is not NULL then the buffer contains always |
| * @a frame_len bytes plus one terminating NUL character. |
| * The caller must free this buffer using #MHD_websocket_free(). |
| * @param[out] frame_len The length of the encoded frame in bytes. |
| * @param[out] utf8_step This parameter is required for fragmentation and |
| * should be NULL if no fragmentation is used. |
| * It contains information about the last encoded |
| * UTF-8 sequence and is required to continue a previous |
| * UTF-8 sequence when fragmentation is used. |
| * `enum MHD_WEBSOCKET_UTF8STEP` is for this value. |
| * If you start a new fragment using |
| * MHD_WEBSOCKET_FRAGMENTATION_NONE or |
| * MHD_WEBSOCKET_FRAGMENTATION_FIRST the value |
| * of this variable will be initialized |
| * to MHD_WEBSOCKET_UTF8STEP_NORMAL. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Encodes binary data into websocket binary frame. |
| * |
| * @param ws The websocket stream. |
| * @param payload The binary data to send. |
| * @param payload_len The length of the binary data in bytes. |
| * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` |
| * to specify the fragmentation behavior. |
| * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE |
| * if you don't want to use fragmentation. |
| * @param[out] frame This variable receives a buffer with |
| * the encoded binary frame. |
| * This is what you typically send via `send()` |
| * to the recipient. |
| * If no encoded frame is available this is NULL. |
| * When this variable is not NULL then the allocated buffer |
| * contains always @a frame_len bytes plus one terminating |
| * NUL character. |
| * The caller must free this buffer using #MHD_websocket_free(). |
| * @param[out] frame_len The length of the result frame buffer in bytes. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Encodes a websocket ping frame |
| * |
| * @param ws The websocket stream. |
| * @param payload The binary ping payload data to send. |
| * This may be NULL if @a payload_len is 0. |
| * @param payload_len The length of the payload data in bytes. |
| * This may not exceed 125 bytes. |
| * @param[out] frame This variable receives a buffer with the encoded ping frame data. |
| * This is what you typically send via `send()` to the recipient. |
| * If no encoded frame is available this is NULL. |
| * When this variable is not NULL then the buffer contains always |
| * @a frame_len bytes plus one terminating NUL character. |
| * The caller must free this buffer using #MHD_websocket_free(). |
| * @param[out] frame_len The length of the result frame buffer in bytes. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Encodes a websocket pong frame |
| * |
| * @param ws The websocket stream. |
| * @param payload The binary pong payload data, which should be |
| * the decoded payload from the received ping frame. |
| * This may be NULL if @a payload_len is 0. |
| * @param payload_len The length of the payload data in bytes. |
| * This may not exceed 125 bytes. |
| * @param[out] frame This variable receives a buffer with |
| * the encoded pong frame data. |
| * This is what you typically send via `send()` |
| * to the recipient. |
| * If no encoded frame is available this is NULL. |
| * When this variable is not NULL then the buffer |
| * contains always @a frame_len bytes plus one |
| * terminating NUL character. |
| * The caller must free this buffer |
| * using #MHD_websocket_free(). |
| * @param[out] frame_len The length of the result frame buffer in bytes. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Encodes a websocket close frame |
| * |
| * @param ws The websocket stream. |
| * @param reason_code The reason for close. |
| * You can use `enum MHD_WEBSOCKET_CLOSEREASON` |
| * for typical reasons, |
| * but you are not limited to these values. |
| * The allowed values are specified in RFC 6455 7.4. |
| * If you don't want to enter a reason, you can specify |
| * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON then |
| * no reason is encoded. |
| * @param reason_utf8 An UTF-8 encoded text reason why the connection is closed. |
| * This may be NULL if @a reason_utf8_len is 0. |
| * This must be NULL if @a reason_code is |
| * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON (= 0). |
| * @param reason_utf8_len The length of the UTF-8 encoded text reason in bytes. |
| * This may not exceed 123 bytes. |
| * @param[out] frame This variable receives a buffer with |
| * the encoded close frame. |
| * This is what you typically send via `send()` |
| * to the recipient. |
| * If no encoded frame is available this is NULL. |
| * When this variable is not NULL then the buffer |
| * contains always @a frame_len bytes plus |
| * one terminating NUL character. |
| * The caller must free this buffer |
| * using #MHD_websocket_free(). |
| * @param[out] frame_len The length of the result frame buffer in bytes. |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _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); |
| |
| /** |
| * Allocates memory with the associated 'malloc' function |
| * of the websocket stream |
| * |
| * @param ws The websocket stream. |
| * @param buf_len The length of the memory to allocate in bytes |
| * |
| * @return The allocated memory on success or NULL on failure. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN void * |
| MHD_websocket_malloc (struct MHD_WebSocketStream *ws, |
| size_t buf_len); |
| |
| /** |
| * Reallocates memory with the associated 'realloc' function |
| * of the websocket stream |
| * |
| * @param ws The websocket stream. |
| * @param buf The previously allocated memory or NULL |
| * @param new_buf_len The new length of the memory in bytes |
| * |
| * @return The allocated memory on success or NULL on failure. |
| * If NULL is returned the previously allocated buffer |
| * remains valid. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN void * |
| MHD_websocket_realloc (struct MHD_WebSocketStream *ws, |
| void *buf, |
| size_t new_buf_len); |
| |
| /** |
| * Frees memory with the associated 'free' function |
| * of the websocket stream |
| * |
| * @param ws The websocket stream. |
| * @param buf The previously allocated memory or NULL |
| * |
| * @return A value of `enum MHD_WEBSOCKET_STATUS`. |
| * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success |
| * or a value less than 0 on errors. |
| * @ingroup websocket |
| */ |
| _MHD_EXTERN int |
| MHD_websocket_free (struct MHD_WebSocketStream *ws, |
| void *buf); |
| |
| #if 0 /* keep Emacsens' auto-indent happy */ |
| { |
| #endif |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |