stream_funcs.h (14420B)
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 * The stage of input data processing. 58 * Used for out-of-memory (in the pool) handling. 59 */ 60 enum MHD_FIXED_ENUM_ MHD_ProcRecvDataStage 61 { 62 MHD_PROC_RECV_INIT, /**< No data HTTP request data have been processed yet */ 63 MHD_PROC_RECV_METHOD, /**< Processing/receiving the request HTTP method */ 64 MHD_PROC_RECV_URI, /**< Processing/receiving the request URI */ 65 MHD_PROC_RECV_HTTPVER, /**< Processing/receiving the request HTTP version string */ 66 MHD_PROC_RECV_HEADERS, /**< Processing/receiving the request HTTP headers */ 67 MHD_PROC_RECV_COOKIE, /**< Processing the received request cookie header */ 68 MHD_PROC_RECV_BODY_NORMAL, /**< Processing/receiving the request non-chunked body */ 69 MHD_PROC_RECV_BODY_CHUNKED,/**< Processing/receiving the request chunked body */ 70 MHD_PROC_RECV_FOOTERS /**< Processing/receiving the request footers */ 71 }; 72 73 /** 74 * Allocate memory from connection's memory pool. 75 * If memory pool doesn't have enough free memory but read or write buffer 76 * have some unused memory, the size of the buffer will be reduced as needed. 77 * @param connection the connection to use 78 * @param size the size of allocated memory area 79 * @return pointer to allocated memory region in the pool or 80 * NULL if no memory is available 81 */ 82 MHD_INTERNAL void * 83 mhd_stream_alloc_memory (struct MHD_Connection *restrict connection, 84 size_t size) 85 MHD_FN_PAR_NONNULL_ALL_; 86 87 /** 88 * Shrink stream read buffer to the zero size of free space in the buffer 89 * @param c the connection whose read buffer is being manipulated 90 */ 91 MHD_INTERNAL void 92 mhd_stream_shrink_read_buffer (struct MHD_Connection *restrict c) 93 MHD_FN_PAR_NONNULL_ALL_; 94 95 /** 96 * Allocate the maximum available amount of memory from MemoryPool 97 * for write buffer. 98 * @param c the connection whose write buffer is being manipulated 99 * @return the size of the free space in the write buffer 100 */ 101 MHD_INTERNAL size_t 102 mhd_stream_maximize_write_buffer (struct MHD_Connection *restrict c) 103 MHD_FN_PAR_NONNULL_ALL_; 104 105 /** 106 * Fully deallocate write buffer, if it was allocated previously. 107 * The write buffer must have no unsent data. 108 * @param c the connection whose write buffer is being manipulated 109 */ 110 MHD_INTERNAL void 111 mhd_stream_release_write_buffer (struct MHD_Connection *restrict c) 112 MHD_FN_PAR_NONNULL_ALL_; 113 114 /** 115 * Select the HTTP error status code for "out of receive buffer space" error. 116 * @param c the connection to process 117 * @param stage the current stage of request receiving 118 * @param add_element_size the size of the @a add_element; 119 * zero if @a add_element is NULL 120 * @param add_element the optional pointer to the element failed to be processed 121 * or added, the meaning of the element depends on 122 * the @a stage. Could be not zero-terminated and can 123 * contain binary zeros. Can be NULL. 124 * @return the HTTP error code to use in the error reply 125 */ 126 MHD_INTERNAL unsigned int 127 mhd_stream_get_no_space_err_status_code (struct MHD_Connection *restrict c, 128 enum MHD_ProcRecvDataStage stage, 129 size_t add_element_size, 130 const char *restrict add_element) 131 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_IN_SIZE_ (4,3); 132 133 /** 134 * Switch connection from recv mode to send mode. 135 * 136 * Current request header or body will not be read anymore, 137 * response must be assigned to connection. 138 * @param c the connection to prepare for sending. 139 */ 140 MHD_INTERNAL void 141 mhd_stream_switch_from_recv_to_send (struct MHD_Connection *c) 142 MHD_FN_PAR_NONNULL_ALL_; 143 144 /** 145 * Finish request serving. 146 * The stream will be re-used or closed. 147 * 148 * @param c the connection to use. 149 */ 150 MHD_INTERNAL void 151 mhd_stream_finish_req_serving (struct MHD_Connection *restrict c, 152 bool reuse) 153 MHD_FN_PAR_NONNULL_ALL_; 154 155 /** 156 * The reason to close the connection 157 */ 158 enum mhd_ConnCloseReason 159 { 160 /* Hard problem while receiving */ 161 /** 162 * Client sent data that cannot be interpreted as HTTP data 163 */ 164 mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN 165 , 166 /** 167 * No space in the connection pool memory for receiving or processing 168 * the request 169 */ 170 mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST 171 , 172 /** 173 * The client shut down send before complete request sent 174 */ 175 mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY 176 , 177 /** 178 * The client shut down send before complete request sent 179 */ 180 mhd_CONN_CLOSE_H2_PREFACE_MISSING 181 , 182 183 /* Hard problem while sending */ 184 185 /** 186 * No space in the connection pool memory for the reply 187 */ 188 mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY 189 , 190 /** 191 * No memory to create error response 192 */ 193 mhd_CONN_CLOSE_NO_MEM_FOR_ERR_RESPONSE 194 , 195 /** 196 * Application behaves incorrectly 197 */ 198 mhd_CONN_CLOSE_APP_ERROR 199 , 200 /** 201 * Application requested abort of the stream 202 */ 203 mhd_CONN_CLOSE_APP_ABORTED 204 , 205 /** 206 * File-backed response too large (unsupported by OS) file offset 207 */ 208 mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE 209 , 210 /** 211 * Error reading file-backed response 212 */ 213 mhd_CONN_CLOSE_FILE_READ_ERROR 214 , 215 /** 216 * File-backed response has file smaller than specified by application 217 */ 218 mhd_CONN_CLOSE_FILE_TOO_SHORT 219 , 220 #ifdef MHD_SUPPORT_AUTH_DIGEST 221 /** 222 * Error generating nonce for Digest Auth 223 */ 224 mhd_CONN_CLOSE_NONCE_ERROR 225 , 226 #endif /* MHD_SUPPORT_AUTH_DIGEST */ 227 228 /* Hard problem while receiving or sending */ 229 /** 230 * MHD internal error. 231 * Should never appear. 232 */ 233 mhd_CONN_CLOSE_INT_ERROR 234 , 235 /** 236 * Failed to register the connection for the external event monitoring 237 */ 238 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED 239 , 240 /** 241 * No system resources available to handle connection 242 */ 243 mhd_CONN_CLOSE_NO_SYS_RESOURCES 244 , 245 /** 246 * The TCP or TLS connection is broken or aborted due to error on socket 247 * or TLS 248 */ 249 mhd_CONN_CLOSE_SOCKET_ERR 250 , 251 /** 252 * The daemon is being shut down, all connection must be closed 253 */ 254 mhd_CONN_CLOSE_DAEMON_SHUTDOWN 255 , 256 257 /* Could be hard or soft error depending on connection state */ 258 /** 259 * Timeout detected when receiving request 260 */ 261 mhd_CONN_CLOSE_TIMEDOUT 262 , 263 264 /* Soft problem */ 265 /** 266 * The connection must be closed after error response as the client 267 * violates HTTP specification 268 */ 269 mhd_CONN_CLOSE_ERR_REPLY_SENT 270 , 271 272 #ifdef MHD_SUPPORT_UPGRADE 273 274 /* Transition to another protocol */ 275 /** 276 * The connection stopped HTTP communication and will be used for another 277 * protocol. 278 * The socket is not being closed. 279 */ 280 mhd_CONN_CLOSE_UPGRADE 281 , 282 #endif /* MHD_SUPPORT_UPGRADE */ 283 284 /* Graceful closing */ 285 /** 286 * Close connection after graceful completion of HTTP communication 287 */ 288 mhd_CONN_CLOSE_HTTP_COMPLETED 289 290 #ifdef MHD_SUPPORT_HTTP2 291 , 292 /** 293 * Graceful closing after finishing HTTP/2 communication. 294 * The HTTP/2 itself could be closed by error. 295 */ 296 mhd_CONN_CLOSE_H2_CLOSE_SOFT 297 , 298 /** 299 * Hard closing after finishing HTTP/2 communication. 300 */ 301 mhd_CONN_CLOSE_H2_CLOSE_HARD 302 #endif /* MHD_SUPPORT_HTTP2 */ 303 }; 304 305 306 /** 307 * Start non-HTTP/2 closing of the connection. 308 * 309 * Application is notified about connection closing (if callback is set), 310 * the socket is shut downed for sending and the connection is marked for 311 * closing. The real resource deallocation and socket closing are performed 312 * later. 313 * 314 * As no resources are deallocated by this function, it is safe to call it 315 * "deep" in the code. Upon return all connection resources still could be used, 316 * pointers can be dereferenced etc. The real cleanup is performed when 317 * connection state is processed by #mhd_conn_process_data(). 318 * 319 * @param c the connection for pre-closing 320 * @param reason the reason for closing 321 * @param log_msg the message for the log 322 */ 323 MHD_INTERNAL void 324 mhd_conn_start_closing (struct MHD_Connection *restrict c, 325 enum mhd_ConnCloseReason reason, 326 const char *log_msg) 327 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3); 328 329 /** 330 * Abort the stream and log message 331 */ 332 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 333 # define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),(m))) 334 #else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 335 # define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),NULL)) 336 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 337 338 /** 339 * Perform initial clean-up and mark for closing. 340 * Set the reason to "aborted by application" 341 * @param c the connection for pre-closing 342 */ 343 #define mhd_conn_start_closing_app_abort(c) \ 344 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_APP_ABORTED, NULL) 345 346 347 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY 348 /** 349 * Perform initial clean-up and mark for closing. 350 * Set the reason to "socket error" 351 * @param c the connection for pre-closing 352 */ 353 #define mhd_conn_start_closing_ext_event_failed(c) \ 354 mhd_conn_start_closing ((c), \ 355 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, \ 356 "The application failed to register FD for " \ 357 "the external events monitoring.") 358 #else /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 359 /** 360 * Perform initial clean-up and mark for closing. 361 * Set the reason to "socket error" 362 * @param c the connection for pre-closing 363 */ 364 #define mhd_conn_start_closing_ext_event_failed(c) \ 365 mhd_conn_start_closing ((c), \ 366 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, NULL) 367 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */ 368 369 /** 370 * Perform initial clean-up and mark for closing. 371 * Set the reason to "socket error" 372 * @param c the connection for pre-closing 373 */ 374 #define mhd_conn_start_closing_skt_err(c) \ 375 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_SOCKET_ERR, NULL) 376 377 /** 378 * Perform initial clean-up and mark for closing. 379 * Set the reason to "request finished" 380 * @param c the connection for pre-closing 381 */ 382 #define mhd_conn_start_closing_req_finished(c) \ 383 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_HTTP_COMPLETED, NULL) 384 385 /** 386 * Perform initial clean-up and mark for closing. 387 * Set the reason to "timed out". 388 * @param c the connection for pre-closing 389 */ 390 #define mhd_conn_start_closing_timedout(c) \ 391 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_TIMEDOUT, NULL) 392 393 /** 394 * Perform initial clean-up and mark for closing. 395 * Set the reason to "daemon shutdown". 396 * @param c the connection for pre-closing 397 */ 398 #define mhd_conn_start_closing_d_shutdown(c) \ 399 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_DAEMON_SHUTDOWN, NULL) 400 401 /** 402 * Perform initial clean-up and mark for closing. 403 * Set the reason to "no system resources". 404 * @param c the connection for pre-closing 405 */ 406 #define mhd_conn_start_closing_no_sys_res(c) \ 407 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_NO_SYS_RESOURCES, NULL) 408 409 #ifdef MHD_SUPPORT_UPGRADE 410 /** 411 * Perform initial clean-up and prepare for HTTP Upgrade. 412 * Set the reason to "upgrading". 413 * @param c the connection for preparing 414 */ 415 # define mhd_conn_pre_upgrade(c) \ 416 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_UPGRADE, NULL) 417 #endif /* MHD_SUPPORT_UPGRADE */ 418 419 #ifdef MHD_SUPPORT_HTTP2 420 # define mhd_conn_start_closing_h2_soft(c) \ 421 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_SOFT, NULL) 422 # define mhd_conn_start_closing_h2_hard(c) \ 423 mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_HARD, NULL) 424 #endif /* MHD_SUPPORT_HTTP2 */ 425 426 427 /** 428 * Perform first part of the initial connection cleanup. 429 * This function is used for both standard connection cleanup and for transition 430 * to HTTP-Upgraded connection. 431 * This cleanup should be performed in the same thread that processes 432 * the connection recv/send/data. 433 * @param c the connection to perform the first part of for pre-cleaning 434 */ 435 MHD_INTERNAL void 436 mhd_conn_pre_clean_part1 (struct MHD_Connection *restrict c) 437 MHD_FN_PAR_NONNULL_ (1); 438 439 /** 440 * Perform initial connection cleanup after start of the connection closing 441 * procedure. 442 * This cleanup should be performed in the same thread that processes 443 * the connection recv/send/data. 444 * @param c the connection for pre-cleaning 445 */ 446 MHD_INTERNAL void 447 mhd_conn_pre_clean (struct MHD_Connection *restrict c) 448 MHD_FN_PAR_NONNULL_ (1); 449 450 #endif /* ! MHD_STREAM_FUNCS_H */