lshpack.h revision 8cba36d8
1/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3MIT License 4 5Copyright (c) 2018 LiteSpeed Technologies Inc 6 7Permission is hereby granted, free of charge, to any person obtaining a copy 8of this software and associated documentation files (the "Software"), to deal 9in the Software without restriction, including without limitation the rights 10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11copies of the Software, and to permit persons to whom the Software is 12furnished to do so, subject to the following conditions: 13 14The above copyright notice and this permission notice shall be included in all 15copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23SOFTWARE. 24*/ 25 26#ifndef LITESPEED_HPACK_H 27#define LITESPEED_HPACK_H 1 28 29#ifdef __cplusplus 30extern "C" { 31#endif 32 33#include <limits.h> 34#include <stdint.h> 35#ifndef WIN32 36#include <sys/uio.h> 37#else 38#include "vc_compat.h" 39#endif 40 41/** Maximum length is defined for convenience */ 42#define LSHPACK_MAX_STRLEN UINT_MAX 43 44struct lshpack_enc; 45struct lshpack_dec; 46 47/** 48 * @typedef lshpack_http_header_t 49 * @brief HTTP header structure. Contains header name and value. 50 * 51 */ 52typedef struct lshpack_header 53{ 54 struct iovec name; 55 struct iovec value; 56} lshpack_header_t; 57 58 59enum lshpack_static_hdr_idx 60{ 61 LSHPACK_HDR_UNKNOWN, 62 LSHPACK_HDR_AUTHORITY, 63 LSHPACK_HDR_METHOD_GET, 64 LSHPACK_HDR_METHOD_POST, 65 LSHPACK_HDR_PATH, 66 LSHPACK_HDR_PATH_INDEX_HTML, 67 LSHPACK_HDR_SCHEME_HTTP, 68 LSHPACK_HDR_SCHEME_HTTPS, 69 LSHPACK_HDR_STATUS_200, 70 LSHPACK_HDR_STATUS_204, 71 LSHPACK_HDR_STATUS_206, 72 LSHPACK_HDR_STATUS_304, 73 LSHPACK_HDR_STATUS_400, 74 LSHPACK_HDR_STATUS_404, 75 LSHPACK_HDR_STATUS_500, 76 LSHPACK_HDR_ACCEPT_CHARSET, 77 LSHPACK_HDR_ACCEPT_ENCODING, 78 LSHPACK_HDR_ACCEPT_LANGUAGE, 79 LSHPACK_HDR_ACCEPT_RANGES, 80 LSHPACK_HDR_ACCEPT, 81 LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN, 82 LSHPACK_HDR_AGE, 83 LSHPACK_HDR_ALLOW, 84 LSHPACK_HDR_AUTHORIZATION, 85 LSHPACK_HDR_CACHE_CONTROL, 86 LSHPACK_HDR_CONTENT_DISPOSITION, 87 LSHPACK_HDR_CONTENT_ENCODING, 88 LSHPACK_HDR_CONTENT_LANGUAGE, 89 LSHPACK_HDR_CONTENT_LENGTH, 90 LSHPACK_HDR_CONTENT_LOCATION, 91 LSHPACK_HDR_CONTENT_RANGE, 92 LSHPACK_HDR_CONTENT_TYPE, 93 LSHPACK_HDR_COOKIE, 94 LSHPACK_HDR_DATE, 95 LSHPACK_HDR_ETAG, 96 LSHPACK_HDR_EXPECT, 97 LSHPACK_HDR_EXPIRES, 98 LSHPACK_HDR_FROM, 99 LSHPACK_HDR_HOST, 100 LSHPACK_HDR_IF_MATCH, 101 LSHPACK_HDR_IF_MODIFIED_SINCE, 102 LSHPACK_HDR_IF_NONE_MATCH, 103 LSHPACK_HDR_IF_RANGE, 104 LSHPACK_HDR_IF_UNMODIFIED_SINCE, 105 LSHPACK_HDR_LAST_MODIFIED, 106 LSHPACK_HDR_LINK, 107 LSHPACK_HDR_LOCATION, 108 LSHPACK_HDR_MAX_FORWARDS, 109 LSHPACK_HDR_PROXY_AUTHENTICATE, 110 LSHPACK_HDR_PROXY_AUTHORIZATION, 111 LSHPACK_HDR_RANGE, 112 LSHPACK_HDR_REFERER, 113 LSHPACK_HDR_REFRESH, 114 LSHPACK_HDR_RETRY_AFTER, 115 LSHPACK_HDR_SERVER, 116 LSHPACK_HDR_SET_COOKIE, 117 LSHPACK_HDR_STRICT_TRANSPORT_SECURITY, 118 LSHPACK_HDR_TRANSFER_ENCODING, 119 LSHPACK_HDR_USER_AGENT, 120 LSHPACK_HDR_VARY, 121 LSHPACK_HDR_VIA, 122 LSHPACK_HDR_WWW_AUTHENTICATE 123}; 124 125 126/** 127 * Initialization routine allocates memory. -1 is returned if memory 128 * could not be allocated. 0 is returned on success. 129 */ 130int 131lshpack_enc_init (struct lshpack_enc *); 132 133/** 134 * Clean up HPACK encoder, freeing all allocated memory. 135 */ 136void 137lshpack_enc_cleanup (struct lshpack_enc *); 138 139/** 140 * @brief Encode one name/value pair 141 * 142 * @param[in,out] henc - A pointer to a valid HPACK API struct 143 * @param[out] dst - A pointer to destination buffer 144 * @param[out] dst_end - A pointer to end of destination buffer 145 * @param[in] name - A pointer to the item name 146 * @param[in] name_len - The item name's length 147 * @param[in] value - A pointer to the item value 148 * @param[in] value_len - The item value's length 149 * @param[in] indexed_type - 0, Add, 1,: without, 2: never 150 * 151 * @return The (possibly advanced) dst pointer. If the destination 152 * pointer was not advanced, an error must have occurred. 153 */ 154unsigned char * 155lshpack_enc_encode2 (struct lshpack_enc *henc, unsigned char *dst, 156 unsigned char *dst_end, const char *name, unsigned name_len, 157 const char *value, unsigned value_len, int indexed_type); 158 159 160/** 161 * @brief Encode one name/value pair 162 * 163 * @param[in,out] henc - A pointer to a valid HPACK API struct 164 * @param[out] dst - A pointer to destination buffer 165 * @param[out] dst_end - A pointer to end of destination buffer 166 * @param[in] hpack_idx - The position of header name in static table, 167 * 0 = unknown, < 0 not in static table, 1 - 63 the position 168 * @param[in] hdr - the header name and value 169 * @param[in] indexed_type - 0, Add, 1,: without, 2: never 170 * 171 * @return The (possibly advanced) dst pointer. If the destination 172 * pointer was not advanced, an error must have occurred. 173 */ 174unsigned char * 175lshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst, 176 unsigned char *dst_end, int hpack_idx, 177 const lshpack_header_t *hdr, int indexed_type); 178 179void 180lshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned); 181 182/** 183 * Turn history on or off. Turning history on may fail (malloc), in 184 * which case -1 is returned. 185 */ 186int 187lshpack_enc_use_hist (struct lshpack_enc *, int on); 188 189/** 190 * Return true if history is used, false otherwise. By default, 191 * history is off. 192 */ 193int 194lshpack_enc_hist_used (const struct lshpack_enc *); 195 196/** 197 * Initialize HPACK decoder structure. 198 */ 199void 200lshpack_dec_init (struct lshpack_dec *); 201 202/** 203 * Clean up HPACK decoder structure, freeing all allocated memory. 204 */ 205void 206lshpack_dec_cleanup (struct lshpack_dec *); 207 208/* 209 * Returns 0 on success, a negative value on failure. 210 * 211 * If 0 is returned, `src' is advanced. Calling with a zero-length input 212 * buffer results in an error. 213 */ 214int 215lshpack_dec_decode (struct lshpack_dec *dec, 216 const unsigned char **src, const unsigned char *src_end, 217 char *dst, char *const dst_end, unsigned *name_len, 218 unsigned *val_len, uint32_t *name_idx); 219 220void 221lshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned); 222 223/* Some internals follow. Struct definitions are exposed to save a malloc. 224 * These structures are not very complicated. 225 */ 226 227#include <sys/queue.h> 228 229struct lshpack_enc_table_entry; 230 231STAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry); 232struct lshpack_double_enc_head; 233 234struct lshpack_enc 235{ 236 unsigned hpe_cur_capacity; 237 unsigned hpe_max_capacity; 238 239 /* Each new dynamic table entry gets the next number. It is used to 240 * calculate the entry's position in the decoder table without having 241 * to maintain an actual array. 242 */ 243 unsigned hpe_next_id; 244 245 /* Dynamic table entries (struct enc_table_entry) live in two hash 246 * tables: name/value hash table and name hash table. These tables 247 * are the same size. 248 */ 249 unsigned hpe_nelem; 250 unsigned hpe_nbits; 251 struct lshpack_enc_head 252 hpe_all_entries; 253 struct lshpack_double_enc_head 254 *hpe_buckets; 255 256 uint32_t *hpe_hist_buf; 257 unsigned hpe_hist_size, hpe_hist_idx; 258 int hpe_hist_wrapped; 259 enum { 260 LSHPACK_ENC_USE_HIST = 1 << 0, 261 } hpe_flags; 262}; 263 264struct lshpack_arr 265{ 266 unsigned nalloc, 267 nelem, 268 off; 269 uintptr_t *els; 270}; 271 272struct lshpack_dec 273{ 274 unsigned hpd_max_capacity; /* Maximum set by caller */ 275 unsigned hpd_cur_max_capacity; /* Adjusted at runtime */ 276 unsigned hpd_cur_capacity; 277 struct lshpack_arr hpd_dyn_table; 278}; 279 280unsigned 281lshpack_enc_get_stx_tab_id (const char *name, unsigned name_len, 282 const char *val, unsigned val_len); 283 284#ifdef __cplusplus 285} 286#endif 287 288#endif 289