1aba8e86eSDmitri Tikhonov/* 2aba8e86eSDmitri TikhonovMIT License 3aba8e86eSDmitri Tikhonov 4d4b9b92cSGeorge WangCopyright (c) 2018 - 2021 LiteSpeed Technologies Inc 5aba8e86eSDmitri Tikhonov 6aba8e86eSDmitri TikhonovPermission is hereby granted, free of charge, to any person obtaining a copy 7aba8e86eSDmitri Tikhonovof this software and associated documentation files (the "Software"), to deal 8aba8e86eSDmitri Tikhonovin the Software without restriction, including without limitation the rights 9aba8e86eSDmitri Tikhonovto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10aba8e86eSDmitri Tikhonovcopies of the Software, and to permit persons to whom the Software is 11aba8e86eSDmitri Tikhonovfurnished to do so, subject to the following conditions: 12aba8e86eSDmitri Tikhonov 13aba8e86eSDmitri TikhonovThe above copyright notice and this permission notice shall be included in all 14aba8e86eSDmitri Tikhonovcopies or substantial portions of the Software. 15aba8e86eSDmitri Tikhonov 16aba8e86eSDmitri TikhonovTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17aba8e86eSDmitri TikhonovIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18aba8e86eSDmitri TikhonovFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19aba8e86eSDmitri TikhonovAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20aba8e86eSDmitri TikhonovLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21aba8e86eSDmitri TikhonovOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22aba8e86eSDmitri TikhonovSOFTWARE. 23aba8e86eSDmitri Tikhonov*/ 24aba8e86eSDmitri Tikhonov 25868e25b9SDmitri Tikhonov#ifndef LITESPEED_HPACK_H 26868e25b9SDmitri Tikhonov#define LITESPEED_HPACK_H 1 27868e25b9SDmitri Tikhonov 28868e25b9SDmitri Tikhonov#ifdef __cplusplus 29868e25b9SDmitri Tikhonovextern "C" { 30868e25b9SDmitri Tikhonov#endif 31868e25b9SDmitri Tikhonov 32226eedebSDmitri Tikhonov#include <limits.h> 33868e25b9SDmitri Tikhonov#include <stdint.h> 34c298a38cSGlenn Strauss#include "lsxpack_header.h" 35868e25b9SDmitri Tikhonov 36226eedebSDmitri Tikhonov#define LSHPACK_MAJOR_VERSION 2 37d4b9b92cSGeorge Wang#define LSHPACK_MINOR_VERSION 3 38d4b9b92cSGeorge Wang#define LSHPACK_PATCH_VERSION 0 395ed13cadSDmitri Tikhonov 40226eedebSDmitri Tikhonov#define lshpack_strlen_t lsxpack_strlen_t 41226eedebSDmitri Tikhonov#define LSHPACK_MAX_STRLEN LSXPACK_MAX_STRLEN 42868e25b9SDmitri Tikhonov 43600751b9SDmitri Tikhonov#ifndef LSHPACK_DEC_HTTP1X_OUTPUT 44600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_OUTPUT 1 45600751b9SDmitri Tikhonov#endif 46600751b9SDmitri Tikhonov#ifndef LSHPACK_DEC_CALC_HASH 47600751b9SDmitri Tikhonov#define LSHPACK_DEC_CALC_HASH 1 48600751b9SDmitri Tikhonov#endif 49600751b9SDmitri Tikhonov 50868e25b9SDmitri Tikhonovstruct lshpack_enc; 51868e25b9SDmitri Tikhonovstruct lshpack_dec; 52868e25b9SDmitri Tikhonov 53226eedebSDmitri Tikhonovenum lshpack_static_hdr_idx 54226eedebSDmitri Tikhonov{ 55226eedebSDmitri Tikhonov LSHPACK_HDR_UNKNOWN, 56226eedebSDmitri Tikhonov LSHPACK_HDR_AUTHORITY, 57226eedebSDmitri Tikhonov LSHPACK_HDR_METHOD_GET, 58226eedebSDmitri Tikhonov LSHPACK_HDR_METHOD_POST, 59226eedebSDmitri Tikhonov LSHPACK_HDR_PATH, 60226eedebSDmitri Tikhonov LSHPACK_HDR_PATH_INDEX_HTML, 61226eedebSDmitri Tikhonov LSHPACK_HDR_SCHEME_HTTP, 62226eedebSDmitri Tikhonov LSHPACK_HDR_SCHEME_HTTPS, 63226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_200, 64226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_204, 65226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_206, 66226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_304, 67226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_400, 68226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_404, 69226eedebSDmitri Tikhonov LSHPACK_HDR_STATUS_500, 70226eedebSDmitri Tikhonov LSHPACK_HDR_ACCEPT_CHARSET, 71226eedebSDmitri Tikhonov LSHPACK_HDR_ACCEPT_ENCODING, 72226eedebSDmitri Tikhonov LSHPACK_HDR_ACCEPT_LANGUAGE, 73226eedebSDmitri Tikhonov LSHPACK_HDR_ACCEPT_RANGES, 74226eedebSDmitri Tikhonov LSHPACK_HDR_ACCEPT, 75226eedebSDmitri Tikhonov LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN, 76226eedebSDmitri Tikhonov LSHPACK_HDR_AGE, 77226eedebSDmitri Tikhonov LSHPACK_HDR_ALLOW, 78226eedebSDmitri Tikhonov LSHPACK_HDR_AUTHORIZATION, 79226eedebSDmitri Tikhonov LSHPACK_HDR_CACHE_CONTROL, 80226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_DISPOSITION, 81226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_ENCODING, 82226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_LANGUAGE, 83226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_LENGTH, 84226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_LOCATION, 85226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_RANGE, 86226eedebSDmitri Tikhonov LSHPACK_HDR_CONTENT_TYPE, 87226eedebSDmitri Tikhonov LSHPACK_HDR_COOKIE, 88226eedebSDmitri Tikhonov LSHPACK_HDR_DATE, 89226eedebSDmitri Tikhonov LSHPACK_HDR_ETAG, 90226eedebSDmitri Tikhonov LSHPACK_HDR_EXPECT, 91226eedebSDmitri Tikhonov LSHPACK_HDR_EXPIRES, 92226eedebSDmitri Tikhonov LSHPACK_HDR_FROM, 93226eedebSDmitri Tikhonov LSHPACK_HDR_HOST, 94226eedebSDmitri Tikhonov LSHPACK_HDR_IF_MATCH, 95226eedebSDmitri Tikhonov LSHPACK_HDR_IF_MODIFIED_SINCE, 96226eedebSDmitri Tikhonov LSHPACK_HDR_IF_NONE_MATCH, 97226eedebSDmitri Tikhonov LSHPACK_HDR_IF_RANGE, 98226eedebSDmitri Tikhonov LSHPACK_HDR_IF_UNMODIFIED_SINCE, 99226eedebSDmitri Tikhonov LSHPACK_HDR_LAST_MODIFIED, 100226eedebSDmitri Tikhonov LSHPACK_HDR_LINK, 101226eedebSDmitri Tikhonov LSHPACK_HDR_LOCATION, 102226eedebSDmitri Tikhonov LSHPACK_HDR_MAX_FORWARDS, 103226eedebSDmitri Tikhonov LSHPACK_HDR_PROXY_AUTHENTICATE, 104226eedebSDmitri Tikhonov LSHPACK_HDR_PROXY_AUTHORIZATION, 105226eedebSDmitri Tikhonov LSHPACK_HDR_RANGE, 106226eedebSDmitri Tikhonov LSHPACK_HDR_REFERER, 107226eedebSDmitri Tikhonov LSHPACK_HDR_REFRESH, 108226eedebSDmitri Tikhonov LSHPACK_HDR_RETRY_AFTER, 109226eedebSDmitri Tikhonov LSHPACK_HDR_SERVER, 110226eedebSDmitri Tikhonov LSHPACK_HDR_SET_COOKIE, 111226eedebSDmitri Tikhonov LSHPACK_HDR_STRICT_TRANSPORT_SECURITY, 112226eedebSDmitri Tikhonov LSHPACK_HDR_TRANSFER_ENCODING, 113226eedebSDmitri Tikhonov LSHPACK_HDR_USER_AGENT, 114226eedebSDmitri Tikhonov LSHPACK_HDR_VARY, 115226eedebSDmitri Tikhonov LSHPACK_HDR_VIA, 116600751b9SDmitri Tikhonov LSHPACK_HDR_WWW_AUTHENTICATE, 117600751b9SDmitri Tikhonov LSHPACK_HDR_TOBE_INDEXED = 255 118226eedebSDmitri Tikhonov}; 119226eedebSDmitri Tikhonov 12054378593SGeorge Wang#define LSHPACK_MAX_INDEX 61 12154378593SGeorge Wang 122226eedebSDmitri Tikhonov#define LSHPACK_ERR_MORE_BUF (-3) 123226eedebSDmitri Tikhonov#define LSHPACK_ERR_TOO_LARGE (-2) 124226eedebSDmitri Tikhonov#define LSHPACK_ERR_BAD_DATA (-1) 125226eedebSDmitri Tikhonov#define LSHPACK_OK (0) 126226eedebSDmitri Tikhonov 127868e25b9SDmitri Tikhonov/** 128868e25b9SDmitri Tikhonov * Initialization routine allocates memory. -1 is returned if memory 129868e25b9SDmitri Tikhonov * could not be allocated. 0 is returned on success. 130868e25b9SDmitri Tikhonov */ 131868e25b9SDmitri Tikhonovint 132868e25b9SDmitri Tikhonovlshpack_enc_init (struct lshpack_enc *); 133868e25b9SDmitri Tikhonov 134868e25b9SDmitri Tikhonov/** 135868e25b9SDmitri Tikhonov * Clean up HPACK encoder, freeing all allocated memory. 136868e25b9SDmitri Tikhonov */ 137868e25b9SDmitri Tikhonovvoid 138868e25b9SDmitri Tikhonovlshpack_enc_cleanup (struct lshpack_enc *); 139868e25b9SDmitri Tikhonov 140868e25b9SDmitri Tikhonov/** 141868e25b9SDmitri Tikhonov * @brief Encode one name/value pair 142868e25b9SDmitri Tikhonov * 143868e25b9SDmitri Tikhonov * @param[in,out] henc - A pointer to a valid HPACK API struct 144868e25b9SDmitri Tikhonov * @param[out] dst - A pointer to destination buffer 145868e25b9SDmitri Tikhonov * @param[out] dst_end - A pointer to end of destination buffer 146226eedebSDmitri Tikhonov * @param[in] input - Header to encode 147868e25b9SDmitri Tikhonov * 148868e25b9SDmitri Tikhonov * @return The (possibly advanced) dst pointer. If the destination 149868e25b9SDmitri Tikhonov * pointer was not advanced, an error must have occurred. 150868e25b9SDmitri Tikhonov */ 151868e25b9SDmitri Tikhonovunsigned char * 152868e25b9SDmitri Tikhonovlshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst, 153226eedebSDmitri Tikhonov unsigned char *dst_end, struct lsxpack_header *input); 154868e25b9SDmitri Tikhonov 155868e25b9SDmitri Tikhonovvoid 156868e25b9SDmitri Tikhonovlshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned); 157868e25b9SDmitri Tikhonov 158868e25b9SDmitri Tikhonov/** 15972061d40SDmitri Tikhonov * Turn history on or off. Turning history on may fail (malloc), in 16072061d40SDmitri Tikhonov * which case -1 is returned. 16172061d40SDmitri Tikhonov */ 16272061d40SDmitri Tikhonovint 16372061d40SDmitri Tikhonovlshpack_enc_use_hist (struct lshpack_enc *, int on); 16472061d40SDmitri Tikhonov 16572061d40SDmitri Tikhonov/** 16672061d40SDmitri Tikhonov * Return true if history is used, false otherwise. By default, 16772061d40SDmitri Tikhonov * history is off. 16872061d40SDmitri Tikhonov */ 16972061d40SDmitri Tikhonovint 17072061d40SDmitri Tikhonovlshpack_enc_hist_used (const struct lshpack_enc *); 17172061d40SDmitri Tikhonov 17272061d40SDmitri Tikhonov/** 173868e25b9SDmitri Tikhonov * Initialize HPACK decoder structure. 174868e25b9SDmitri Tikhonov */ 175868e25b9SDmitri Tikhonovvoid 176600751b9SDmitri Tikhonovlshpack_dec_init (struct lshpack_dec *); 177868e25b9SDmitri Tikhonov 178868e25b9SDmitri Tikhonov/** 179868e25b9SDmitri Tikhonov * Clean up HPACK decoder structure, freeing all allocated memory. 180868e25b9SDmitri Tikhonov */ 181868e25b9SDmitri Tikhonovvoid 182868e25b9SDmitri Tikhonovlshpack_dec_cleanup (struct lshpack_dec *); 183868e25b9SDmitri Tikhonov 184868e25b9SDmitri Tikhonov/* 185868e25b9SDmitri Tikhonov * Returns 0 on success, a negative value on failure. 186868e25b9SDmitri Tikhonov * 187868e25b9SDmitri Tikhonov * If 0 is returned, `src' is advanced. Calling with a zero-length input 188868e25b9SDmitri Tikhonov * buffer results in an error. 189226eedebSDmitri Tikhonov * 190226eedebSDmitri Tikhonov * To calculate number of bytes written to the output buffer: 191226eedebSDmitri Tikhonov * output->name_len + output->val_len + lshpack_dec_extra_bytes(dec) 192868e25b9SDmitri Tikhonov */ 193868e25b9SDmitri Tikhonovint 194868e25b9SDmitri Tikhonovlshpack_dec_decode (struct lshpack_dec *dec, 195868e25b9SDmitri Tikhonov const unsigned char **src, const unsigned char *src_end, 196226eedebSDmitri Tikhonov struct lsxpack_header *output); 197226eedebSDmitri Tikhonov 198226eedebSDmitri Tikhonov/* Return number of extra bytes per header */ 199600751b9SDmitri Tikhonov#if LSHPACK_DEC_HTTP1X_OUTPUT 200600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_EXTRA (2) 201600751b9SDmitri Tikhonov#define lshpack_dec_extra_bytes(dec_) (4) 202600751b9SDmitri Tikhonov#else 203600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_EXTRA (0) 204600751b9SDmitri Tikhonov#define lshpack_dec_extra_bytes(dec_) (0) 205600751b9SDmitri Tikhonov#endif 206868e25b9SDmitri Tikhonov 207868e25b9SDmitri Tikhonovvoid 208868e25b9SDmitri Tikhonovlshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned); 209868e25b9SDmitri Tikhonov 210868e25b9SDmitri Tikhonov/* Some internals follow. Struct definitions are exposed to save a malloc. 211868e25b9SDmitri Tikhonov * These structures are not very complicated. 212868e25b9SDmitri Tikhonov */ 213868e25b9SDmitri Tikhonov 214868e25b9SDmitri Tikhonov#include <sys/queue.h> 215868e25b9SDmitri Tikhonov 2165459745fSGlenn Strauss#ifdef __OpenBSD__ 2175459745fSGlenn Strauss#define STAILQ_HEAD SIMPLEQ_HEAD 2185459745fSGlenn Strauss#define STAILQ_ENTRY SIMPLEQ_ENTRY 2195459745fSGlenn Strauss#define STAILQ_INIT SIMPLEQ_INIT 2205459745fSGlenn Strauss#define STAILQ_INSERT_TAIL SIMPLEQ_INSERT_TAIL 2215459745fSGlenn Strauss#define STAILQ_EMPTY SIMPLEQ_EMPTY 2225459745fSGlenn Strauss#define STAILQ_FIRST SIMPLEQ_FIRST 2235459745fSGlenn Strauss#define STAILQ_NEXT SIMPLEQ_NEXT 2245459745fSGlenn Strauss#define STAILQ_REMOVE_HEAD SIMPLEQ_REMOVE_HEAD 2255459745fSGlenn Strauss#define STAILQ_FOREACH SIMPLEQ_FOREACH 2265459745fSGlenn Strauss#endif 2275459745fSGlenn Strauss 2283ba42754SDmitri Tikhonovstruct lshpack_enc_table_entry; 229868e25b9SDmitri Tikhonov 2303ba42754SDmitri TikhonovSTAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry); 2313ba42754SDmitri Tikhonovstruct lshpack_double_enc_head; 232868e25b9SDmitri Tikhonov 233868e25b9SDmitri Tikhonovstruct lshpack_enc 234868e25b9SDmitri Tikhonov{ 235868e25b9SDmitri Tikhonov unsigned hpe_cur_capacity; 236868e25b9SDmitri Tikhonov unsigned hpe_max_capacity; 237868e25b9SDmitri Tikhonov 238868e25b9SDmitri Tikhonov /* Each new dynamic table entry gets the next number. It is used to 239868e25b9SDmitri Tikhonov * calculate the entry's position in the decoder table without having 240868e25b9SDmitri Tikhonov * to maintain an actual array. 241868e25b9SDmitri Tikhonov */ 242868e25b9SDmitri Tikhonov unsigned hpe_next_id; 243868e25b9SDmitri Tikhonov 244868e25b9SDmitri Tikhonov /* Dynamic table entries (struct enc_table_entry) live in two hash 245868e25b9SDmitri Tikhonov * tables: name/value hash table and name hash table. These tables 246868e25b9SDmitri Tikhonov * are the same size. 247868e25b9SDmitri Tikhonov */ 248868e25b9SDmitri Tikhonov unsigned hpe_nelem; 249868e25b9SDmitri Tikhonov unsigned hpe_nbits; 2503ba42754SDmitri Tikhonov struct lshpack_enc_head 2513ba42754SDmitri Tikhonov hpe_all_entries; 2523ba42754SDmitri Tikhonov struct lshpack_double_enc_head 253868e25b9SDmitri Tikhonov *hpe_buckets; 25472061d40SDmitri Tikhonov 25572061d40SDmitri Tikhonov uint32_t *hpe_hist_buf; 25672061d40SDmitri Tikhonov unsigned hpe_hist_size, hpe_hist_idx; 25772061d40SDmitri Tikhonov int hpe_hist_wrapped; 25872061d40SDmitri Tikhonov enum { 25972061d40SDmitri Tikhonov LSHPACK_ENC_USE_HIST = 1 << 0, 26072061d40SDmitri Tikhonov } hpe_flags; 261868e25b9SDmitri Tikhonov}; 262868e25b9SDmitri Tikhonov 263868e25b9SDmitri Tikhonovstruct lshpack_arr 264868e25b9SDmitri Tikhonov{ 265868e25b9SDmitri Tikhonov unsigned nalloc, 266868e25b9SDmitri Tikhonov nelem, 267868e25b9SDmitri Tikhonov off; 268868e25b9SDmitri Tikhonov uintptr_t *els; 269868e25b9SDmitri Tikhonov}; 270868e25b9SDmitri Tikhonov 271868e25b9SDmitri Tikhonovstruct lshpack_dec 272868e25b9SDmitri Tikhonov{ 273226eedebSDmitri Tikhonov struct lshpack_arr hpd_dyn_table; 274868e25b9SDmitri Tikhonov unsigned hpd_max_capacity; /* Maximum set by caller */ 275868e25b9SDmitri Tikhonov unsigned hpd_cur_max_capacity; /* Adjusted at runtime */ 276868e25b9SDmitri Tikhonov unsigned hpd_cur_capacity; 277226eedebSDmitri Tikhonov unsigned hpd_state; 278868e25b9SDmitri Tikhonov}; 279868e25b9SDmitri Tikhonov 280226eedebSDmitri Tikhonov/* This function may update hash values and flags */ 281226eedebSDmitri Tikhonovunsigned 282226eedebSDmitri Tikhonovlshpack_enc_get_stx_tab_id (struct lsxpack_header *); 283fa385e06SDmitri Tikhonov 284868e25b9SDmitri Tikhonov#ifdef __cplusplus 285868e25b9SDmitri Tikhonov} 286868e25b9SDmitri Tikhonov#endif 287868e25b9SDmitri Tikhonov 288868e25b9SDmitri Tikhonov#endif 289