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 */