h2_req_get_items.c (7307B)
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_req_get_items.c 41 * @brief Implementation of HTTP/2 request items public getters 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 46 #include "mhd_sys_options.h" 47 48 #include "sys_bool_type.h" 49 #include "sys_base_types.h" 50 51 #include "mhd_assert.h" 52 53 #include "mhd_cntnr_ptr.h" 54 55 #include "mhd_connection.h" 56 #include "h2_conn_data.h" 57 #include "h2_stream_data.h" 58 59 #include "h2_req_item_struct.h" 60 #include "h2_req_items_funcs.h" 61 62 #include "mhd_str.h" 63 64 #include "h2_req_get_items.h" 65 66 67 mhd_static_inline unsigned int 68 req_items_kind_mask (enum MHD_ValueKind kind) 69 { 70 unsigned int m; 71 m = 0u; 72 if (0u != (MHD_VK_HEADER & (unsigned int) kind)) 73 m |= (unsigned int) mhd_H2_RIK_HEADER; 74 if (0u != (MHD_VK_COOKIE & (unsigned int) kind)) 75 m |= (unsigned int) mhd_H2_RIK_COOKIE; 76 if (0u != (MHD_VK_URI_QUERY_PARAM & (unsigned int) kind)) 77 { 78 m |= (unsigned int) mhd_H2_RIK_URI_PARAM; 79 m |= (unsigned int) mhd_H2_RIK_URI_PARAM_NV; 80 } 81 if (0u != (MHD_VK_TRAILER & (unsigned int) kind)) 82 m |= (unsigned int) mhd_H2_RIK_TRAILER; 83 84 return m; 85 } 86 87 88 MHD_INTERNAL 89 MHD_FN_PAR_NONNULL_ALL_ 90 MHD_FN_PAR_IN_SIZE_ (4,3) 91 MHD_FN_PAR_CSTR_ (4) MHD_FN_PAR_OUT_ (5) bool 92 mhd_h2_request_get_value_n (struct MHD_Request *restrict r, 93 enum MHD_ValueKind kind, 94 size_t key_len, 95 const char *restrict key, 96 struct MHD_StringNullable *restrict value_out) 97 { 98 struct mhd_H2Stream *const s = 99 mhd_CNTNR_PTR ((struct mhd_H2RequestData *) (void*) r, 100 struct mhd_H2Stream, req); 101 struct MHD_Connection *const c = s->c; 102 size_t pos; 103 unsigned int type_mask; 104 const char *buff; 105 106 mhd_assert (r->is_http2); 107 mhd_assert (s->is_h2); 108 109 if ((mhd_H2_REQ_STAGE_HEADERS_DECODING != s->req.stage) 110 && (mhd_H2_REQ_STAGE_HEADERS_PROCESSING != s->req.stage) 111 && (mhd_H2_REQ_STAGE_TRAILERS_DECODING != s->req.stage) 112 && (mhd_H2_REQ_STAGE_TRAILERS_PROCESSING != s->req.stage)) 113 return false; 114 115 mhd_assert (mhd_h2_items_debug_get_streamid (c->h2.mem.req_ib) 116 == s->stream_id); 117 118 type_mask = req_items_kind_mask (kind); 119 buff = mhd_h2_items_get_strings_buffc (c->h2.mem.req_ib); 120 121 pos = 0u; 122 while (true) 123 { 124 const struct mhd_H2ReqItem *itm; 125 126 itm = mhd_h2_items_get_item_nc (c->h2.mem.req_ib, 127 pos++); 128 129 if (NULL == itm) 130 break; 131 132 if (key_len != itm->name_len) 133 continue; 134 135 if (0u == (type_mask & (unsigned int) itm->kind)) 136 continue; 137 138 if (! mhd_str_equal_lowercase_bin_n (key, 139 buff + itm->offset, 140 key_len)) 141 continue; 142 143 if (mhd_H2_RIK_URI_PARAM_NV != itm->kind) 144 { 145 value_out->cstr = buff + itm->offset + itm->name_len + 1u; 146 value_out->len = (size_t) itm->val_len; 147 } 148 else 149 { 150 value_out->cstr = NULL; 151 value_out->len = 0u; 152 } 153 154 return true; 155 } 156 157 return false; 158 } 159 160 161 mhd_static_inline enum MHD_ValueKind 162 req_item_kind_h2_to_h1 (enum mhd_H2RequestItemKind h2kind) 163 { 164 switch (h2kind) 165 { 166 case mhd_H2_RIK_HEADER: 167 case mhd_H2_RIK_PSEUDOHEADER: 168 return MHD_VK_HEADER; 169 case mhd_H2_RIK_COOKIE: 170 return MHD_VK_COOKIE; 171 case mhd_H2_RIK_URI_PARAM: 172 case mhd_H2_RIK_URI_PARAM_NV: 173 return MHD_VK_URI_QUERY_PARAM; 174 case mhd_H2_RIK_TRAILER: 175 return MHD_VK_TRAILER; 176 case mhd_H2_RIK_PLACEHOLDER: 177 case mhd_H2_RIK_ELIMINATED: 178 default: 179 break; 180 } 181 return MHD_VK_HEADER; 182 } 183 184 185 MHD_INTERNAL 186 MHD_FN_PAR_NONNULL_ (1) size_t 187 mhd_h2_request_get_values_cb (struct MHD_Request *r, 188 enum MHD_ValueKind kind, 189 MHD_NameValueIterator iterator, 190 void *iterator_cls) 191 { 192 struct mhd_H2Stream *const s = 193 mhd_CNTNR_PTR ((struct mhd_H2RequestData *) (void*) r, 194 struct mhd_H2Stream, req); 195 struct MHD_Connection *const c = s->c; 196 size_t pos; 197 unsigned int type_mask; 198 const char *buff; 199 size_t count; 200 201 202 mhd_assert (r->is_http2); 203 mhd_assert (s->is_h2); 204 205 if ((mhd_H2_REQ_STAGE_HEADERS_DECODING != s->req.stage) 206 && (mhd_H2_REQ_STAGE_HEADERS_PROCESSING != s->req.stage) 207 && (mhd_H2_REQ_STAGE_TRAILERS_DECODING != s->req.stage) 208 && (mhd_H2_REQ_STAGE_TRAILERS_PROCESSING != s->req.stage)) 209 return false; 210 211 mhd_assert (mhd_h2_items_debug_get_streamid (c->h2.mem.req_ib) 212 == s->stream_id); 213 214 type_mask = req_items_kind_mask (kind); 215 buff = mhd_h2_items_get_strings_buffc (c->h2.mem.req_ib); 216 217 pos = 0u; 218 count = 0u; 219 while (true) 220 { 221 const struct mhd_H2ReqItem *itm; 222 223 itm = mhd_h2_items_get_item_nc (c->h2.mem.req_ib, 224 pos++); 225 226 if (NULL == itm) 227 break; 228 229 if (((unsigned int) itm->kind) != (type_mask & (unsigned int) itm->kind)) 230 continue; 231 232 ++count; 233 if (NULL != iterator) 234 { 235 struct MHD_NameAndValue nv; 236 237 nv.name.cstr = buff + itm->offset; 238 nv.name.len = (size_t) itm->val_len; 239 if (mhd_H2_RIK_URI_PARAM_NV != itm->kind) 240 { 241 nv.value.cstr = buff + itm->offset + itm->name_len + 1u; 242 nv.value.len = (size_t) itm->val_len; 243 } 244 else 245 { 246 nv.value.cstr = NULL; 247 nv.value.len = 0u; 248 } 249 250 if (MHD_NO == 251 iterator (iterator_cls, 252 req_item_kind_h2_to_h1 (itm->kind), 253 &nv)) 254 return count; 255 } 256 } 257 258 return count; 259 }