libmicrohttpd2

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

stream_funcs.h (15461B)


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