1 /* 2 This file is part of libmicrohttpd 3 Copyright (C) 2021 Christian Grothoff (and other contributing authors) 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 /** 20 * @file microhttpd_ws.h 21 * @brief interface for experimental web socket extension to libmicrohttpd 22 * @author David Gausmann 23 */ 24 /* 25 * *** WARNING! *** 26 * * The websockets interface is currenly in "experimental" stage. * 27 * * It does not work on architectures with endianness different from * 28 * * big endian and little endian and may have some portability issues.* 29 * * API and ABI are not yet stable. * 30 */ 31 #ifndef MHD_MICROHTTPD_WS_H 32 #define MHD_MICROHTTPD_WS_H 33 34 35 #ifdef __cplusplus 36 extern "C" 37 { 38 #if 0 /* keep Emacsens' auto-indent happy */ 39 } 40 #endif 41 #endif 42 43 44 /** 45 * @brief Handle for the encoding/decoding of websocket data 46 * (one stream is used per websocket) 47 * @ingroup websocket 48 */ 49 struct MHD_WebSocketStream; 50 51 /** 52 * @brief Flags for the initialization of a websocket stream 53 * `struct MHD_WebSocketStream` used by 54 * #MHD_websocket_stream_init() or 55 * #MHD_websocket_stream_init2(). 56 * @ingroup websocket 57 */ 58 enum MHD_WEBSOCKET_FLAG 59 { 60 /** 61 * The websocket stream is initialized in server mode (default). 62 * Thus all outgoing payload will not be "masked". 63 * All incoming payload must be masked. 64 * This flag cannot be used together with #MHD_WEBSOCKET_FLAG_CLIENT 65 */ 66 MHD_WEBSOCKET_FLAG_SERVER = 0, 67 /** 68 * The websocket stream is initialized in client mode. 69 * You will usually never use that mode in combination with libmicrohttpd, 70 * because libmicrohttpd provides a server and not a client. 71 * In client mode all outgoing payload will be "masked" 72 * (XOR-ed with random values). 73 * All incoming payload must be unmasked. 74 * If you use this mode, you must always call #MHD_websocket_stream_init2() 75 * instead of #MHD_websocket_stream_init(), because you need 76 * to pass a random number generator callback function for masking. 77 * This flag cannot be used together with #MHD_WEBSOCKET_FLAG_SERVER 78 */ 79 MHD_WEBSOCKET_FLAG_CLIENT = 1, 80 /** 81 * You don't want to get fragmented data while decoding (default). 82 * Fragmented frames will be internally put together until 83 * they are complete. 84 * Whether or not data is fragmented is decided 85 * by the sender of the data during encoding. 86 * This cannot be used together with #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 87 */ 88 MHD_WEBSOCKET_FLAG_NO_FRAGMENTS = 0, 89 /** 90 * You want fragmented data, if it appears while decoding. 91 * You will receive the content of the fragmented frame, 92 * but if you are decoding text, you will never get an unfinished 93 * UTF-8 sequence (if the sequence appears between two fragments). 94 * Instead the text will end before the unfinished UTF-8 sequence. 95 * With the next fragment, which finishes the UTF-8 sequence, 96 * you will get the complete UTF-8 sequence. 97 * This cannot be used together with #MHD_WEBSOCKET_FLAG_NO_FRAGMENTS 98 */ 99 MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS = 2, 100 /** 101 * If the websocket stream becomes invalid during decoding due to 102 * protocol errors, a matching close frame will automatically 103 * be generated. 104 * The close frame will be returned via the parameters 105 * `payload` and `payload_len` of #MHD_websocket_decode() and 106 * the return value is negative 107 * (a value of `enum MHD_WEBSOCKET_STATUS`). 108 * The generated close frame must be freed by the caller 109 * with #MHD_websocket_free(). 110 */ 111 MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR = 4 112 }; 113 114 /** 115 * @brief Enum to specify the fragmenting behavior 116 * while encoding with #MHD_websocket_encode_text() or 117 * #MHD_websocket_encode_binary(). 118 * @ingroup websocket 119 */ 120 enum MHD_WEBSOCKET_FRAGMENTATION 121 { 122 /** 123 * You don't want to use fragmentation. 124 * The encoded frame consists of only one frame. 125 */ 126 MHD_WEBSOCKET_FRAGMENTATION_NONE = 0, 127 /** 128 * You want to use fragmentation. 129 * The encoded frame is the first frame of 130 * a series of data frames of the same type 131 * (text or binary). 132 * You may send control frames (ping, pong or close) 133 * between these data frames. 134 */ 135 MHD_WEBSOCKET_FRAGMENTATION_FIRST = 1, 136 /** 137 * You want to use fragmentation. 138 * The encoded frame is not the first frame of 139 * the series of data frames, but also not the last one. 140 * You may send control frames (ping, pong or close) 141 * between these data frames. 142 */ 143 MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING = 2, 144 /** 145 * You want to use fragmentation. 146 * The encoded frame is the last frame of 147 * the series of data frames, but also not the first one. 148 * After this frame, you may send all types of frames again. 149 */ 150 MHD_WEBSOCKET_FRAGMENTATION_LAST = 3 151 }; 152 153 /** 154 * @brief Enum of the return value for almost every MHD_websocket function. 155 * Errors are negative and values equal to or above zero mean a success. 156 * Positive values are only used by #MHD_websocket_decode(). 157 * @ingroup websocket 158 */ 159 enum MHD_WEBSOCKET_STATUS 160 { 161 /** 162 * The call succeeded. 163 * For #MHD_websocket_decode() this means that no error occurred, 164 * but also no frame has been completed yet. 165 * For other functions this means simply a success. 166 */ 167 MHD_WEBSOCKET_STATUS_OK = 0, 168 /** 169 * #MHD_websocket_decode() has decoded a text frame. 170 * The parameters `payload` and `payload_len` are filled with 171 * the decoded text (if any). 172 */ 173 MHD_WEBSOCKET_STATUS_TEXT_FRAME = 0x1, 174 /** 175 * #MHD_websocket_decode() has decoded a binary frame. 176 * The parameters `payload` and `payload_len` are filled with 177 * the decoded binary data (if any). 178 */ 179 MHD_WEBSOCKET_STATUS_BINARY_FRAME = 0x2, 180 /** 181 * #MHD_websocket_decode() has decoded a close frame. 182 * This means you must close the socket using #MHD_upgrade_action() 183 * with #MHD_UPGRADE_ACTION_CLOSE. 184 * You may respond with a close frame before closing. 185 * The parameters `payload` and `payload_len` are filled with 186 * the close reason (if any). 187 * The close reason starts with a two byte sequence of close code 188 * in network byte order (see `enum MHD_WEBSOCKET_CLOSEREASON`). 189 * After these two bytes a UTF-8 encoded close reason may follow. 190 * You can call #MHD_websocket_split_close_reason() to split that 191 * close reason. 192 */ 193 MHD_WEBSOCKET_STATUS_CLOSE_FRAME = 0x8, 194 /** 195 * #MHD_websocket_decode() has decoded a ping frame. 196 * You should respond to this with a pong frame. 197 * The pong frame must contain the same binary data as 198 * the corresponding ping frame (if it had any). 199 * The parameters `payload` and `payload_len` are filled with 200 * the binary ping data (if any). 201 */ 202 MHD_WEBSOCKET_STATUS_PING_FRAME = 0x9, 203 /** 204 * #MHD_websocket_decode() has decoded a pong frame. 205 * You should usually only receive pong frames if you sent 206 * a ping frame before. 207 * The binary data should be equal to your ping frame and can be 208 * used to distinguish the response if you sent multiple ping frames. 209 * The parameters `payload` and `payload_len` are filled with 210 * the binary pong data (if any). 211 */ 212 MHD_WEBSOCKET_STATUS_PONG_FRAME = 0xA, 213 /** 214 * #MHD_websocket_decode() has decoded a text frame fragment. 215 * The parameters `payload` and `payload_len` are filled with 216 * the decoded text (if any). 217 * This is like #MHD_WEBSOCKET_STATUS_TEXT_FRAME, but it can only 218 * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during 219 * the call of #MHD_websocket_stream_init() or 220 * #MHD_websocket_stream_init2(). 221 */ 222 MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT = 0x11, 223 /** 224 * #MHD_websocket_decode() has decoded a binary frame fragment. 225 * The parameters `payload` and `payload_len` are filled with 226 * the decoded binary data (if any). 227 * This is like #MHD_WEBSOCKET_STATUS_BINARY_FRAME, but it can only 228 * appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS during 229 * the call of #MHD_websocket_stream_init() or 230 * #MHD_websocket_stream_init2(). 231 */ 232 MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT = 0x12, 233 /** 234 * #MHD_websocket_decode() has decoded the next text frame fragment. 235 * The parameters `payload` and `payload_len` are filled with 236 * the decoded text (if any). 237 * This is like #MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, but it appears 238 * only after the first and before the last fragment of a series of fragments. 239 * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 240 * during the call of #MHD_websocket_stream_init() or 241 * #MHD_websocket_stream_init2(). 242 */ 243 MHD_WEBSOCKET_STATUS_TEXT_NEXT_FRAGMENT = 0x21, 244 /** 245 * #MHD_websocket_decode() has decoded the next binary frame fragment. 246 * The parameters `payload` and `payload_len` are filled with 247 * the decoded binary data (if any). 248 * This is like #MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, but it appears 249 * only after the first and before the last fragment of a series of fragments. 250 * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 251 * during the call of #MHD_websocket_stream_init() or 252 * #MHD_websocket_stream_init2(). 253 */ 254 MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT = 0x22, 255 /** 256 * #MHD_websocket_decode() has decoded the last text frame fragment. 257 * The parameters `payload` and `payload_len` are filled with 258 * the decoded text (if any). 259 * This is like #MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, but it appears 260 * only for the last fragment of a series of fragments. 261 * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 262 * during the call of #MHD_websocket_stream_init() or 263 * #MHD_websocket_stream_init2(). 264 */ 265 MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT = 0x41, 266 /** 267 * #MHD_websocket_decode() has decoded the last binary frame fragment. 268 * The parameters `payload` and `payload_len` are filled with 269 * the decoded binary data (if any). 270 * This is like #MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, but it appears 271 * only for the last fragment of a series of fragments. 272 * It can only appear if you specified #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 273 * during the call of #MHD_websocket_stream_init() or 274 * #MHD_websocket_stream_init2(). 275 */ 276 MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT = 0x42, 277 /** 278 * The call failed and the stream is invalid now for decoding. 279 * You must close the websocket now using #MHD_upgrade_action() 280 * with #MHD_UPGRADE_ACTION_CLOSE. 281 * You may send a close frame before closing. 282 * This is only used by #MHD_websocket_decode() and happens 283 * if the stream contains errors (i. e. invalid byte data). 284 */ 285 MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR = -1, 286 /** 287 * You tried to decode something, but the stream has already 288 * been marked invalid. 289 * You must close the websocket now using #MHD_upgrade_action() 290 * with #MHD_UPGRADE_ACTION_CLOSE. 291 * You may send a close frame before closing. 292 * This is only used by #MHD_websocket_decode() and happens 293 * if you call #MDM_websocket_decode() again after 294 * has been invalidated. 295 * You can call #MHD_websocket_stream_is_valid() at any time 296 * to check whether a stream is invalid or not. 297 */ 298 MHD_WEBSOCKET_STATUS_STREAM_BROKEN = -2, 299 /** 300 * A memory allocation failed. The stream remains valid. 301 * If this occurred while decoding, the decoding could be 302 * possible later if enough memory is available. 303 * This could happen while decoding if you received a too big data frame. 304 * You could try to specify max_payload_size during the call of 305 * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2() to 306 * avoid this and close the websocket instead. 307 */ 308 MHD_WEBSOCKET_STATUS_MEMORY_ERROR = -3, 309 /** 310 * You passed invalid parameters during the function call 311 * (i. e. a NULL pointer for a required parameter). 312 * The stream remains valid. 313 */ 314 MHD_WEBSOCKET_STATUS_PARAMETER_ERROR = -4, 315 /** 316 * The maximum payload size has been exceeded. 317 * If you got this return code from #MHD_websocket_decode() then 318 * the stream becomes invalid and the websocket must be closed 319 * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. 320 * You may send a close frame before closing. 321 * The maximum payload size is specified during the call of 322 * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). 323 * This can also appear if you specified 0 as maximum payload size 324 * when the message is greater than the maximum allocatable memory size 325 * (i. e. more than 4 GiB on 32 bit systems). 326 * If you got this return code from #MHD_websocket_encode_close(), 327 * #MHD_websocket_encode_ping() or #MHD_websocket_encode_pong() then 328 * you passed to much payload data. The stream remains valid then. 329 */ 330 MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED = -5, 331 /** 332 * An UTF-8 sequence is invalid. 333 * If you got this return code from #MHD_websocket_decode() then 334 * the stream becomes invalid and you must close the websocket 335 * using #MHD_upgrade_action() with #MHD_UPGRADE_ACTION_CLOSE. 336 * You may send a close frame before closing. 337 * If you got this from #MHD_websocket_encode_text() or 338 * #MHD_websocket_encode_close() then you passed invalid UTF-8 text. 339 * The stream remains valid then. 340 */ 341 MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR = -6, 342 /** 343 * A check routine for the HTTP headers came to the conclusion that 344 * the header value isn't valid for a websocket handshake request. 345 * This value can only be returned from the following functions: 346 * * #MHD_websocket_check_http_version() 347 * * #MHD_websocket_check_connection_header() 348 * * #MHD_websocket_check_upgrade_header() 349 * * #MHD_websocket_check_version_header() 350 * * #MHD_websocket_create_accept_header() 351 */ 352 MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER = -7 353 }; 354 355 /** 356 * @brief Enumeration of possible close reasons for close frames. 357 * 358 * The possible values are specified in RFC 6455 7.4.1 359 * These close reasons here are the default set specified by RFC 6455, 360 * but also other close reasons could be used. 361 * 362 * The definition is for short: 363 * 0-999 are never used (if you pass 0 in 364 * #MHD_websocket_encode_close() then no close reason is used). 365 * 1000-2999 are specified by RFC 6455. 366 * 3000-3999 are specified by libraries, etc. but must be registered by IANA. 367 * 4000-4999 are reserved for private use. 368 * 369 * @ingroup websocket 370 */ 371 enum MHD_WEBSOCKET_CLOSEREASON 372 { 373 /** 374 * This value is used as placeholder for #MHD_websocket_encode_close() 375 * to tell that you don't want to specify any reason. 376 * If you use this value then no reason text may be used. 377 * This value cannot be a result of decoding, because this value 378 * is not a valid close reason for the websocket protocol. 379 */ 380 MHD_WEBSOCKET_CLOSEREASON_NO_REASON = 0, 381 /** 382 * You close the websocket because it fulfilled its purpose and shall 383 * now be closed in a normal, planned way. 384 */ 385 MHD_WEBSOCKET_CLOSEREASON_REGULAR = 1000, 386 /** 387 * You close the websocket because you are shutting down the server or 388 * something similar. 389 */ 390 MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY = 1001, 391 /** 392 * You close the websocket because a protocol error occurred 393 * during decoding (i. e. invalid byte data). 394 */ 395 MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR = 1002, 396 /** 397 * You close the websocket because you received data which you don't accept. 398 * For example if you received a binary frame, 399 * but your application only expects text frames. 400 */ 401 MHD_WEBSOCKET_CLOSEREASON_UNSUPPORTED_DATATYPE = 1003, 402 /** 403 * You close the websocket because it contains malformed UTF-8. 404 * The UTF-8 validity is automatically checked by #MHD_websocket_decode(), 405 * so you don't need to check it on your own. 406 * UTF-8 is specified in RFC 3629. 407 */ 408 MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8 = 1007, 409 /** 410 * You close the websocket because of any reason. 411 * Usually this close reason is used if no other close reason 412 * is more specific or if you don't want to use any other close reason. 413 */ 414 MHD_WEBSOCKET_CLOSEREASON_POLICY_VIOLATED = 1008, 415 /** 416 * You close the websocket because you received a frame which is too big 417 * to process. 418 * You can specify the maximum allowed payload size during the call of 419 * #MHD_websocket_stream_init() or #MHD_websocket_stream_init2(). 420 */ 421 MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED = 1009, 422 /** 423 * This status code can be sent by the client if it 424 * expected a specific extension, but this extension hasn't been negotiated. 425 */ 426 MHD_WEBSOCKET_CLOSEREASON_MISSING_EXTENSION = 1010, 427 /** 428 * The server closes the websocket because it encountered 429 * an unexpected condition that prevented it from fulfilling the request. 430 */ 431 MHD_WEBSOCKET_CLOSEREASON_UNEXPECTED_CONDITION = 1011 432 }; 433 434 /** 435 * @brief Enumeration of possible UTF-8 check steps 436 * 437 * These values are used during the encoding of fragmented text frames 438 * or for error analysis while encoding text frames. 439 * Its values specify the next step of the UTF-8 check. 440 * UTF-8 sequences consist of one to four bytes. 441 * This enumeration just says how long the current UTF-8 sequence is 442 * and what is the next expected byte. 443 * 444 * @ingroup websocket 445 */ 446 enum MHD_WEBSOCKET_UTF8STEP 447 { 448 /** 449 * There is no open UTF-8 sequence. 450 * The next byte must be 0x00-0x7F or 0xC2-0xF4. 451 */ 452 MHD_WEBSOCKET_UTF8STEP_NORMAL = 0, 453 /** 454 * The second byte of a two byte UTF-8 sequence. 455 * The first byte was 0xC2-0xDF. 456 * The next byte must be 0x80-0xBF. 457 */ 458 MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 = 1, 459 /** 460 * The second byte of a three byte UTF-8 sequence. 461 * The first byte was 0xE0. 462 * The next byte must be 0xA0-0xBF. 463 */ 464 MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2 = 2, 465 /** 466 * The second byte of a three byte UTF-8 sequence. 467 * The first byte was 0xED. 468 * The next byte must by 0x80-0x9F. 469 */ 470 MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2 = 3, 471 /** 472 * The second byte of a three byte UTF-8 sequence. 473 * The first byte was 0xE1-0xEC or 0xEE-0xEF. 474 * The next byte must be 0x80-0xBF. 475 */ 476 MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2 = 4, 477 /** 478 * The third byte of a three byte UTF-8 sequence. 479 * The next byte must be 0x80-0xBF. 480 */ 481 MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2 = 5, 482 /** 483 * The second byte of a four byte UTF-8 sequence. 484 * The first byte was 0xF0. 485 * The next byte must be 0x90-0xBF. 486 */ 487 MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3 = 6, 488 /** 489 * The second byte of a four byte UTF-8 sequence. 490 * The first byte was 0xF4. 491 * The next byte must be 0x80-0x8F. 492 */ 493 MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3 = 7, 494 /** 495 * The second byte of a four byte UTF-8 sequence. 496 * The first byte was 0xF1-0xF3. 497 * The next byte must be 0x80-0xBF. 498 */ 499 MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3 = 8, 500 /** 501 * The third byte of a four byte UTF-8 sequence. 502 * The next byte must be 0x80-0xBF. 503 */ 504 MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3 = 9, 505 /** 506 * The fourth byte of a four byte UTF-8 sequence. 507 * The next byte must be 0x80-0xBF. 508 */ 509 MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3 = 10 510 }; 511 512 /** 513 * @brief Enumeration of validity values 514 * 515 * These values are used for #MHD_websocket_stream_is_valid() 516 * and specify the validity status. 517 * 518 * @ingroup websocket 519 */ 520 enum MHD_WEBSOCKET_VALIDITY 521 { 522 /** 523 * The stream is invalid. 524 * It cannot be used for decoding anymore. 525 */ 526 MHD_WEBSOCKET_VALIDITY_INVALID = 0, 527 /** 528 * The stream is valid. 529 * Decoding works as expected. 530 */ 531 MHD_WEBSOCKET_VALIDITY_VALID = 1, 532 /** 533 * The stream has received a close frame and 534 * is partly invalid. 535 * You can still use the stream for decoding, 536 * but if a data frame is received an error will be reported. 537 * After a close frame has been sent, no data frames 538 * may follow from the sender of the close frame. 539 */ 540 MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES = 2 541 }; 542 /** 543 * This callback function is used internally by many websocket functions 544 * for allocating data. 545 * By default `malloc()` is used. 546 * You can use your own allocation function with 547 * #MHD_websocket_stream_init2() if you wish to. 548 * This can be useful for operating systems like Windows 549 * where `malloc()`, `realloc()` and `free()` are compiler-dependent. 550 * You can call the associated `malloc()` callback of 551 * a websocket stream with #MHD_websocket_malloc(). 552 * 553 * @param buf_len buffer size in bytes 554 * @return allocated memory 555 * @ingroup websocket 556 */ 557 typedef void * 558 (*MHD_WebSocketMallocCallback) (size_t buf_len); 559 /** 560 * This callback function is used internally by many websocket 561 * functions for reallocating data. 562 * By default `realloc()` is used. 563 * You can use your own reallocation function with 564 * #MHD_websocket_stream_init2() if you wish to. 565 * This can be useful for operating systems like Windows 566 * where `malloc()`, `realloc()` and `free()` are compiler-dependent. 567 * You can call the associated `realloc()` callback of 568 * a websocket stream with #MHD_websocket_realloc(). 569 * 570 * @param buf buffer 571 * @param new_buf_len new buffer size in bytes 572 * @return reallocated memory 573 * @ingroup websocket 574 */ 575 typedef void * 576 (*MHD_WebSocketReallocCallback) (void *buf, size_t new_buf_len); 577 /** 578 * This callback function is used internally by many websocket 579 * functions for freeing data. 580 * By default `free()` is used. 581 * You can use your own free function with 582 * #MHD_websocket_stream_init2() if you wish to. 583 * This can be useful for operating systems like Windows 584 * where `malloc()`, `realloc()` and `free()` are compiler-dependent. 585 * You can call the associated `free()` callback of 586 * a websocket stream with #MHD_websocket_free(). 587 * 588 * @param buf buffer 589 * @ingroup websocket 590 */ 591 typedef void 592 (*MHD_WebSocketFreeCallback) (void *buf); 593 /** 594 * This callback function is used for generating random numbers 595 * for masking payload data in client mode. 596 * If you use websockets in server mode with libmicrohttpd then 597 * you don't need a random number generator, because 598 * the server doesn't mask its outgoing messageses. 599 * However if you wish to use a websocket stream in client mode, 600 * you must pass this callback function to #MHD_websocket_stream_init2(). 601 * 602 * @param cls closure specified in #MHD_websocket_stream_init2() 603 * @param buf buffer to fill with random values 604 * @param buf_len size of buffer in bytes 605 * @return The number of generated random bytes. 606 * Should usually equal to buf_len. 607 * @ingroup websocket 608 */ 609 typedef size_t 610 (*MHD_WebSocketRandomNumberGenerator) (void *cls, void *buf, size_t buf_len); 611 612 /** 613 * Checks the HTTP version of the incoming request. 614 * Websocket requests are only allowed for HTTP/1.1 or above. 615 * 616 * @param http_version The value of the 'version' parameter of your 617 * access_handler callback 618 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 619 * 0 means the HTTP version is correct for a websocket request, 620 * a value less than zero means that the HTTP version isn't 621 * valid for a websocket request. 622 * @ingroup websocket 623 */ 624 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 625 MHD_websocket_check_http_version (const char *http_version); 626 627 /** 628 * Checks the value of the 'Connection' HTTP request header. 629 * Websocket requests require the token 'Upgrade' in 630 * the 'Connection' HTTP request header. 631 * 632 * @param connection_header The value of the 'Connection' request header. 633 * You can get this request header value by passing 634 * #MHD_HTTP_HEADER_CONNECTION to 635 * #MHD_lookup_connection_value(). 636 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 637 * 0 means the 'Connection' request header is correct 638 * for a websocket request, 639 * a value less than zero means that the 'Connection' header isn't 640 * valid for a websocket request. 641 * @ingroup websocket 642 */ 643 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 644 MHD_websocket_check_connection_header (const char *connection_header); 645 646 /** 647 * Checks the value of the 'Upgrade' HTTP request header. 648 * Websocket requests require the value 'websocket' in 649 * the 'Upgrade' HTTP request header. 650 * 651 * @param upgrade_header The value of the 'Upgrade' request header. 652 * You can get this request header value by passing 653 * #MHD_HTTP_HEADER_UPGRADE to 654 * #MHD_lookup_connection_value(). 655 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 656 * 0 means the 'Upgrade' request header is correct 657 * for a websocket request, 658 * a value less than zero means that the 'Upgrade' header isn't 659 * valid for a websocket request. 660 * @ingroup websocket 661 */ 662 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 663 MHD_websocket_check_upgrade_header (const char *upgrade_header); 664 665 /** 666 * Checks the value of the 'Sec-WebSocket-Version' HTTP request header. 667 * Websocket requests require the value '13' 668 * in the 'Sec-WebSocket-Version' HTTP request header. 669 * 670 * @param version_header The value of the 'Sec-WebSocket-Version' 671 * request header. 672 * You can get this request header value by passing 673 * #MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION to 674 * #MHD_lookup_connection_value(). 675 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 676 * 0 means the 'Sec-WebSocket-Version' request header is correct 677 * for a websocket request, 678 * a value less than zero means that the 'Sec-WebSocket-Version' 679 * header isn't valid for a websocket request. 680 * @ingroup websocket 681 */ 682 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 683 MHD_websocket_check_version_header (const char *version_header); 684 685 /** 686 * Creates the response value for the 'Sec-WebSocket-Key' HTTP request header. 687 * The generated value must be sent to the client 688 * as 'Sec-WebSocket-Accept' HTTP response header. 689 * 690 * @param sec_websocket_key The value of the 'Sec-WebSocket-Key' 691 * request header. 692 * You can get this request header value by passing 693 * #MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY to 694 * #MHD_lookup_connection_value(). 695 * @param[out] sec_websocket_accept The response buffer, which will receive 696 * the generated 'Sec-WebSocket-Accept' header. 697 * This buffer must be at least 29 bytes long and 698 * will contain the response value plus 699 * a terminating NUL on success. 700 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 701 * Typically 0 on success or less than 0 on errors. 702 * @ingroup websocket 703 */ 704 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 705 MHD_websocket_create_accept_header (const char *sec_websocket_key, 706 char *sec_websocket_accept); 707 708 /** 709 * Creates a new websocket stream, used for decoding/encoding. 710 * 711 * @param[out] ws The websocket stream 712 * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values 713 * to modify the behavior of the websocket stream. 714 * @param max_payload_size The maximum size for incoming payload 715 * data in bytes. Use 0 to allow each size. 716 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 717 * Typically 0 on success or less than 0 on errors. 718 * @ingroup websocket 719 */ 720 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 721 MHD_websocket_stream_init (struct MHD_WebSocketStream **ws, 722 int flags, 723 size_t max_payload_size); 724 725 /** 726 * Creates a new websocket stream, used for decoding/encoding, 727 * but with custom memory functions for malloc, realloc and free. 728 * Also a random number generator can be specified for client mode. 729 * 730 * @param[out] ws The websocket stream 731 * @param flags Combination of `enum MHD_WEBSOCKET_FLAG` values 732 * to modify the behavior of the websocket stream. 733 * @param max_payload_size The maximum size for incoming payload 734 * data in bytes. Use 0 to allow each size. 735 * @param callback_malloc The callback function for `malloc()`. 736 * @param callback_realloc The callback function for `realloc()`. 737 * @param callback_free The callback function for `free()`. 738 * @param cls_rng A closure for the random number generator callback. 739 * This is only required when 740 * MHD_WEBSOCKET_FLAG_CLIENT is passed in `flags`. 741 * The given value is passed to 742 * the random number generator. 743 * May be NULL if not needed. 744 * Should be NULL when you are 745 * not using MHD_WEBSOCKET_FLAG_CLIENT. 746 * @param callback_rng A callback function for a 747 * secure random number generator. 748 * This is only required when 749 * MHD_WEBSOCKET_FLAG_CLIENT is passed in `flags`. 750 * Should be NULL otherwise. 751 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 752 * Typically 0 on success or less than 0 on errors. 753 * @ingroup websocket 754 */ 755 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 756 MHD_websocket_stream_init2 (struct MHD_WebSocketStream **ws, 757 int flags, 758 size_t max_payload_size, 759 MHD_WebSocketMallocCallback callback_malloc, 760 MHD_WebSocketReallocCallback callback_realloc, 761 MHD_WebSocketFreeCallback callback_free, 762 void *cls_rng, 763 MHD_WebSocketRandomNumberGenerator callback_rng); 764 765 /** 766 * Frees a websocket stream 767 * 768 * @param ws The websocket stream. This value may be NULL. 769 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 770 * Typically 0 on success or less than 0 on errors. 771 * @ingroup websocket 772 */ 773 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 774 MHD_websocket_stream_free (struct MHD_WebSocketStream *ws); 775 776 /** 777 * Invalidates a websocket stream. 778 * After invalidation a websocket stream cannot be used for decoding anymore. 779 * Encoding is still possible. 780 * 781 * @param ws The websocket stream. 782 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 783 * Typically 0 on success or less than 0 on errors. 784 * @ingroup websocket 785 */ 786 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 787 MHD_websocket_stream_invalidate (struct MHD_WebSocketStream *ws); 788 789 /** 790 * Queries whether a websocket stream is valid. 791 * Invalidated websocket streams cannot be used for decoding anymore. 792 * Encoding is still possible. 793 * 794 * @param ws The websocket stream. 795 * @return A value of `enum MHD_WEBSOCKET_VALIDITY`. 796 * @ingroup websocket 797 */ 798 _MHD_EXTERN enum MHD_WEBSOCKET_VALIDITY 799 MHD_websocket_stream_is_valid (struct MHD_WebSocketStream *ws); 800 801 /** 802 * Decodes a byte sequence for a websocket stream. 803 * Decoding is done until either a frame is complete or 804 * the end of the byte sequence is reached. 805 * 806 * @param ws The websocket stream. 807 * @param streambuf The byte sequence for decoding. 808 * Typically that what you received via `recv()`. 809 * @param streambuf_len The length of the byte sequence @a streambuf 810 * @param[out] streambuf_read_len The number of bytes which has been processed 811 * by this call. This value may be less 812 * than @a streambuf_len when a frame is decoded 813 * before the end of the buffer is reached. 814 * The remaining bytes of @a buf must be passed 815 * to the next call of this function. 816 * @param[out] payload Pointer to a variable, which receives a buffer 817 * with the decoded payload data. 818 * If no decoded data is available this is NULL. 819 * When the returned value is not NULL then 820 * the buffer contains always @a payload_len bytes plus 821 * one terminating NUL character. 822 * The caller must free this buffer 823 * using #MHD_websocket_free(). 824 * If you passed the flag 825 * #MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR 826 * upon creation of this websocket stream and 827 * a decoding error occurred 828 * (function return value less than 0), then this 829 * buffer contains a generated close frame 830 * which must be sent via the socket to the recipient. 831 * If you passed the flag #MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS 832 * upon creation of the websocket stream then 833 * this payload may only be a part of the complete message. 834 * Only complete UTF-8 sequences are returned 835 * for fragmented text frames. 836 * If necessary the UTF-8 sequence will be completed 837 * with the next text fragment. 838 * @param[out] payload_len The length of the result payload buffer in bytes. 839 * 840 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 841 * This is greater than 0 if a frame has is complete, 842 * equal to 0 if more data is needed an less than 0 on errors. 843 * @ingroup websocket 844 */ 845 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 846 MHD_websocket_decode (struct MHD_WebSocketStream *ws, 847 const char *streambuf, 848 size_t streambuf_len, 849 size_t *streambuf_read_len, 850 char **payload, 851 size_t *payload_len); 852 853 /** 854 * Splits the payload of a decoded close frame. 855 * 856 * @param payload The payload of the close frame. 857 * This parameter may only be NULL if @a payload_len is 0. 858 * @param payload_len The length of @a payload. 859 * @param[out] reason_code The numeric close reason. 860 * If there was no close reason, this is 861 * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON. 862 * Compare with `enum MHD_WEBSOCKET_CLOSEREASON`. 863 * This parameter is optional and may be NULL. 864 * @param[out] reason_utf8 The literal close reason. 865 * If there was no literal close reason, this is NULL. 866 * This parameter is optional and may be NULL. 867 * Please note that no memory is allocated 868 * in this function. 869 * If not NULL the returned value of this parameter 870 * points to a position in the specified @a payload. 871 * @param[out] reason_utf8_len The length of the literal close reason. 872 * If there was no literal close reason, this is 0. 873 * This parameter is optional and may be NULL. 874 * 875 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 876 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 877 * or a value less than 0 on errors. 878 * @ingroup websocket 879 */ 880 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 881 MHD_websocket_split_close_reason (const char *payload, 882 size_t payload_len, 883 unsigned short *reason_code, 884 const char **reason_utf8, 885 size_t *reason_utf8_len); 886 887 /** 888 * Encodes an UTF-8 encoded text into websocket text frame. 889 * 890 * @param ws The websocket stream. 891 * @param payload_utf8 The UTF-8 encoded text to send. 892 * This may be NULL if payload_utf8_len is 0. 893 * @param payload_utf8_len The length of the UTF-8 encoded text in bytes. 894 * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` 895 * to specify the fragmentation behavior. 896 * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE 897 * if you don't want to use fragmentation. 898 * @param[out] frame This variable receives a buffer with the encoded frame. 899 * This is what you typically send via `send()` to the recipient. 900 * If no encoded data is available this is NULL. 901 * When this variable is not NULL then the buffer contains always 902 * @a frame_len bytes plus one terminating NUL character. 903 * The caller must free this buffer using #MHD_websocket_free(). 904 * @param[out] frame_len The length of the encoded frame in bytes. 905 * @param[out] utf8_step This parameter is required for fragmentation and 906 * should be NULL if no fragmentation is used. 907 * It contains information about the last encoded 908 * UTF-8 sequence and is required to continue a previous 909 * UTF-8 sequence when fragmentation is used. 910 * `enum MHD_WEBSOCKET_UTF8STEP` is for this value. 911 * If you start a new fragment using 912 * MHD_WEBSOCKET_FRAGMENTATION_NONE or 913 * MHD_WEBSOCKET_FRAGMENTATION_FIRST the value 914 * of this variable will be initialized 915 * to MHD_WEBSOCKET_UTF8STEP_NORMAL. 916 * 917 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 918 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 919 * or a value less than 0 on errors. 920 * @ingroup websocket 921 */ 922 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 923 MHD_websocket_encode_text (struct MHD_WebSocketStream *ws, 924 const char *payload_utf8, 925 size_t payload_utf8_len, 926 int fragmentation, 927 char **frame, 928 size_t *frame_len, 929 int *utf8_step); 930 931 /** 932 * Encodes binary data into websocket binary frame. 933 * 934 * @param ws The websocket stream. 935 * @param payload The binary data to send. 936 * @param payload_len The length of the binary data in bytes. 937 * @param fragmentation A value of `enum MHD_WEBSOCKET_FRAGMENTATION` 938 * to specify the fragmentation behavior. 939 * Specify MHD_WEBSOCKET_FRAGMENTATION_NONE 940 * if you don't want to use fragmentation. 941 * @param[out] frame This variable receives a buffer with 942 * the encoded binary frame. 943 * This is what you typically send via `send()` 944 * to the recipient. 945 * If no encoded frame is available this is NULL. 946 * When this variable is not NULL then the allocated buffer 947 * contains always @a frame_len bytes plus one terminating 948 * NUL character. 949 * The caller must free this buffer using #MHD_websocket_free(). 950 * @param[out] frame_len The length of the result frame buffer in bytes. 951 * 952 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 953 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 954 * or a value less than 0 on errors. 955 * @ingroup websocket 956 */ 957 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 958 MHD_websocket_encode_binary (struct MHD_WebSocketStream *ws, 959 const char *payload, 960 size_t payload_len, 961 int fragmentation, 962 char **frame, 963 size_t *frame_len); 964 965 /** 966 * Encodes a websocket ping frame 967 * 968 * @param ws The websocket stream. 969 * @param payload The binary ping payload data to send. 970 * This may be NULL if @a payload_len is 0. 971 * @param payload_len The length of the payload data in bytes. 972 * This may not exceed 125 bytes. 973 * @param[out] frame This variable receives a buffer with the encoded ping frame data. 974 * This is what you typically send via `send()` to the recipient. 975 * If no encoded frame is available this is NULL. 976 * When this variable is not NULL then the buffer contains always 977 * @a frame_len bytes plus one terminating NUL character. 978 * The caller must free this buffer using #MHD_websocket_free(). 979 * @param[out] frame_len The length of the result frame buffer in bytes. 980 * 981 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 982 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 983 * or a value less than 0 on errors. 984 * @ingroup websocket 985 */ 986 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 987 MHD_websocket_encode_ping (struct MHD_WebSocketStream *ws, 988 const char *payload, 989 size_t payload_len, 990 char **frame, 991 size_t *frame_len); 992 993 /** 994 * Encodes a websocket pong frame 995 * 996 * @param ws The websocket stream. 997 * @param payload The binary pong payload data, which should be 998 * the decoded payload from the received ping frame. 999 * This may be NULL if @a payload_len is 0. 1000 * @param payload_len The length of the payload data in bytes. 1001 * This may not exceed 125 bytes. 1002 * @param[out] frame This variable receives a buffer with 1003 * the encoded pong frame data. 1004 * This is what you typically send via `send()` 1005 * to the recipient. 1006 * If no encoded frame is available this is NULL. 1007 * When this variable is not NULL then the buffer 1008 * contains always @a frame_len bytes plus one 1009 * terminating NUL character. 1010 * The caller must free this buffer 1011 * using #MHD_websocket_free(). 1012 * @param[out] frame_len The length of the result frame buffer in bytes. 1013 * 1014 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 1015 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 1016 * or a value less than 0 on errors. 1017 * @ingroup websocket 1018 */ 1019 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 1020 MHD_websocket_encode_pong (struct MHD_WebSocketStream *ws, 1021 const char *payload, 1022 size_t payload_len, 1023 char **frame, 1024 size_t *frame_len); 1025 1026 /** 1027 * Encodes a websocket close frame 1028 * 1029 * @param ws The websocket stream. 1030 * @param reason_code The reason for close. 1031 * You can use `enum MHD_WEBSOCKET_CLOSEREASON` 1032 * for typical reasons, 1033 * but you are not limited to these values. 1034 * The allowed values are specified in RFC 6455 7.4. 1035 * If you don't want to enter a reason, you can specify 1036 * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON then 1037 * no reason is encoded. 1038 * @param reason_utf8 An UTF-8 encoded text reason why the connection is closed. 1039 * This may be NULL if @a reason_utf8_len is 0. 1040 * This must be NULL if @a reason_code is 1041 * #MHD_WEBSOCKET_CLOSEREASON_NO_REASON (= 0). 1042 * @param reason_utf8_len The length of the UTF-8 encoded text reason in bytes. 1043 * This may not exceed 123 bytes. 1044 * @param[out] frame This variable receives a buffer with 1045 * the encoded close frame. 1046 * This is what you typically send via `send()` 1047 * to the recipient. 1048 * If no encoded frame is available this is NULL. 1049 * When this variable is not NULL then the buffer 1050 * contains always @a frame_len bytes plus 1051 * one terminating NUL character. 1052 * The caller must free this buffer 1053 * using #MHD_websocket_free(). 1054 * @param[out] frame_len The length of the result frame buffer in bytes. 1055 * 1056 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 1057 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 1058 * or a value less than 0 on errors. 1059 * @ingroup websocket 1060 */ 1061 _MHD_EXTERN enum MHD_WEBSOCKET_STATUS 1062 MHD_websocket_encode_close (struct MHD_WebSocketStream *ws, 1063 unsigned short reason_code, 1064 const char *reason_utf8, 1065 size_t reason_utf8_len, 1066 char **frame, 1067 size_t *frame_len); 1068 1069 /** 1070 * Allocates memory with the associated 'malloc' function 1071 * of the websocket stream 1072 * 1073 * @param ws The websocket stream. 1074 * @param buf_len The length of the memory to allocate in bytes 1075 * 1076 * @return The allocated memory on success or NULL on failure. 1077 * @ingroup websocket 1078 */ 1079 _MHD_EXTERN void * 1080 MHD_websocket_malloc (struct MHD_WebSocketStream *ws, 1081 size_t buf_len); 1082 1083 /** 1084 * Reallocates memory with the associated 'realloc' function 1085 * of the websocket stream 1086 * 1087 * @param ws The websocket stream. 1088 * @param buf The previously allocated memory or NULL 1089 * @param new_buf_len The new length of the memory in bytes 1090 * 1091 * @return The allocated memory on success or NULL on failure. 1092 * If NULL is returned the previously allocated buffer 1093 * remains valid. 1094 * @ingroup websocket 1095 */ 1096 _MHD_EXTERN void * 1097 MHD_websocket_realloc (struct MHD_WebSocketStream *ws, 1098 void *buf, 1099 size_t new_buf_len); 1100 1101 /** 1102 * Frees memory with the associated 'free' function 1103 * of the websocket stream 1104 * 1105 * @param ws The websocket stream. 1106 * @param buf The previously allocated memory or NULL 1107 * 1108 * @return A value of `enum MHD_WEBSOCKET_STATUS`. 1109 * This is #MHD_WEBSOCKET_STATUS_OK (= 0) on success 1110 * or a value less than 0 on errors. 1111 * @ingroup websocket 1112 */ 1113 _MHD_EXTERN int 1114 MHD_websocket_free (struct MHD_WebSocketStream *ws, 1115 void *buf); 1116 1117 #if 0 /* keep Emacsens' auto-indent happy */ 1118 { 1119 #endif 1120 #ifdef __cplusplus 1121 } 1122 #endif 1123 1124 #endif 1125