mhd_response.h (8863B)
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) 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/mhd_response.h 41 * @brief The definition of the MHD_Response type and related structures 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #ifndef MHD_RESPONSE_H 46 #define MHD_RESPONSE_H 1 47 48 #include "mhd_sys_options.h" 49 50 #include "sys_bool_type.h" 51 #include "sys_base_types.h" 52 53 #include "mhd_public_api.h" 54 55 #include "mhd_dlinked_list.h" 56 #include "mhd_str_types.h" 57 #ifdef MHD_SUPPORT_AUTH_DIGEST 58 # include "mhd_auth_digest_hdr.h" 59 #endif 60 61 #include "mhd_iovec.h" 62 63 #ifdef MHD_SUPPORT_THREADS 64 # include "mhd_locks.h" 65 #endif 66 67 #include "mhd_atomic_counter.h" 68 69 #ifdef MHD_SUPPORT_HTTP2 70 # include "h2/h2_resp_data.h" 71 #endif 72 73 74 struct ResponseOptions; /* forward declaration */ 75 76 struct mhd_ResponseHeader; /* forward declaration */ 77 78 mhd_DLINKEDL_LINKS_DEF (mhd_ResponseHeader); 79 80 /** 81 * Response header / field 82 */ 83 struct mhd_ResponseHeader 84 { 85 /** 86 * The name of the header / field 87 */ 88 struct MHD_String name; 89 90 /** 91 * The value of the header / field 92 */ 93 struct MHD_String value; 94 95 #ifdef MHD_SUPPORT_HTTP2 96 /** 97 * HTTP/2-specific header / field data 98 */ 99 struct mhd_H2ResponseHeader h2; 100 #endif /* MHD_SUPPORT_HTTP2 */ 101 102 /** 103 * The links to other headers 104 */ 105 mhd_DLNKDL_LINKS (mhd_ResponseHeader,headers); 106 }; 107 108 /** 109 * The type of content 110 */ 111 enum mhd_ResponseContentDataType 112 { 113 mhd_RESPONSE_CONTENT_DATA_INVALID = 0 114 , 115 mhd_RESPONSE_CONTENT_DATA_BUFFER 116 , 117 mhd_RESPONSE_CONTENT_DATA_IOVEC 118 , 119 mhd_RESPONSE_CONTENT_DATA_FILE 120 , 121 mhd_RESPONSE_CONTENT_DATA_CALLBACK 122 }; 123 124 /** 125 * I/O vector response data 126 */ 127 struct mhd_ResponseIoVec 128 { 129 /** 130 * The copy of array of iovec elements. 131 * Must be freed! 132 */ 133 mhd_iovec *iov; 134 135 /** 136 * The number of elements in the @a iov array 137 */ 138 size_t cnt; 139 }; 140 141 /** 142 * The file data for the the response 143 */ 144 struct mhd_ResponseFD 145 { 146 /** 147 * The file description of the response 148 */ 149 int fd; 150 151 /** 152 * The offset in the file of the response content 153 */ 154 uint_fast64_t offset; 155 156 /** 157 * Indicate that @a fd is a pipe 158 */ 159 bool is_pipe; 160 161 #ifdef mhd_USE_SENDFILE 162 /** 163 * Use 'sendfile()' function for the @a FD 164 * Initially 'true' (except for pipes) but can be flipped to 'false' if 165 * sendfile() cannot handle this file. 166 */ 167 volatile bool use_sf; 168 #endif 169 }; 170 171 /** 172 * Dynamic response data 173 */ 174 struct mhd_ResponseDynamic 175 { 176 /** 177 * The callback for the content data 178 */ 179 MHD_DynamicContentCreator cb; 180 /** 181 * The closure for the @a cb 182 */ 183 void *cls; 184 }; 185 186 /** 187 * The response content data 188 */ 189 union mhd_ResponseContent 190 { 191 /** 192 * The fixed unmodifiable data. 193 * 'unsigned char' pointer is used to simplify individual ranges addressing. 194 */ 195 const unsigned char *restrict buf; 196 197 /** 198 * The I/O vector data 199 */ 200 struct mhd_ResponseIoVec iovec; 201 202 /** 203 * The file data for the the response 204 */ 205 struct mhd_ResponseFD file; 206 207 /** 208 * Dynamic response data 209 */ 210 struct mhd_ResponseDynamic dyn; 211 }; 212 213 /** 214 * The data of the free/cleanup callback 215 */ 216 struct mhd_FreeCbData 217 { 218 /** 219 * The Free/Cleanup callback 220 */ 221 MHD_FreeCallback cb; 222 223 /** 224 * The closure for the @a cb 225 */ 226 void *cls; 227 }; 228 229 230 struct mhd_ResponseReuseData 231 { 232 /** 233 * Indicate that response could be used more than one time 234 */ 235 volatile bool reusable; 236 237 /** 238 * The number of active uses of the response. 239 * Used only when @a reusable is 'true'. 240 * When number reached zero, the response is destroyed. 241 */ 242 struct mhd_AtomicCounter counter; 243 244 #ifdef MHD_SUPPORT_THREADS 245 /** 246 * The mutex for @a settings access. 247 * Used only when @a reusable is 'true'. 248 */ 249 mhd_mutex settings_lock; 250 #endif /* MHD_SUPPORT_THREADS */ 251 }; 252 253 struct mhd_ResponseConfiguration 254 { 255 /** 256 * Response have undefined content 257 * Must be used only when response content (even zero-size) is not allowed. 258 */ 259 bool head_only; 260 261 /** 262 * If set to 'true' then the chunked encoding must be used (if allowed 263 * by HTTP version). 264 * If 'false' then chunked encoding must not be used. 265 */ 266 bool chunked; 267 268 /** 269 * If 'true', "Connection: close" header must be always used 270 */ 271 bool close_forced; 272 273 /** 274 * Use "HTTP/1.0" in the reply header 275 * @a chunked is 'false' if this flag set. 276 * @a close_forced is 'true' is this flag set. 277 */ 278 bool mode_1_0; 279 280 /** 281 * The (possible incorrect) content length is provided by application 282 */ 283 bool cnt_len_by_app; 284 285 /** 286 * Response has "Date:" header 287 */ 288 bool has_hdr_date; // TODO: set the member 289 290 /** 291 * Response has "Connection:" header 292 */ 293 bool has_hdr_conn; // TODO: set the member 294 295 /** 296 * Response is internal-only error response 297 */ 298 bool int_err_resp; 299 300 #ifdef MHD_SUPPORT_AUTH_BASIC 301 /** 302 * Response has Basic Auth "challenge" header 303 */ 304 bool has_bauth; 305 #endif /* MHD_SUPPORT_AUTH_BASIC */ 306 }; 307 308 /** 309 * Special data for internal error responses 310 */ 311 struct mhd_ResponseInternalErrData 312 { 313 /** 314 * The length of the @a spec_hdr 315 */ 316 size_t spec_hdr_len; 317 /** 318 * The special header string. 319 * The final CRLF is not included. 320 * Must be deallocated if not NULL. 321 */ 322 char *spec_hdr; 323 }; 324 325 #ifndef NDEBUG 326 struct mhd_ResponseDebug 327 { 328 bool is_internal; 329 }; 330 #endif 331 332 mhd_DLINKEDL_LIST_DEF (mhd_ResponseHeader); 333 334 // TODO: Group members in structs 335 336 struct MHD_Response 337 { 338 /** 339 * The response HTTP status code 340 */ 341 enum MHD_HTTP_StatusCode sc; 342 343 /** 344 * The size of the response. 345 * #MHD_SIZE_UNKNOWN if size is undefined 346 */ 347 uint_fast64_t cntn_size; 348 349 /** 350 * The type of the content data 351 */ 352 enum mhd_ResponseContentDataType cntn_dtype; 353 354 /** 355 * The data of the content of the response 356 */ 357 union mhd_ResponseContent cntn; 358 359 /** 360 * The data of the free/cleanup callback 361 */ 362 struct mhd_FreeCbData free; 363 364 /** 365 * Configuration data of the response 366 */ 367 struct mhd_ResponseConfiguration cfg; 368 369 /** 370 * If response is "frozen" then response data cannot be changed. 371 * The use counter for re-usable responses is the exception and can be 372 * changed when "frozen". 373 */ 374 volatile bool frozen; 375 376 /** 377 * The re-use parameters 378 */ 379 struct mhd_ResponseReuseData reuse; 380 381 /** 382 * The settings, before the response is @a frozen 383 */ 384 struct ResponseOptions *restrict settings; 385 386 /** 387 * The double linked list of the response headers 388 */ 389 mhd_DLNKDL_LIST (mhd_ResponseHeader,headers); 390 391 #ifdef MHD_SUPPORT_AUTH_DIGEST 392 /** 393 * The double linked list of the Digest Auth response headers 394 */ 395 mhd_DLNKDL_LIST (mhd_RespAuthDigestHeader,auth_d_hdrs); 396 #endif 397 398 /** 399 * Special data for internal error responses 400 */ 401 struct mhd_ResponseInternalErrData special_resp; 402 403 /** 404 * Should be always 'false' for the response lifetime 405 */ 406 bool was_destroyed; 407 408 #ifndef NDEBUG 409 struct mhd_ResponseDebug dbg; 410 #endif 411 }; 412 413 /* 414 * Check whether the response has Digest Auth headers 415 */ 416 #ifdef MHD_SUPPORT_AUTH_DIGEST 417 #define mhd_RESP_HAS_AUTH_DIGEST(resp) \ 418 (NULL != mhd_DLINKEDL_GET_FIRST (resp, auth_d_hdrs)) 419 #else 420 #define mhd_RESP_HAS_AUTH_DIGEST(resp) (((void) (resp)), ! ! 0) 421 #endif 422 423 #endif /* ! MHD_RESPONSE_H */