libmicrohttpd2

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

h2_frame_codec.h (8925B)


      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) 2025 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/h2/h2_frame_codec.h
     41  * @brief  Declarations of HTTP/2 frame decoding and encoding functions
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #ifndef MHD_H2_FRAME_CODEC_H
     46 #define MHD_H2_FRAME_CODEC_H 1
     47 
     48 #include "mhd_sys_options.h"
     49 
     50 #include "sys_base_types.h"
     51 
     52 #include "mhd_buffer.h"
     53 #include "h2_frame_types.h"
     54 
     55 #if defined(_MSC_FULL_VER)
     56 #pragma warning(push)
     57 /* Disable C4505 "unreferenced local function has been removed" */
     58 #pragma warning(disable:4505)
     59 #endif /* _MSC_FULL_VER */
     60 
     61 /**
     62  * The basic (mandatory) HTTP/2 frame header size
     63  */
     64 #define mhd_H2_FR_HDR_BASE_SIZE      (9u)
     65 
     66 /**
     67  * The minimum HTTP/2 frame size
     68  */
     69 #define mhd_H2_FR_SIZE_MIN   mhd_H2_FR_HDR_BASE_SIZE
     70 
     71 /**
     72  * Maximum extra frame header size for known frame types.
     73  */
     74 #define mhd_H2_FR_HDR_EXTRA_SIZE_MAX    (8u)
     75 
     76 /**
     77  * Result of frame decode
     78  */
     79 enum MHD_FIXED_ENUM_ mhd_H2FrameDecodeResult
     80 {
     81   /**
     82    * Frame is successfully decoded
     83    */
     84   mhd_H2_F_DEC_OK = 0
     85   ,
     86   /**
     87    * Frame header is completely decoded, but frame payload is incomplete
     88    * Frame information is valid.
     89    */
     90   mhd_H2_F_DEC_F_PAYLOAD_INCOMPLETE
     91   ,
     92   /**
     93    * Frame header information is not complete.
     94    * Not enough data to decode frame header.
     95    */
     96   mhd_H2_F_DEC_F_HEADER_INCOMPLETE
     97   ,
     98   /**
     99    * Stream error of type "Frame size error"
    100    */
    101   mhd_H2_F_DEC_STREAM_ERR_F_SIZE
    102   ,
    103   /**
    104    * Stream error of type "Protocol error"
    105    */
    106   mhd_H2_F_DEC_STREAM_ERR_PROT
    107   ,
    108   /**
    109    * Connection error of type "Frame size error"
    110    */
    111   mhd_H2_F_DEC_CONN_ERR_F_SIZE
    112   ,
    113   /**
    114    * Connection error of type "Protocol error"
    115    */
    116   mhd_H2_F_DEC_CONN_ERR_PROT
    117 };
    118 
    119 #define mhd_H2_FRAME_DEC_ERR_IS_HARD(res) \
    120         (mhd_H2_F_DEC_F_HEADER_INCOMPLETE < (res))
    121 
    122 /**
    123  * Decode an HTTP/2 frame.
    124  *
    125  * If result is #mhd_H2_F_DEC_OK or #mhd_H2_F_DEC_F_PAYLOAD_INCOMPLETE then
    126  * @a frame_info has full information about known frame types.
    127  * When result is not #mhd_H2_F_DEC_OK, #mhd_H2_F_DEC_F_PAYLOAD_INCOMPLETE or
    128  * #mhd_H2_F_DEC_F_HEADER_INCOMPLETE, the only valid data in the @a frame_info
    129  * is "length", "type" and "stream_id".
    130  * @param buff_size the size of the data available to decode
    131  * @param buff the data to decode
    132  * @param max_frame_size the maximum allowed frame size
    133  * @param[out] frame_info set to frame information
    134  * @param[out] frame_payload on successful decode set to the frame payload
    135  *                           size and location
    136  * @return #mhd_H2_F_DEC_OK on success,
    137  *         the error code otherwise
    138  */
    139 MHD_INTERNAL enum mhd_H2FrameDecodeResult
    140 mhd_h2_frame_decode (size_t buff_size,
    141                      uint8_t *restrict buff,
    142                      uint_least32_t max_frame_size,
    143                      union mhd_H2FrameUnion *restrict frame_info,
    144                      struct mhd_Buffer *restrict frame_payload)
    145 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_SIZE_(2,1)
    146 MHD_FN_PAR_OUT_(4) MHD_FN_PAR_OUT_ (5);
    147 
    148 
    149 /**
    150  * Find an amount of extra bytes required to encode the HTTP/2 frame.
    151  *
    152  * Each frame is encoded to the basic frame header size
    153  * #mhd_H2_FR_HDR_BASE_SIZE plus optional extra bytes (depending on frame
    154  * flags), plus the frame payload (only for relevant frame types), plus
    155  * optional padding at the end.
    156  *
    157  * This function calculates the total extra bytes for known frame types based
    158  * on the frame header type and flags. This extra size is counted as a part
    159  * of the frame "length".
    160  * @param frame_info the information about the frame; only type and flags are
    161  *                   checked
    162  * @return the number of extra bytes needed to write the frame header, which is
    163  *         a value in range 0 .. #mhd_H2_FR_HDR_EXTRA_SIZE_MAX;
    164  *         does not include the basic frame header
    165  *         size #mhd_H2_FR_HDR_BASE_SIZE
    166  */
    167 MHD_INTERNAL size_t
    168 mhd_h2_frame_get_extra_hdr_size (
    169   const union mhd_H2FrameUnion *restrict frame_info)
    170 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_ (1);
    171 
    172 
    173 /**
    174  * Get the size of the padding (if any) set in the @a frame_info.
    175  *
    176  * The padding is counted as a part of frame "length".
    177  * @param frame_info the information about frame, only type, flags and
    178  *                   padding size (if any) are checked
    179  * @return the padding size used at the end of the frame
    180  */
    181 MHD_INTERNAL size_t
    182 mhd_h2_frame_get_padding_size (
    183   const union mhd_H2FrameUnion *restrict frame_info)
    184 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_ (1);
    185 
    186 
    187 /**
    188  * Calculate full frame size
    189  * @param frame_info the information about frame
    190  * @return the total size of the frame, including frame header and payload
    191  */
    192 mhd_static_inline MHD_FN_PAR_NONNULL_ALL_
    193 MHD_FN_PAR_IN_ (1) size_t
    194 mhd_h2_frame_get_total_size (const union mhd_H2FrameUnion *restrict frame_info)
    195 {
    196   mhd_assert ((mhd_h2_frame_get_extra_hdr_size (frame_info)
    197                + mhd_h2_frame_get_padding_size (frame_info))
    198               <= frame_info->selector.length);
    199   return (size_t) (mhd_H2_FR_HDR_BASE_SIZE + frame_info->selector.length);
    200 }
    201 
    202 
    203 /**
    204  * Set 'length' member in the HTTP/2 frame.
    205  * This function takes into account the frame type, the size of the extra
    206  * frame header (if any), the padding (if allowed by frame type and set in
    207  * @a frame_info) and the payload size.
    208  *
    209  * @param[in,out] frame_info the information about frame: the type, all flags
    210  *                           and padding size (if any) must be set; the 'length'
    211  *                           is modified
    212  * @param real_payload_size the size of the real payload of the frame (the
    213  *                          part of the frame after extra header bytes and
    214  *                          before the padding (if any) bytes;
    215  *                          must be zero for frames without payload support;
    216  *                          must fit 24 bits length together with padding and
    217  *                          extra header
    218  * @return the total size of the updated frame: the basis header plus the value
    219  *         of the frame 'length' field
    220  */
    221 MHD_INTERNAL size_t
    222 mhd_h2_frame_set_payload_size (union mhd_H2FrameUnion *restrict frame_info,
    223                                size_t real_payload_size)
    224 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_INOUT_ (1);
    225 
    226 /**
    227  * Encode the HTTP/2 frame header into the output buffer.
    228  *
    229  * This function writes the HTTP/2 basic frame header and extra frame header
    230  * (if any, for know frame types only) using data from @a frame_info.
    231  * @param frame_info the frame information to encode
    232  * @param out_buff_size the size of @a out_buff in bytes
    233  * @param[out] out_buff the output buffer to receive the encoded header
    234  * @return the number of bytes written on success
    235  *         (always #mhd_H2_FR_HDR_BASE_SIZE or more),
    236  *         or 0 if @a out_buff_size is too small (the output buffer may be
    237  *         alerted in case of this error)
    238  */
    239 MHD_INTERNAL size_t
    240 mhd_h2_frame_hdr_encode (const union mhd_H2FrameUnion *restrict frame_info,
    241                          size_t out_buff_size,
    242                          uint8_t *restrict out_buff)
    243 MHD_FN_PAR_NONNULL_ALL_ MHD_FN_PAR_IN_ (1)
    244 MHD_FN_PAR_OUT_SIZE_ (3,2);
    245 
    246 #if defined(_MSC_FULL_VER)
    247 /* Restore warnings */
    248 #pragma warning(pop)
    249 #endif /* _MSC_FULL_VER */
    250 
    251 #endif /* ! MHD_H2_FRAME_CODEC_H */