1/* 2 * lsqpack.h - QPACK library 3 */ 4 5/* 6MIT License 7 8Copyright (c) 2018 - 2022 LiteSpeed Technologies Inc 9 10Permission is hereby granted, free of charge, to any person obtaining a copy 11of this software and associated documentation files (the "Software"), to deal 12in the Software without restriction, including without limitation the rights 13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14copies of the Software, and to permit persons to whom the Software is 15furnished to do so, subject to the following conditions: 16 17The above copyright notice and this permission notice shall be included in all 18copies or substantial portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26SOFTWARE. 27*/ 28 29#ifndef LSQPACK_H 30#define LSQPACK_H 1 31 32#ifdef __cplusplus 33extern "C" { 34#endif 35 36#include <limits.h> 37#include <stdint.h> 38#include <stdio.h> 39 40#if defined(_MSC_VER) 41#include <BaseTsd.h> 42typedef SSIZE_T ssize_t; 43#endif 44 45#define LSQPACK_MAJOR_VERSION 2 46#define LSQPACK_MINOR_VERSION 3 47#define LSQPACK_PATCH_VERSION 0 48 49/** Let's start with four billion for now */ 50typedef unsigned lsqpack_abs_id_t; 51 52#define LSQPACK_MAX_ABS_ID (~((lsqpack_abs_id_t) 0)) 53 54#define LSQPACK_DEF_DYN_TABLE_SIZE 0 55#define LSQPACK_DEF_MAX_RISKED_STREAMS 0 56 57struct lsqpack_enc; 58struct lsqpack_dec; 59struct lsxpack_header; 60 61enum lsqpack_enc_opts 62{ 63 /** 64 * Client and server follow different heuristics. The encoder is either 65 * in one or the other mode. 66 * 67 * At the moment this option is a no-op. This is a potential future 68 * work item where some heuristics may be added to the library. 69 */ 70 LSQPACK_ENC_OPT_SERVER = 1 << 0, 71 72 /** 73 * The encoder was pre-initialized using @ref lsqpack_enc_preinit() and 74 * so some initialization steps can be skipped. 75 */ 76 LSQPACK_ENC_OPT_STAGE_2 = 1 << 1, 77 78 /* The options below are advanced. The author only uses them for debugging 79 * or testing. 80 */ 81 82 /** 83 * Disable emitting dup instructions. 84 * 85 * Disabling dup instructions usually makes compression performance 86 * significanly worse. Do not use unless you know what you are doing. 87 */ 88 LSQPACK_ENC_OPT_NO_DUP = 1 << 2, 89 90 /** 91 * Index aggressively: ignore history 92 * 93 * Ignoring history usually makes compression performance significanly 94 * worse. Do not use unless you know what you are doing. 95 */ 96 LSQPACK_ENC_OPT_IX_AGGR = 1 << 3, 97 98 /** 99 * Turn off memory guard: keep on allocating state tracking oustanding 100 * headers even if they never get acknowledged. 101 * 102 * This is useful for some forms of testing. 103 */ 104 LSQPACK_ENC_OPT_NO_MEM_GUARD = 1 << 4, 105}; 106 107 108/** 109 * Initialize the encoder so that it can be used without using the 110 * dynamic table. Once peer's settings are known, call 111 * @ref lsqpack_enc_init(). 112 * 113 * `logger_ctx' can be set to NULL if no special logging is set up. 114 */ 115void 116lsqpack_enc_preinit (struct lsqpack_enc *, void *logger_ctx); 117 118/** 119 * Number of bytes required to encode the longest possible Set Dynamic Table 120 * Capacity instruction. This is a theoretical limit based on the integral 121 * type (unsigned int) used by this library to store the capacity value. If 122 * the encoder is initialized with a smaller maximum table capacity, it is 123 * safe to use fewer bytes. 124 * 125 * SDTC instructtion can be produced by @ref lsqpack_enc_init() and 126 * @ref lsqpack_enc_set_max_capacity(). 127 */ 128#if UINT_MAX == 65535 129#define LSQPACK_LONGEST_SDTC 4 130#elif UINT_MAX == 4294967295 131#define LSQPACK_LONGEST_SDTC 6 132#elif UINT_MAX == 18446744073709551615ULL 133#define LSQPACK_LONGEST_SDTC 11 134#else 135#error unexpected sizeof(unsigned) 136#endif 137 138int 139lsqpack_enc_init (struct lsqpack_enc *, 140 /** `logger_ctx' can be set to NULL if no special logging is set up. */ 141 void *logger_ctx, 142 /** 143 * As specified by the decoder. This value is used to calculate 144 * MaxEntries. 145 */ 146 unsigned max_table_size, 147 /** 148 * Actual dynamic table size to use. 149 */ 150 unsigned dyn_table_size, 151 unsigned max_risked_streams, enum lsqpack_enc_opts, 152 /** 153 * If `dyn_table_size' is not zero, Set Dynamic Table Capacity (SDTC) 154 * instruction is generated and placed into `sdtc_buf'. `sdtc_buf_sz' 155 * parameter is used both for input and output. 156 * 157 * If `dyn_table_size' is zero, `sdtc_buf' and `sdtc_buf_sz' are optional 158 * and can be set to NULL. 159 */ 160 unsigned char *sdtc_buf, size_t *sdtc_buf_sz); 161 162/** 163 * Set table size to `capacity'. If necessary, Set Dynamic Table Capacity 164 * (SDTC) instruction is generated and placed into `tsu_buf'. If `capacity' 165 * is larger than the maximum table size specified during initialization, an 166 * error is returned. 167 */ 168int 169lsqpack_enc_set_max_capacity (struct lsqpack_enc *enc, unsigned capacity, 170 unsigned char *sdtc_buf, size_t *sdtc_buf_sz); 171 172/** Start a new header block. Return 0 on success or -1 on error. */ 173int 174lsqpack_enc_start_header (struct lsqpack_enc *, uint64_t stream_id, 175 unsigned seqno); 176 177/** Status returned by @ref lsqpack_enc_encode() */ 178enum lsqpack_enc_status 179{ 180 /** Header field encoded successfully */ 181 LQES_OK, 182 /** There was not enough room in the encoder stream buffer */ 183 LQES_NOBUF_ENC, 184 /** There was not enough room in the header block buffer */ 185 LQES_NOBUF_HEAD, 186}; 187 188enum lsqpack_enc_flags 189{ 190 /** 191 * Do not index this header field. No output to the encoder stream 192 * will be produced. 193 */ 194 LQEF_NO_INDEX = 1 << 0, 195 /** 196 * Never index this field. This will set the 'N' bit on Literal Header 197 * Field With Name Reference, Literal Header Field With Post-Base Name 198 * Reference, and Literal Header Field Without Name Reference instructions 199 * in the header block. Implies LQEF_NO_INDEX. 200 */ 201 LQEF_NEVER_INDEX = 1 << 1, 202 /** 203 * Do not update history. 204 */ 205 LQEF_NO_HIST_UPD = 1 << 2, 206 /** 207 * Do not use the dynamic table. This is stricter than LQEF_NO_INDEX: 208 * this means that the dynamic table will be neither referenced nor 209 * modified. 210 */ 211 LQEF_NO_DYN = 1 << 3, 212}; 213 214/** 215 * Encode header field into current header block. 216 * 217 * See @ref lsqpack_enc_status for explanation of the return values. 218 * 219 * enc_sz and header_sz parameters are used for both input and output. If 220 * the return value is LQES_OK, they contain number of bytes written to 221 * enc_buf and header_buf, respectively. enc_buf contains the bytes that 222 * must be written to the encoder stream; header_buf contains bytes that 223 * must be written to the header block. 224 * 225 * Note that even though this function may allocate memory, it falls back to 226 * not using the dynamic table should memory allocation fail. Thus, failures 227 * to encode due to not enough memory do not exist. 228 */ 229enum lsqpack_enc_status 230lsqpack_enc_encode (struct lsqpack_enc *, 231 unsigned char *enc_buf, size_t *enc_sz, 232 unsigned char *header_buf, size_t *header_sz, 233 const struct lsxpack_header *, 234 enum lsqpack_enc_flags flags); 235 236/** 237 * Cancel current header block. Cancellation is only allowed if the dynamic 238 * table is not used. Returns 0 on success, -1 on failure. 239 */ 240int 241lsqpack_enc_cancel_header (struct lsqpack_enc *); 242 243 244/** 245 * Properties of the current header block 246 */ 247enum lsqpack_enc_header_flags 248{ 249 /** Set if there are at-risk references in this header block */ 250 LSQECH_REF_AT_RISK = 1 << 0, 251 /** Set if the header block references newly inserted entries */ 252 LSQECH_REF_NEW_ENTRIES = 1 << 1, 253 /** Set if min-reffed value is cached */ 254 LSQECH_MINREF_CACHED = 1 << 2, 255}; 256 257 258/** 259 * End current header block. The Header Block Prefix is written to `buf'. 260 * 261 * `buf' must be at least two bytes. 11 bytes are necessary to encode 262 * UINT64_MAX using 7- or 8-bit prefix. Therefore, 22 bytes is the 263 * theoretical maximum for this library. 264 * 265 * Use @ref lsqpack_enc_header_block_prefix_size() if you require better 266 * precision. 267 * 268 * Returns: 269 * - A positive value indicates success and is the number of bytes 270 * written to `buf'. 271 * - Zero means that there is not enough room in `buf' to write out the 272 * full prefix. 273 * - A negative value means an error. This is returned if there is no 274 * started header to end. 275 * 276 * If header was ended successfully and @ref flags is not NULL, it is 277 * assigned properties of the header block. 278 */ 279ssize_t 280lsqpack_enc_end_header (struct lsqpack_enc *, unsigned char *buf, size_t, 281 enum lsqpack_enc_header_flags *flags /* Optional */); 282 283/** 284 * Process next chunk of bytes from the decoder stream. Returns 0 on success, 285 * -1 on failure. The failure should be treated as fatal. 286 */ 287int 288lsqpack_enc_decoder_in (struct lsqpack_enc *, const unsigned char *, size_t); 289 290/** 291 * Return estimated compression ratio until this point. Compression ratio 292 * is defined as size of the output divided by the size of the input, where 293 * output includes both header blocks and instructions sent on the encoder 294 * stream. 295 */ 296float 297lsqpack_enc_ratio (const struct lsqpack_enc *); 298 299/** 300 * Return maximum size needed to encode Header Block Prefix 301 */ 302size_t 303lsqpack_enc_header_block_prefix_size (const struct lsqpack_enc *); 304 305void 306lsqpack_enc_cleanup (struct lsqpack_enc *); 307 308/** Decoder header set interface */ 309struct lsqpack_dec_hset_if 310{ 311 void (*dhi_unblocked)(void *hblock_ctx); 312 struct lsxpack_header * 313 (*dhi_prepare_decode)(void *hblock_ctx, 314 struct lsxpack_header *, size_t space); 315 int (*dhi_process_header)(void *hblock_ctx, struct lsxpack_header *); 316}; 317 318enum lsqpack_dec_opts 319{ 320 /** 321 * In this mode, returned lsxpack_header will contain ": " between 322 * name and value strings and have "\r\n" after the value. 323 */ 324 LSQPACK_DEC_OPT_HTTP1X = 1 << 0, 325 /** Include name hash into lsxpack_header */ 326 LSQPACK_DEC_OPT_HASH_NAME = 1 << 1, 327 /** Include nameval hash into lsxpack_header */ 328 LSQPACK_DEC_OPT_HASH_NAMEVAL = 1 << 2, 329}; 330 331void 332lsqpack_dec_init (struct lsqpack_dec *, void *logger_ctx, 333 unsigned dyn_table_size, unsigned max_risked_streams, 334 const struct lsqpack_dec_hset_if *, enum lsqpack_dec_opts); 335 336/** 337 * Values returned by @ref lsqpack_dec_header_in() and 338 * @ref lsqpack_dec_header_read() 339 */ 340enum lsqpack_read_header_status 341{ 342 /** 343 * The header list has been placed in `hlist' and `buf' has been advanced. 344 * This header should be released using 345 * @ref lsqpack_dec_destroy_header_list() after the caller is done with it. 346 * 347 * Note that the header list in `hlist' has an unlimited lifetime. Even 348 * destroying it after @ref lsqpack_dec_cleanup() is called is OK and 349 * will not leak memory. 350 */ 351 LQRHS_DONE, 352 /** 353 * The decoder cannot decode the header block until more dynamic table 354 * entries become available. `buf' is advanced. When the header block 355 * becomes unblocked, the decoder will call hblock_unblocked() callback 356 * specified in the constructor. See @ref lsqpack_dec_init(). 357 * 358 * Once a header block is unblocked, it cannot get blocked again. In 359 * other words, this status can only be returned once per header block. 360 */ 361 LQRHS_BLOCKED, 362 /** 363 * The decoder needs more bytes from the header block to proceed. When 364 * they become available, call @ref lsqpack_dec_header_read(). `buf' is 365 * advanced. 366 */ 367 LQRHS_NEED, 368 /** 369 * An error has occurred. This can be any error: decoding error, memory 370 * allocation failure, or some internal error. 371 */ 372 LQRHS_ERROR, 373}; 374 375/** 376 * Number of bytes needed to encode the longest Header Acknowledgement 377 * instruction. 378 */ 379#define LSQPACK_LONGEST_HEADER_ACK 10 380 381 382/** 383 * Call this function when the header blocks is first read. The decoder 384 * will try to decode the header block. The decoder can process header 385 * blocks in a streaming fashion, which means that there is no need to 386 * buffer the header block. As soon as header block bytes become available, 387 * they can be fed to this function or @ref lsqpack_dec_header_read(). 388 * 389 * See @ref lsqpack_read_header_status for explanation of the return codes. 390 * 391 * If the decoder returns LQRHS_NEED or LQRHS_BLOCKED, it keeps a reference to 392 * the user-provided header block context `hblock_ctx'. It uses this value for 393 * two purposes: 394 * 1. to use as argument to hblock_unblocked(); and 395 * 2. to locate header block state when @ref lsqpack_dec_header_read() is 396 * called. 397 * 398 * If the decoder returns LQRHS_DONE or LQRHS_ERROR, it means that it no 399 * longer has a reference to the header block. 400 */ 401enum lsqpack_read_header_status 402lsqpack_dec_header_in (struct lsqpack_dec *, void *hblock_ctx, 403 uint64_t stream_id, size_t header_block_size, 404 const unsigned char **buf, size_t bufsz, 405 unsigned char *dec_buf, size_t *dec_buf_sz); 406 407/** 408 * Call this function when more header block bytes are become available 409 * after this function or @ref lsqpack_dec_header_in() returned LQRHS_NEED 410 * or hblock_unblocked() callback has been called. This function behaves 411 * similarly to @ref lsqpack_dec_header_in(): see its comments for more 412 * information. 413 */ 414enum lsqpack_read_header_status 415lsqpack_dec_header_read (struct lsqpack_dec *dec, void *hblock_ctx, 416 const unsigned char **buf, size_t bufsz, 417 unsigned char *dec_buf, size_t *dec_buf_sz); 418 419/** 420 * Feed encoder stream data to the decoder. Zero is returned on success, 421 * negative value on error. 422 */ 423int 424lsqpack_dec_enc_in (struct lsqpack_dec *, const unsigned char *, size_t); 425 426/** 427 * Returns true if Insert Count Increment (ICI) instruction is pending. 428 */ 429int 430lsqpack_dec_ici_pending (const struct lsqpack_dec *dec); 431 432/** 433 * Number of bytes required to encode the longest Insert Count Increment (ICI) 434 * instruction. 435 */ 436#define LSQPACK_LONGEST_ICI 6 437 438ssize_t 439lsqpack_dec_write_ici (struct lsqpack_dec *, unsigned char *, size_t); 440 441/** Number of bytes required to encode the longest cancel instruction */ 442#define LSQPACK_LONGEST_CANCEL 6 443 444/** 445 * Cancel stream associated with the header block context `hblock_ctx' and 446 * write cancellation instruction to `buf'. `buf' must be at least 447 * @ref LSQPACK_LONGEST_CANCEL bytes long. 448 * 449 * Number of bytes written to `buf' is returned. If stream `stream_id' 450 * could not be found, zero is returned. If `buf' is too short, -1 is 451 * returned. 452 */ 453ssize_t 454lsqpack_dec_cancel_stream (struct lsqpack_dec *, void *hblock_ctx, 455 unsigned char *buf, size_t buf_sz); 456 457/** 458 * Generate Cancel Stream instruction for stream `stream_id'. Call when 459 * abandoning stream (see [draft-ietf-quic-qpack-14] Section 2.2.2.2). 460 * 461 * Return values: 462 * -1 error (`buf' is too short) 463 * 0 Emitting Cancel Stream instruction is unnecessary 464 * >0 Size of Cancel Stream instruction written to `buf'. 465 */ 466ssize_t 467lsqpack_dec_cancel_stream_id (struct lsqpack_dec *dec, uint64_t stream_id, 468 unsigned char *buf, size_t buf_sz); 469 470/** 471 * Delete reference to the header block context `hblock_ctx'. Use this 472 * instead of @ref lsqpack_dec_cancel_stream() when producing a Cancel Stream 473 * instruction is not necessary. 474 */ 475int 476lsqpack_dec_unref_stream (struct lsqpack_dec *, void *hblock_ctx); 477 478/** 479 * Return estimated compression ratio until this point. Compression ratio 480 * is defined as size of the input divided by the size of the output, where 481 * input includes both header blocks and instructions received on the encoder 482 * stream. 483 */ 484float 485lsqpack_dec_ratio (const struct lsqpack_dec *); 486 487/** 488 * Clean up the decoder. If any there are any blocked header blocks, 489 * references to them will be discarded. 490 */ 491void 492lsqpack_dec_cleanup (struct lsqpack_dec *); 493 494/** 495 * Print human-readable decoder table. 496 */ 497void 498lsqpack_dec_print_table (const struct lsqpack_dec *, FILE *out); 499 500 501struct lsqpack_dec_err 502{ 503 enum { 504 LSQPACK_DEC_ERR_LOC_HEADER_BLOCK, 505 LSQPACK_DEC_ERR_LOC_ENC_STREAM, 506 } type; 507 int line; /* In the source file */ 508 uint64_t off; /* Offset in header block or on encoder stream */ 509 uint64_t stream_id; /* Only applicable to header block */ 510}; 511 512 513const struct lsqpack_dec_err * 514lsqpack_dec_get_err_info (const struct lsqpack_dec *); 515 516/** 517 * Enum for name/value entries in the static table. Use it to speed up 518 * encoding by setting xhdr->qpack_index and LSXPACK_QPACK_IDX flag. If 519 * it's a full match, set LSXPACK_VAL_MATCHED flag as well. 520 */ 521enum lsqpack_tnv 522{ 523 LSQPACK_TNV_AUTHORITY = 0, /* ":authority" "" */ 524 LSQPACK_TNV_PATH = 1, /* ":path" "/" */ 525 LSQPACK_TNV_AGE_0 = 2, /* "age" "0" */ 526 LSQPACK_TNV_CONTENT_DISPOSITION = 3, /* "content-disposition" "" */ 527 LSQPACK_TNV_CONTENT_LENGTH_0 = 4, /* "content-length" "0" */ 528 LSQPACK_TNV_COOKIE = 5, /* "cookie" "" */ 529 LSQPACK_TNV_DATE = 6, /* "date" "" */ 530 LSQPACK_TNV_ETAG = 7, /* "etag" "" */ 531 LSQPACK_TNV_IF_MODIFIED_SINCE = 8, /* "if-modified-since" "" */ 532 LSQPACK_TNV_IF_NONE_MATCH = 9, /* "if-none-match" "" */ 533 LSQPACK_TNV_LAST_MODIFIED = 10, /* "last-modified" "" */ 534 LSQPACK_TNV_LINK = 11, /* "link" "" */ 535 LSQPACK_TNV_LOCATION = 12, /* "location" "" */ 536 LSQPACK_TNV_REFERER = 13, /* "referer" "" */ 537 LSQPACK_TNV_SET_COOKIE = 14, /* "set-cookie" "" */ 538 LSQPACK_TNV_METHOD_CONNECT = 15, /* ":method" "CONNECT" */ 539 LSQPACK_TNV_METHOD_DELETE = 16, /* ":method" "DELETE" */ 540 LSQPACK_TNV_METHOD_GET = 17, /* ":method" "GET" */ 541 LSQPACK_TNV_METHOD_HEAD = 18, /* ":method" "HEAD" */ 542 LSQPACK_TNV_METHOD_OPTIONS = 19, /* ":method" "OPTIONS" */ 543 LSQPACK_TNV_METHOD_POST = 20, /* ":method" "POST" */ 544 LSQPACK_TNV_METHOD_PUT = 21, /* ":method" "PUT" */ 545 LSQPACK_TNV_SCHEME_HTTP = 22, /* ":scheme" "http" */ 546 LSQPACK_TNV_SCHEME_HTTPS = 23, /* ":scheme" "https" */ 547 LSQPACK_TNV_STATUS_103 = 24, /* ":status" "103" */ 548 LSQPACK_TNV_STATUS_200 = 25, /* ":status" "200" */ 549 LSQPACK_TNV_STATUS_304 = 26, /* ":status" "304" */ 550 LSQPACK_TNV_STATUS_404 = 27, /* ":status" "404" */ 551 LSQPACK_TNV_STATUS_503 = 28, /* ":status" "503" */ 552 LSQPACK_TNV_ACCEPT = 29, /* "accept" star slash star */ 553 LSQPACK_TNV_ACCEPT_APPLICATION_DNS_MESSAGE = 30, /* "accept" "application/dns-message" */ 554 LSQPACK_TNV_ACCEPT_ENCODING_GZIP_DEFLATE_BR = 31, /* "accept-encoding" "gzip, deflate, br" */ 555 LSQPACK_TNV_ACCEPT_RANGES_BYTES = 32, /* "accept-ranges" "bytes" */ 556 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_HEADERS_CACHE_CONTROL = 33, /* "access-control-allow-headers" "cache-control" */ 557 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_HEADERS_CONTENT_TYPE = 34, /* "access-control-allow-headers" "content-type" */ 558 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_ORIGIN = 35, /* "access-control-allow-origin" "*" */ 559 LSQPACK_TNV_CACHE_CONTROL_MAX_AGE_0 = 36, /* "cache-control" "max-age=0" */ 560 LSQPACK_TNV_CACHE_CONTROL_MAX_AGE_2592000 = 37, /* "cache-control" "max-age=2592000" */ 561 LSQPACK_TNV_CACHE_CONTROL_MAX_AGE_604800 = 38, /* "cache-control" "max-age=604800" */ 562 LSQPACK_TNV_CACHE_CONTROL_NO_CACHE = 39, /* "cache-control" "no-cache" */ 563 LSQPACK_TNV_CACHE_CONTROL_NO_STORE = 40, /* "cache-control" "no-store" */ 564 LSQPACK_TNV_CACHE_CONTROL_PUBLIC_MAX_AGE_31536000 = 41, /* "cache-control" "public, max-age=31536000" */ 565 LSQPACK_TNV_CONTENT_ENCODING_BR = 42, /* "content-encoding" "br" */ 566 LSQPACK_TNV_CONTENT_ENCODING_GZIP = 43, /* "content-encoding" "gzip" */ 567 LSQPACK_TNV_CONTENT_TYPE_APPLICATION_DNS_MESSAGE = 44, /* "content-type" "application/dns-message" */ 568 LSQPACK_TNV_CONTENT_TYPE_APPLICATION_JAVASCRIPT = 45, /* "content-type" "application/javascript" */ 569 LSQPACK_TNV_CONTENT_TYPE_APPLICATION_JSON = 46, /* "content-type" "application/json" */ 570 LSQPACK_TNV_CONTENT_TYPE_APPLICATION_X_WWW_FORM_URLENCODED = 47, /* "content-type" "application/x-www-form-urlencoded" */ 571 LSQPACK_TNV_CONTENT_TYPE_IMAGE_GIF = 48, /* "content-type" "image/gif" */ 572 LSQPACK_TNV_CONTENT_TYPE_IMAGE_JPEG = 49, /* "content-type" "image/jpeg" */ 573 LSQPACK_TNV_CONTENT_TYPE_IMAGE_PNG = 50, /* "content-type" "image/png" */ 574 LSQPACK_TNV_CONTENT_TYPE_TEXT_CSS = 51, /* "content-type" "text/css" */ 575 LSQPACK_TNV_CONTENT_TYPE_TEXT_HTML_CHARSET_UTF_8 = 52, /* "content-type" "text/html; charset=utf-8" */ 576 LSQPACK_TNV_CONTENT_TYPE_TEXT_PLAIN = 53, /* "content-type" "text/plain" */ 577 LSQPACK_TNV_CONTENT_TYPE_TEXT_PLAIN_CHARSET_UTF_8 = 54, /* "content-type" "text/plain;charset=utf-8" */ 578 LSQPACK_TNV_RANGE_BYTES_0 = 55, /* "range" "bytes=0-" */ 579 LSQPACK_TNV_STRICT_TRANSPORT_SECURITY_MAX_AGE_31536000 = 56, /* "strict-transport-security" "max-age=31536000" */ 580 LSQPACK_TNV_STRICT_TRANSPORT_SECURITY_MAX_AGE_31536000_INCLUDESUBDOMAINS = 57, /* "strict-transport-security" "max-age=31536000; includesubdomains" */ 581 LSQPACK_TNV_STRICT_TRANSPORT_SECURITY_MAX_AGE_31536000_INCLUDESUBDOMAINS_PRELOAD = 58, /* "strict-transport-security" "max-age=31536000; includesubdomains; preload" */ 582 LSQPACK_TNV_VARY_ACCEPT_ENCODING = 59, /* "vary" "accept-encoding" */ 583 LSQPACK_TNV_VARY_ORIGIN = 60, /* "vary" "origin" */ 584 LSQPACK_TNV_X_CONTENT_TYPE_OPTIONS_NOSNIFF = 61, /* "x-content-type-options" "nosniff" */ 585 LSQPACK_TNV_X_XSS_PROTECTION_1_MODE_BLOCK = 62, /* "x-xss-protection" "1; mode=block" */ 586 LSQPACK_TNV_STATUS_100 = 63, /* ":status" "100" */ 587 LSQPACK_TNV_STATUS_204 = 64, /* ":status" "204" */ 588 LSQPACK_TNV_STATUS_206 = 65, /* ":status" "206" */ 589 LSQPACK_TNV_STATUS_302 = 66, /* ":status" "302" */ 590 LSQPACK_TNV_STATUS_400 = 67, /* ":status" "400" */ 591 LSQPACK_TNV_STATUS_403 = 68, /* ":status" "403" */ 592 LSQPACK_TNV_STATUS_421 = 69, /* ":status" "421" */ 593 LSQPACK_TNV_STATUS_425 = 70, /* ":status" "425" */ 594 LSQPACK_TNV_STATUS_500 = 71, /* ":status" "500" */ 595 LSQPACK_TNV_ACCEPT_LANGUAGE = 72, /* "accept-language" "" */ 596 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_CREDENTIALS_FALSE = 73, /* "access-control-allow-credentials" "FALSE" */ 597 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_CREDENTIALS_TRUE = 74, /* "access-control-allow-credentials" "TRUE" */ 598 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_HEADERS = 75, /* "access-control-allow-headers" "*" */ 599 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_METHODS_GET = 76, /* "access-control-allow-methods" "get" */ 600 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_METHODS_GET_POST_OPTIONS = 77, /* "access-control-allow-methods" "get, post, options" */ 601 LSQPACK_TNV_ACCESS_CONTROL_ALLOW_METHODS_OPTIONS = 78, /* "access-control-allow-methods" "options" */ 602 LSQPACK_TNV_ACCESS_CONTROL_EXPOSE_HEADERS_CONTENT_LENGTH = 79, /* "access-control-expose-headers" "content-length" */ 603 LSQPACK_TNV_ACCESS_CONTROL_REQUEST_HEADERS_CONTENT_TYPE = 80, /* "access-control-request-headers" "content-type" */ 604 LSQPACK_TNV_ACCESS_CONTROL_REQUEST_METHOD_GET = 81, /* "access-control-request-method" "get" */ 605 LSQPACK_TNV_ACCESS_CONTROL_REQUEST_METHOD_POST = 82, /* "access-control-request-method" "post" */ 606 LSQPACK_TNV_ALT_SVC_CLEAR = 83, /* "alt-svc" "clear" */ 607 LSQPACK_TNV_AUTHORIZATION = 84, /* "authorization" "" */ 608 LSQPACK_TNV_CONTENT_SECURITY_POLICY_SCRIPT_SRC_NONE_OBJECT_SRC_NONE_BASE_URI_NONE = 85, /* "content-security-policy" "script-src 'none'; object-src 'none'; base-uri 'none'" */ 609 LSQPACK_TNV_EARLY_DATA_1 = 86, /* "early-data" "1" */ 610 LSQPACK_TNV_EXPECT_CT = 87, /* "expect-ct" "" */ 611 LSQPACK_TNV_FORWARDED = 88, /* "forwarded" "" */ 612 LSQPACK_TNV_IF_RANGE = 89, /* "if-range" "" */ 613 LSQPACK_TNV_ORIGIN = 90, /* "origin" "" */ 614 LSQPACK_TNV_PURPOSE_PREFETCH = 91, /* "purpose" "prefetch" */ 615 LSQPACK_TNV_SERVER = 92, /* "server" "" */ 616 LSQPACK_TNV_TIMING_ALLOW_ORIGIN = 93, /* "timing-allow-origin" "*" */ 617 LSQPACK_TNV_UPGRADE_INSECURE_REQUESTS_1 = 94, /* "upgrade-insecure-requests" "1" */ 618 LSQPACK_TNV_USER_AGENT = 95, /* "user-agent" "" */ 619 LSQPACK_TNV_X_FORWARDED_FOR = 96, /* "x-forwarded-for" "" */ 620 LSQPACK_TNV_X_FRAME_OPTIONS_DENY = 97, /* "x-frame-options" "deny" */ 621 LSQPACK_TNV_X_FRAME_OPTIONS_SAMEORIGIN = 98, /* "x-frame-options" "sameorigin" */ 622}; 623 624 625/* 626 * Internals follow. The internals are subject to change without notice. 627 */ 628 629#include <sys/queue.h> 630 631/* It takes 11 bytes to encode UINT64_MAX as HPACK integer */ 632#define LSQPACK_UINT64_ENC_SZ 11u 633 634struct lsqpack_enc_table_entry; 635 636STAILQ_HEAD(lsqpack_enc_head, lsqpack_enc_table_entry); 637struct lsqpack_double_enc_head; 638 639struct lsqpack_header_info_arr; 640 641struct lsqpack_dec_int_state 642{ 643 int resume; 644 unsigned M, nread; 645 uint64_t val; 646}; 647 648struct lsqpack_enc 649{ 650 /* The number of all the entries in the dynamic table that have been 651 * created so far. This is used to calculate the Absolute Index. 652 */ 653 lsqpack_abs_id_t qpe_ins_count; 654 lsqpack_abs_id_t qpe_max_acked_id; 655 lsqpack_abs_id_t qpe_last_ici; 656 657 enum { 658 LSQPACK_ENC_HEADER = 1 << 0, 659 LSQPACK_ENC_USE_DUP = 1 << 1, 660 LSQPACK_ENC_NO_MEM_GUARD = 1 << 2, 661 } qpe_flags; 662 663 unsigned qpe_cur_bytes_used; 664 unsigned qpe_cur_max_capacity; 665 unsigned qpe_real_max_capacity; 666 unsigned qpe_max_entries; 667 /* Sum of all dropped entries. OK if it overflows. */ 668 unsigned qpe_dropped; 669 670 /* The maximum risked streams is the SETTINGS_QPACK_BLOCKED_STREAMS 671 * setting. Note that streams must be differentiated from headers. 672 */ 673 unsigned qpe_max_risked_streams; 674 unsigned qpe_cur_streams_at_risk; 675 676 /* Number of used entries in qpe_hinfo_arrs */ 677 unsigned qpe_hinfo_arrs_count; 678 679 /* Dynamic table entries (struct enc_table_entry) live in two hash 680 * tables: name/value hash table and name hash table. These tables 681 * are the same size. 682 */ 683 unsigned qpe_nelem; 684 unsigned qpe_nbits; 685 struct lsqpack_enc_head qpe_all_entries; 686 struct lsqpack_double_enc_head 687 *qpe_buckets; 688 689 STAILQ_HEAD(, lsqpack_header_info_arr) 690 qpe_hinfo_arrs; 691 TAILQ_HEAD(, lsqpack_header_info) 692 qpe_all_hinfos; 693 TAILQ_HEAD(, lsqpack_header_info) 694 qpe_risked_hinfos; 695 696 /* Current header state */ 697 struct { 698 struct lsqpack_header_info *hinfo, *other_at_risk; 699 700 /* Number of headers in this header list added to the history */ 701 unsigned n_hdr_added_to_hist; 702 lsqpack_abs_id_t min_reffed; 703 enum lsqpack_enc_header_flags 704 flags; 705 lsqpack_abs_id_t base_idx; 706 } qpe_cur_header; 707 708 struct { 709 struct lsqpack_dec_int_state dec_int_state; 710 int (*handler)(struct lsqpack_enc *, uint64_t); 711 } qpe_dec_stream_state; 712 713 /* Used to calculate estimated compression ratio. Note that the `out' 714 * part contains bytes sent on the decoder stream, as it also counts 715 * toward the overhead. 716 */ 717 unsigned qpe_bytes_in; 718 unsigned qpe_bytes_out; 719 void *qpe_logger_ctx; 720 721 /* Exponential moving averages (EMAs) of the number of elements in the 722 * dynamic table and the number of header fields in a single header list. 723 * These values are used to adjust history size. 724 */ 725 float qpe_table_nelem_ema; 726 float qpe_header_count_ema; 727 728 struct lsqpack_hist_el *qpe_hist_els; 729 unsigned qpe_hist_idx; 730 unsigned qpe_hist_nels; 731 int qpe_hist_wrapped; 732}; 733 734struct lsqpack_ringbuf 735{ 736 unsigned rb_nalloc, rb_head, rb_tail; 737 void **rb_els; 738}; 739 740TAILQ_HEAD(lsqpack_header_sets, lsqpack_header_set_elem); 741 742struct lsqpack_header_block; 743 744struct lsqpack_decode_status 745{ 746 uint8_t state; 747 uint8_t eos; 748}; 749 750struct lsqpack_huff_decode_state 751{ 752 int resume; 753 struct lsqpack_decode_status status; 754}; 755 756struct lsqpack_dec_inst; 757 758struct lsqpack_dec 759{ 760 enum lsqpack_dec_opts qpd_opts; 761 /** This is the hard limit set at initialization */ 762 unsigned qpd_max_capacity; 763 /** The current maximum capacity can be adjusted at run-time */ 764 unsigned qpd_cur_max_capacity; 765 unsigned qpd_cur_capacity; 766 unsigned qpd_max_risked_streams; 767 unsigned qpd_max_entries; 768 /* Used to calculate estimated compression ratio. Note that the `in' 769 * part contains bytes sent on the decoder stream, as it also counts 770 * toward the overhead. 771 */ 772 unsigned qpd_bytes_in; 773 unsigned qpd_bytes_out; 774 /** ID of the last dynamic table entry. Has the range 775 * [0, qpd_max_entries * 2 - 1 ] 776 */ 777 lsqpack_abs_id_t qpd_last_id; 778 /** TODO: describe the mechanism */ 779 lsqpack_abs_id_t qpd_largest_known_id; 780 const struct lsqpack_dec_hset_if 781 *qpd_dh_if; 782 783 void *qpd_logger_ctx; 784 785 /** This is the dynamic table */ 786 struct lsqpack_ringbuf qpd_dyn_table; 787 788 TAILQ_HEAD(, header_block_read_ctx) 789 qpd_hbrcs; 790 791 /** Blocked headers are kept in a small hash */ 792#define LSQPACK_DEC_BLOCKED_BITS 3 793 TAILQ_HEAD(, header_block_read_ctx) 794 qpd_blocked_headers[1 << LSQPACK_DEC_BLOCKED_BITS]; 795 /** Number of blocked streams (in qpd_blocked_headers) */ 796 unsigned qpd_n_blocked; 797 798 /** Average number of header fields in header list */ 799 float qpd_hlist_size_ema; 800 801 /** Reading the encoder stream */ 802 struct { 803 int resume; 804 union { 805 /* State for reading in the Insert With Named Reference 806 * instruction. 807 */ 808 struct { 809 struct lsqpack_dec_int_state dec_int_state; 810 struct lsqpack_huff_decode_state dec_huff_state; 811 unsigned name_idx; 812 unsigned val_len; 813 struct lsqpack_dec_table_entry *reffed_entry; 814 struct lsqpack_dec_table_entry *entry; 815 const char *name; 816 unsigned alloced_val_len; 817 unsigned val_off; 818 unsigned nread; 819 unsigned name_len; 820 signed char is_huffman; 821 signed char is_static; 822 } with_namref; 823 824 /* State for reading in the Insert Without Named Reference 825 * instruction. 826 */ 827 struct { 828 struct lsqpack_dec_int_state dec_int_state; 829 struct lsqpack_huff_decode_state dec_huff_state; 830 unsigned str_len; 831 struct lsqpack_dec_table_entry *entry; 832 unsigned alloced_len; 833 unsigned str_off; 834 unsigned nread; 835 signed char is_huffman; 836 } wo_namref; 837 838 struct { 839 struct lsqpack_dec_int_state dec_int_state; 840 unsigned index; 841 } duplicate; 842 843 struct { 844 struct lsqpack_dec_int_state dec_int_state; 845 uint64_t new_size; 846 } sdtc; 847 } ctx_u; 848 } qpd_enc_state; 849 struct lsqpack_dec_err qpd_err; 850}; 851 852#ifdef __cplusplus 853} 854#endif 855 856#endif 857