libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

stream_funcs.h (15372B)


      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  * Update last activity mark to the current time.
    157  * @param c the connection to update
    158  */
    159 MHD_INTERNAL void
    160 mhd_stream_update_activity_mark (struct MHD_Connection *restrict c)
    161 MHD_FN_PAR_NONNULL_ALL_;
    162 
    163 
    164 /**
    165  * Update last activity mark on the resumed connection
    166  * @param c the connection to update
    167  */
    168 MHD_INTERNAL void
    169 mhd_stream_resumed_activity_mark (struct MHD_Connection *restrict c)
    170 MHD_FN_PAR_NONNULL_ALL_;
    171 
    172 
    173 /**
    174  * Remove connection from time-out lists
    175  * @param c the connection to process
    176  */
    177 MHD_INTERNAL void
    178 mhd_conn_remove_from_timeout_lists (struct MHD_Connection *restrict c)
    179 MHD_FN_PAR_NONNULL_ALL_;
    180 
    181 /**
    182  * Check whether connection's timeout is expired.
    183  * @param c the connection to update
    184  * @return 'true' if connection timeout expired and connection needs to be
    185  *         closed,
    186  *         'false' otherwise
    187  */
    188 MHD_INTERNAL bool
    189 mhd_stream_is_timeout_expired (struct MHD_Connection *restrict c)
    190 MHD_FN_PAR_NONNULL_ALL_;
    191 
    192 /**
    193  * The reason to close the connection
    194  */
    195 enum mhd_ConnCloseReason
    196 {
    197   /* Hard problem while receiving */
    198   /**
    199    * Client sent data that cannot be interpreted as HTTP data
    200    */
    201   mhd_CONN_CLOSE_CLIENT_HTTP_ERR_ABORT_CONN
    202   ,
    203   /**
    204    * No space in the connection pool memory for receiving or processing
    205    * the request
    206    */
    207   mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REQUEST
    208   ,
    209   /**
    210    * The client shut down send before complete request sent
    211    */
    212   mhd_CONN_CLOSE_CLIENT_SHUTDOWN_EARLY
    213   ,
    214   /**
    215    * The client shut down send before complete request sent
    216    */
    217   mhd_CONN_CLOSE_H2_PREFACE_MISSING
    218   ,
    219 
    220   /* Hard problem while sending */
    221 
    222   /**
    223    * No space in the connection pool memory for the reply
    224    */
    225   mhd_CONN_CLOSE_NO_POOL_MEM_FOR_REPLY
    226   ,
    227   /**
    228    * No memory to create error response
    229    */
    230   mhd_CONN_CLOSE_NO_MEM_FOR_ERR_RESPONSE
    231   ,
    232   /**
    233    * Application behaves incorrectly
    234    */
    235   mhd_CONN_CLOSE_APP_ERROR
    236   ,
    237   /**
    238    * Application requested abort of the stream
    239    */
    240   mhd_CONN_CLOSE_APP_ABORTED
    241   ,
    242   /**
    243    * File-backed response too large (unsupported by OS) file offset
    244    */
    245   mhd_CONN_CLOSE_FILE_OFFSET_TOO_LARGE
    246   ,
    247   /**
    248    * Error reading file-backed response
    249    */
    250   mhd_CONN_CLOSE_FILE_READ_ERROR
    251   ,
    252   /**
    253    * File-backed response has file smaller than specified by application
    254    */
    255   mhd_CONN_CLOSE_FILE_TOO_SHORT
    256   ,
    257 #ifdef MHD_SUPPORT_AUTH_DIGEST
    258   /**
    259    * Error generating nonce for Digest Auth
    260    */
    261   mhd_CONN_CLOSE_NONCE_ERROR
    262   ,
    263 #endif /* MHD_SUPPORT_AUTH_DIGEST */
    264 
    265   /* Hard problem while receiving or sending */
    266   /**
    267    * MHD internal error.
    268    * Should never appear.
    269    */
    270   mhd_CONN_CLOSE_INT_ERROR
    271   ,
    272   /**
    273    * Failed to register the connection for the external event monitoring
    274    */
    275   mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED
    276   ,
    277   /**
    278    * No system resources available to handle connection
    279    */
    280   mhd_CONN_CLOSE_NO_SYS_RESOURCES
    281   ,
    282   /**
    283    * The TCP or TLS connection is broken or aborted due to error on socket
    284    * or TLS
    285    */
    286   mhd_CONN_CLOSE_SOCKET_ERR
    287   ,
    288   /**
    289    * The daemon is being shut down, all connection must be closed
    290    */
    291   mhd_CONN_CLOSE_DAEMON_SHUTDOWN
    292   ,
    293 
    294   /* Could be hard or soft error depending on connection state */
    295   /**
    296    * Timeout detected when receiving request
    297    */
    298   mhd_CONN_CLOSE_TIMEDOUT
    299   ,
    300 
    301   /* Soft problem */
    302   /**
    303    * The connection must be closed after error response as the client
    304    * violates HTTP specification
    305    */
    306   mhd_CONN_CLOSE_ERR_REPLY_SENT
    307   ,
    308 
    309 #ifdef MHD_SUPPORT_UPGRADE
    310 
    311   /* Transition to another protocol */
    312   /**
    313    * The connection stopped HTTP communication and will be used for another
    314    * protocol.
    315    * The socket is not being closed.
    316    */
    317   mhd_CONN_CLOSE_UPGRADE
    318   ,
    319 #endif /* MHD_SUPPORT_UPGRADE */
    320 
    321   /* Graceful closing */
    322   /**
    323    * Close connection after graceful completion of HTTP communication
    324    */
    325   mhd_CONN_CLOSE_HTTP_COMPLETED
    326 
    327 #ifdef MHD_SUPPORT_HTTP2
    328   ,
    329   /**
    330    * Graceful closing after finishing HTTP/2 communication.
    331    * The HTTP/2 itself could be closed by error.
    332    */
    333   mhd_CONN_CLOSE_H2_CLOSE_SOFT
    334   ,
    335   /**
    336    * Hard closing after finishing HTTP/2 communication.
    337    */
    338   mhd_CONN_CLOSE_H2_CLOSE_HARD
    339 #endif /* MHD_SUPPORT_HTTP2 */
    340 };
    341 
    342 
    343 /**
    344  * Start non-HTTP/2 closing of the connection.
    345  *
    346  * Application is notified about connection closing (if callback is set),
    347  * the socket is shut downed for sending and the connection is marked for
    348  * closing. The real resource deallocation and socket closing are performed
    349  * later.
    350  *
    351  * As no resources are deallocated by this function, it is safe to call it
    352  * "deep" in the code. Upon return all connection resources still could be used,
    353  * pointers can be dereferenced etc. The real cleanup is performed when
    354  * connection state is processed by #mhd_conn_process_data().
    355  *
    356  * @param c the connection for pre-closing
    357  * @param reason the reason for closing
    358  * @param log_msg the message for the log
    359  */
    360 MHD_INTERNAL void
    361 mhd_conn_start_closing (struct MHD_Connection *restrict c,
    362                         enum mhd_ConnCloseReason reason,
    363                         const char *log_msg)
    364 MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_CSTR_ (3);
    365 
    366 /**
    367  * Abort the stream and log message
    368  */
    369 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY
    370 #  define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),(m)))
    371 #else  /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */
    372 #  define mhd_STREAM_ABORT(c,r,m) (mhd_conn_start_closing ((c),(r),NULL))
    373 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */
    374 
    375 /**
    376  * Perform initial clean-up and mark for closing.
    377  * Set the reason to "aborted by application"
    378  * @param c the connection for pre-closing
    379  */
    380 #define mhd_conn_start_closing_app_abort(c) \
    381         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_APP_ABORTED, NULL)
    382 
    383 
    384 #ifdef MHD_SUPPORT_LOG_FUNCTIONALITY
    385 /**
    386  * Perform initial clean-up and mark for closing.
    387  * Set the reason to "socket error"
    388  * @param c the connection for pre-closing
    389  */
    390 #define mhd_conn_start_closing_ext_event_failed(c) \
    391         mhd_conn_start_closing ((c), \
    392                                 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, \
    393                                 "The application failed to register FD for " \
    394                                 "the external events monitoring.")
    395 #else  /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */
    396 /**
    397  * Perform initial clean-up and mark for closing.
    398  * Set the reason to "socket error"
    399  * @param c the connection for pre-closing
    400  */
    401 #define mhd_conn_start_closing_ext_event_failed(c) \
    402         mhd_conn_start_closing ((c), \
    403                                 mhd_CONN_CLOSE_EXTR_EVENT_REG_FAILED, NULL)
    404 #endif /* ! MHD_SUPPORT_LOG_FUNCTIONALITY */
    405 
    406 /**
    407  * Perform initial clean-up and mark for closing.
    408  * Set the reason to "socket error"
    409  * @param c the connection for pre-closing
    410  */
    411 #define mhd_conn_start_closing_skt_err(c) \
    412         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_SOCKET_ERR, NULL)
    413 
    414 /**
    415  * Perform initial clean-up and mark for closing.
    416  * Set the reason to "request finished"
    417  * @param c the connection for pre-closing
    418  */
    419 #define mhd_conn_start_closing_req_finished(c) \
    420         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_HTTP_COMPLETED, NULL)
    421 
    422 /**
    423  * Perform initial clean-up and mark for closing.
    424  * Set the reason to "timed out".
    425  * @param c the connection for pre-closing
    426  */
    427 #define mhd_conn_start_closing_timedout(c) \
    428         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_TIMEDOUT, NULL)
    429 
    430 /**
    431  * Perform initial clean-up and mark for closing.
    432  * Set the reason to "daemon shutdown".
    433  * @param c the connection for pre-closing
    434  */
    435 #define mhd_conn_start_closing_d_shutdown(c) \
    436         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_DAEMON_SHUTDOWN, NULL)
    437 
    438 /**
    439  * Perform initial clean-up and mark for closing.
    440  * Set the reason to "no system resources".
    441  * @param c the connection for pre-closing
    442  */
    443 #define mhd_conn_start_closing_no_sys_res(c) \
    444         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_NO_SYS_RESOURCES, NULL)
    445 
    446 #ifdef MHD_SUPPORT_UPGRADE
    447 /**
    448  * Perform initial clean-up and prepare for HTTP Upgrade.
    449  * Set the reason to "upgrading".
    450  * @param c the connection for preparing
    451  */
    452 #  define mhd_conn_pre_upgrade(c) \
    453         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_UPGRADE, NULL)
    454 #endif /* MHD_SUPPORT_UPGRADE */
    455 
    456 #ifdef MHD_SUPPORT_HTTP2
    457 #  define mhd_conn_start_closing_h2_soft(c) \
    458         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_SOFT, NULL)
    459 #  define mhd_conn_start_closing_h2_hard(c) \
    460         mhd_conn_start_closing ((c), mhd_CONN_CLOSE_H2_CLOSE_HARD, NULL)
    461 #endif /* MHD_SUPPORT_HTTP2 */
    462 
    463 
    464 /**
    465  * Perform first part of the initial connection cleanup.
    466  * This function is used for both standard connection cleanup and for transition
    467  * to HTTP-Upgraded connection.
    468  * This cleanup should be performed in the same thread that processes
    469  * the connection recv/send/data.
    470  * @param c the connection to perform the first part of for pre-cleaning
    471  */
    472 MHD_INTERNAL void
    473 mhd_conn_pre_clean_part1 (struct MHD_Connection *restrict c)
    474 MHD_FN_PAR_NONNULL_ (1);
    475 
    476 /**
    477  * Perform initial connection cleanup after start of the connection closing
    478  * procedure.
    479  * This cleanup should be performed in the same thread that processes
    480  * the connection recv/send/data.
    481  * @param c the connection for pre-cleaning
    482  */
    483 MHD_INTERNAL void
    484 mhd_conn_pre_clean (struct MHD_Connection *restrict c)
    485 MHD_FN_PAR_NONNULL_ (1);
    486 
    487 #endif /* ! MHD_STREAM_FUNCS_H */