stream_funcs.h (15423B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2022-2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/stream_funcs.h 41 * @brief The declaration of the stream internal functions 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #ifndef MHD_STREAM_FUNCS_H 46 #define MHD_STREAM_FUNCS_H 1 47 48 #include "mhd_sys_options.h" 49 #include "sys_base_types.h" 50 #include "sys_bool_type.h" 51 52 53 struct MHD_Connection; /* forward declaration */ 54 55 56 /** 57 * Initialise request- and reply-specific stream data. 58 * 59 * Any resources referenced by the old values must be released before calling 60 * this function. 61 * @param c the connection whose request and reply data are initialised 62 */ 63 MHD_INTERNAL void 64 mhd_stream_init_req_reply (struct MHD_Connection *restrict c) 65 MHD_FN_PAR_NONNULL_ALL_; 66 67 68 /** 69 * The stage of input data processing. 70 * Used for out-of-memory (in the pool) handling. 71 */ 72 enum MHD_FIXED_ENUM_ MHD_ProcRecvDataStage 73 { 74 MHD_PROC_RECV_INIT, /**< No data HTTP request data have been processed yet */ 75 MHD_PROC_RECV_METHOD, /**< Processing/receiving the request HTTP method */ 76 MHD_PROC_RECV_URI, /**< Processing/receiving the request URI */ 77 MHD_PROC_RECV_HTTPVER, /**< Processing/receiving the request HTTP version string */ 78 MHD_PROC_RECV_HEADERS, /**< Processing/receiving the request HTTP headers */ 79 MHD_PROC_RECV_COOKIE, /**< Processing the received request cookie header */ 80 MHD_PROC_RECV_BODY_NORMAL, /**< Processing/receiving the request non-chunked body */ 81 MHD_PROC_RECV_BODY_CHUNKED,/**< Processing/receiving the request chunked body */ 82 MHD_PROC_RECV_FOOTERS /**< Processing/receiving the request footers */ 83 }; 84 85 /** 86 * Allocate memory from connection's memory pool. 87 * If memory pool doesn't have enough free memory but read or write buffer 88 * have some unused memory, the size of the buffer will be reduced as needed. 89 * @param connection the connection to use 90 * @param size the size of allocated memory area 91 * @return pointer to allocated memory region in the pool or 92 * NULL if no memory is available 93 */ 94 MHD_INTERNAL void * 95 mhd_stream_alloc_memory (struct MHD_Connection *restrict connection, 96 size_t size) 97 MHD_FN_PAR_NONNULL_ALL_; 98 99 /** 100 * Shrink stream read buffer to the zero size of free space in the buffer 101 * @param c the connection whose read buffer is being manipulated 102 */ 103 MHD_INTERNAL void 104 mhd_stream_shrink_read_buffer (struct MHD_Connection *restrict c) 105 MHD_FN_PAR_NONNULL_ALL_; 106 107 /** 108 * Allocate the maximum available amount of memory from MemoryPool 109 * for write buffer. 110 * @param c the connection whose write buffer is being manipulated 111 * @return the size of the free space in the write buffer 112 */ 113 MHD_INTERNAL size_t 114 mhd_stream_maximize_write_buffer (struct MHD_Connection *restrict c) 115 MHD_FN_PAR_NONNULL_ALL_; 116 117 /** 118 * Fully deallocate write buffer, if it was allocated previously. 119 * The write buffer must have no unsent data. 120 * @param c the connection whose write buffer is being manipulated 121 */ 122 MHD_INTERNAL void 123 mhd_stream_release_write_buffer (struct MHD_Connection *restrict c) 124 MHD_FN_PAR_NONNULL_ALL_; 125 126 /** 127 * Select the HTTP error status code for "out of receive buffer space" error. 128 * @param c the connection to process 129 * @param stage the current stage of request receiving 130 * @param add_element_size the size of the @a add_element; 131 * zero if @a add_element is NULL 132 * @param add_element the optional pointer to the element failed to be processed 133 * or added, the meaning of the element depends on 134 * the @a stage. Could be not zero-terminated and can 135 * contain binary zeros. Can be NULL. 136 * @return the HTTP error code to use in the error reply 137 */ 138 MHD_INTERNAL unsigned int 139 mhd_stream_get_no_space_err_status_code (struct MHD_Connection *restrict c, 140 enum MHD_ProcRecvDataStage stage, 141 size_t add_element_size, 142 const char *restrict add_element) 143 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_IN_SIZE_ (4, 3); 144 145 /** 146 * Switch connection from recv mode to send mode. 147 * 148 * Current request header or body will not be read anymore, 149 * response must be assigned to connection. 150 * @param c the connection to prepare for sending. 151 */ 152 MHD_INTERNAL void 153 mhd_stream_switch_from_recv_to_send (struct MHD_Connection *c) 154 MHD_FN_PAR_NONNULL_ALL_; 155 156 /** 157 * Finish request serving. 158 * The stream will be re-used or closed. 159 * 160 * @param c the connection to use. 161 */ 162 MHD_INTERNAL void 163 mhd_stream_finish_req_serving (struct MHD_Connection *restrict c, 164 bool reuse) 165 MHD_FN_PAR_NONNULL_ALL_; 166 167 /** 168 * The reason to close the connection 169 */ 170 enum mhd_ConnCloseReason 171 { 172 /* Hard problem while receiving */ 173 /** 174 * Client sent data that cannot be interpreted as HTTP data 175 */ 176 mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN 177 , 178 /** 179 * No space in the connection pool memory for receiving or processing 180 * the request 181 */ 182 mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST 183 , 184 /** 185 * The client shut down send before complete request sent 186 */ 187 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY 188 , 189 /** 190 * The client does not send HTTP/2 preface 191 */ 192 mhd_CONN_CLOSE_H2_PREFACE_MISSING 193 , 194 195 /* Hard problem while sending */ 196 197 /** 198 * No space in the connection pool memory for the reply 199 */ 200 mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY 201 , 202 /** 203 * No memory to create error response 204 */ 205 mhd_CONN_CLOSE_NO_MEM_FOR_ERR_RESPONSE 206 , 207 /** 208 * Application behaves incorrectly 209 */ 210 mhd_CONN_CLOSE_APP_ERROR 211 , 212 /** 213 * Application requested abort of the stream 214 */ 215 mhd_CONN_CLOSE_APP_ABORTED 216 , 217 /** 218 * File-backed response too large (unsupported by OS) file offset 219 */ 220 mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE 221 , 222 /** 223 * Error reading file-backed response 224 */ 225 mhd_CONN_CLOSE_FILE_READ_ERROR 226 , 227 /** 228 * File-backed response has file smaller than specified by application 229 */ 230 mhd_CONN_CLOSE_FILE_TOO_SHORT 231 , 232 #ifdef MHD_SUPPORT_AUTH_DIGEST 233 /** 234 * Error generating nonce for Digest Auth 235 */ 236 mhd_CONN_CLOSE_NONCE_ERROR 237 , 238 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 239 240 /* Hard problem while receiving or sending */ 241 /** 242 * MHD internal error. 243 * Should never appear. 244 */ 245 mhd_CONN_CLOSE_INT_ERROR 246 , 247 /** 248 * Failed to register the connection for the external event monitoring 249 */ 250 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED 251 , 252 /** 253 * No system resources available to handle connection 254 */ 255 mhd_CONN_CLOSE_NO_SYS_RESOURCES 256 , 257 /** 258 * The TCP or TLS connection is broken or aborted due to error on socket 259 * or TLS 260 */ 261 mhd_CONN_CLOSE_SOCKET_ERR 262 , 263 /** 264 * The daemon is being shut down, all connection must be closed 265 */ 266 mhd_CONN_CLOSE_DAEMON_SHUTDOWN 267 , 268 269 /* Could be hard or soft error depending on connection state */ 270 /** 271 * Timeout detected when receiving request 272 */ 273 mhd_CONN_CLOSE_TIMEDOUT 274 , 275 276 /* Soft problem */ 277 /** 278 * The connection must be closed after error response as the client 279 * violates HTTP specification 280 */ 281 mhd_CONN_CLOSE_ERR_REPLY_SENT 282 , 283 284 #ifdef MHD_SUPPORT_UPGRADE 285 286 /* Transition to another protocol */ 287 /** 288 * The connection stopped HTTP communication and will be used for another 289 * protocol. 290 * The socket is not being closed. 291 */ 292 mhd_CONN_CLOSE_UPGRADE 293 , 294 #endif /* MHD_SUPPORT_UPGRADE */ 295 296 /* Graceful closing */ 297 /** 298 * Close connection after graceful completion of HTTP communication 299 */ 300 mhd_CONN_CLOSE_HTTP_COMPLETED 301 302 #ifdef MHD_SUPPORT_HTTP2 303 , 304 /** 305 * Graceful closing after finishing HTTP/2 communication. 306 * The HTTP/2 itself could be closed by error. 307 */ 308 mhd_CONN_CLOSE_H2_CLOSE_SOFT 309 , 310 /** 311 * Hard closing after finishing HTTP/2 communication. 312 */ 313 mhd_CONN_CLOSE_H2_CLOSE_HARD 314 #endif /* MHD_SUPPORT_HTTP2 */ 315 #ifdef mhd_HAVE_TLS_ACME 316 , 317 /** 318 * The connection is an ACME ALPN challenge connection and 319 * the challenge has been completed. 320 */ 321 mhd_CONN_CLOSE_ACME_ALPN_CHALLENGE_COMPLETED 322 #endif /* mhd_HAVE_TLS_ACME */ 323 }; 324 325 326 /** 327 * Start non-HTTP/2 closing of the connection. 328 * 329 * Application is notified about connection closing (if callback is set), 330 * the socket is shut downed for sending and the connection is marked for 331 * closing. The real resource deallocation and socket closing are performed 332 * later. 333 * 334 * As no resources are deallocated by this function, it is safe to call it 335 * "deep" in the code. Upon return all connection resources still could be used, 336 * pointers can be dereferenced etc. The real cleanup is performed when 337 * connection state is processed by #mhd_conn_process_data(). 338 * 339 * @param c the connection for pre-closing 340 * @param reason the reason for closing 341 * @param log_msg the message for the log 342 */ 343 MHD_INTERNAL void 344 mhd_conn_start_closing (struct MHD_Connection *restrict c, 345 enum mhd_ConnCloseReason reason, 346 const char *log_msg) 347 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3); 348 349 /** 350 * Abort the stream and log message 351 */ 352 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 353 # define mhd_STREAM_ABORT(c, r, m) (mhd_conn_start_closing ((c),(r),(m))) 354 #else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 355 # define mhd_STREAM_ABORT(c, r, m) (mhd_conn_start_closing ((c),(r),NULL)) 356 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 357 358 /** 359 * Perform initial clean-up and mark for closing. 360 * Set the reason to "aborted by application" 361 * @param c the connection for pre-closing 362 */ 363 #define mhd_conn_start_closing_app_abort(c) \ 364 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_APP_ABORTED, NULL) 365 366 367 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 368 /** 369 * Perform initial clean-up and mark for closing. 370 * Set the reason to "socket error" 371 * @param c the connection for pre-closing 372 */ 373 # define mhd_conn_start_closing_ext_event_failed(c) \ 374 mhd_conn_start_closing ((c), \ 375 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, \ 376 "The application failed to register FD for " \ 377 "the external events monitoring.") 378 #else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 379 /** 380 * Perform initial clean-up and mark for closing. 381 * Set the reason to "socket error" 382 * @param c the connection for pre-closing 383 */ 384 # define mhd_conn_start_closing_ext_event_failed(c) \ 385 mhd_conn_start_closing ((c), \ 386 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, NULL) 387 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 388 389 /** 390 * Perform initial clean-up and mark for closing. 391 * Set the reason to "socket error" 392 * @param c the connection for pre-closing 393 */ 394 #define mhd_conn_start_closing_skt_err(c) \ 395 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_SOCKET_ERR, NULL) 396 397 /** 398 * Perform initial clean-up and mark for closing. 399 * Set the reason to "request finished" 400 * @param c the connection for pre-closing 401 */ 402 #define mhd_conn_start_closing_req_finished(c) \ 403 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_HTTP_COMPLETED, NULL) 404 405 /** 406 * Perform initial clean-up and mark for closing. 407 * Set the reason to "timed out". 408 * @param c the connection for pre-closing 409 */ 410 #define mhd_conn_start_closing_timedout(c) \ 411 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_TIMEDOUT, NULL) 412 413 /** 414 * Perform initial clean-up and mark for closing. 415 * Set the reason to "daemon shutdown". 416 * @param c the connection for pre-closing 417 */ 418 #define mhd_conn_start_closing_d_shutdown(c) \ 419 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_DAEMON_SHUTDOWN, NULL) 420 421 /** 422 * Perform initial clean-up and mark for closing. 423 * Set the reason to "no system resources". 424 * @param c the connection for pre-closing 425 */ 426 #define mhd_conn_start_closing_no_sys_res(c) \ 427 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_NO_SYS_RESOURCES, NULL) 428 429 #ifdef mhd_HAVE_TLS_ACME 430 /** 431 * Perform initial clean-up and mark for closing. 432 * Set the reason to "ACME ALPN challenge completed". 433 * @param c the connection for pre-closing 434 */ 435 # define mhd_conn_start_closing_acme_alpn_challenge_completed(c) \ 436 mhd_conn_start_closing ((c), \ 437 mhd_CONN_CLOSE_ACME_ALPN_CHALLENGE_COMPLETED, \ 438 NULL) 439 #endif /* mhd_HAVE_TLS_ACME */ 440 441 #ifdef MHD_SUPPORT_UPGRADE 442 /** 443 * Perform initial clean-up and prepare for HTTP Upgrade. 444 * Set the reason to "upgrading". 445 * @param c the connection for preparing 446 */ 447 # define mhd_conn_pre_upgrade(c) \ 448 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_UPGRADE, NULL) 449 #endif /* MHD_SUPPORT_UPGRADE */ 450 451 #ifdef MHD_SUPPORT_HTTP2 452 # define mhd_conn_start_closing_h2_soft(c) \ 453 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_SOFT, NULL) 454 # define mhd_conn_start_closing_h2_hard(c) \ 455 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_HARD, NULL) 456 #endif /* MHD_SUPPORT_HTTP2 */ 457 458 459 /** 460 * Perform first part of the initial connection cleanup. 461 * This function is used for both standard connection cleanup and for transition 462 * to HTTP-Upgraded connection. 463 * This cleanup should be performed in the same thread that processes 464 * the connection recv/send/data. 465 * @param c the connection to perform the first part of for pre-cleaning 466 */ 467 MHD_INTERNAL void 468 mhd_conn_pre_clean_part1 (struct MHD_Connection *restrict c) 469 MHD_FN_PAR_NONNULL_ (1); 470 471 /** 472 * Perform initial connection cleanup after start of the connection closing 473 * procedure. 474 * This cleanup should be performed in the same thread that processes 475 * the connection recv/send/data. 476 * @param c the connection for pre-cleaning 477 */ 478 MHD_INTERNAL void 479 mhd_conn_pre_clean (struct MHD_Connection *restrict c) 480 MHD_FN_PAR_NONNULL_ (1); 481 482 #endif /* ! MHD_STREAM_FUNCS_H */