lshpack.h revision 2d296031
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 <stdint.h> 34#ifndef WIN32 35#include <sys/uio.h> 36#else 37#include "vc_compat.h" 38#endif 39 40/** 41 * Strings up to 65535 characters in length are supported. 42 */ 43typedef uint16_t lshpack_strlen_t; 44 45/** Maximum length is defined for convenience */ 46#define LSHPACK_MAX_STRLEN UINT16_MAX 47 48struct lshpack_enc; 49struct lshpack_dec; 50 51/** 52 * @typedef lshpack_http_header_t 53 * @brief HTTP header structure. Contains header name and value. 54 * 55 */ 56typedef struct lshpack_header 57{ 58 struct iovec name; 59 struct iovec value; 60} lshpack_header_t; 61 62 63enum lshpack_static_hdr_idx 64{ 65 LSHPACK_HDR_UNKNOWN, 66 LSHPACK_HDR_AUTHORITY, 67 LSHPACK_HDR_METHOD_GET, 68 LSHPACK_HDR_METHOD_POST, 69 LSHPACK_HDR_PATH, 70 LSHPACK_HDR_PATH_INDEX_HTML, 71 LSHPACK_HDR_SCHEME_HTTP, 72 LSHPACK_HDR_SCHEME_HTTPS, 73 LSHPACK_HDR_STATUS_200, 74 LSHPACK_HDR_STATUS_204, 75 LSHPACK_HDR_STATUS_206, 76 LSHPACK_HDR_STATUS_304, 77 LSHPACK_HDR_STATUS_400, 78 LSHPACK_HDR_STATUS_404, 79 LSHPACK_HDR_STATUS_500, 80 LSHPACK_HDR_ACCEPT_CHARSET, 81 LSHPACK_HDR_ACCEPT_ENCODING, 82 LSHPACK_HDR_ACCEPT_LANGUAGE, 83 LSHPACK_HDR_ACCEPT_RANGES, 84 LSHPACK_HDR_ACCEPT, 85 LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN, 86 LSHPACK_HDR_AGE, 87 LSHPACK_HDR_ALLOW, 88 LSHPACK_HDR_AUTHORIZATION, 89 LSHPACK_HDR_CACHE_CONTROL, 90 LSHPACK_HDR_CONTENT_DISPOSITION, 91 LSHPACK_HDR_CONTENT_ENCODING, 92 LSHPACK_HDR_CONTENT_LANGUAGE, 93 LSHPACK_HDR_CONTENT_LENGTH, 94 LSHPACK_HDR_CONTENT_LOCATION, 95 LSHPACK_HDR_CONTENT_RANGE, 96 LSHPACK_HDR_CONTENT_TYPE, 97 LSHPACK_HDR_COOKIE, 98 LSHPACK_HDR_DATE, 99 LSHPACK_HDR_ETAG, 100 LSHPACK_HDR_EXPECT, 101 LSHPACK_HDR_EXPIRES, 102 LSHPACK_HDR_FROM, 103 LSHPACK_HDR_HOST, 104 LSHPACK_HDR_IF_MATCH, 105 LSHPACK_HDR_IF_MODIFIED_SINCE, 106 LSHPACK_HDR_IF_NONE_MATCH, 107 LSHPACK_HDR_IF_RANGE, 108 LSHPACK_HDR_IF_UNMODIFIED_SINCE, 109 LSHPACK_HDR_LAST_MODIFIED, 110 LSHPACK_HDR_LINK, 111 LSHPACK_HDR_LOCATION, 112 LSHPACK_HDR_MAX_FORWARDS, 113 LSHPACK_HDR_PROXY_AUTHENTICATE, 114 LSHPACK_HDR_PROXY_AUTHORIZATION, 115 LSHPACK_HDR_RANGE, 116 LSHPACK_HDR_REFERER, 117 LSHPACK_HDR_REFRESH, 118 LSHPACK_HDR_RETRY_AFTER, 119 LSHPACK_HDR_SERVER, 120 LSHPACK_HDR_SET_COOKIE, 121 LSHPACK_HDR_STRICT_TRANSPORT_SECURITY, 122 LSHPACK_HDR_TRANSFER_ENCODING, 123 LSHPACK_HDR_USER_AGENT, 124 LSHPACK_HDR_VARY, 125 LSHPACK_HDR_VIA, 126 LSHPACK_HDR_WWW_AUTHENTICATE 127}; 128 129 130/** 131 * Initialization routine allocates memory. -1 is returned if memory 132 * could not be allocated. 0 is returned on success. 133 */ 134int 135lshpack_enc_init (struct lshpack_enc *); 136 137/** 138 * Clean up HPACK encoder, freeing all allocated memory. 139 */ 140void 141lshpack_enc_cleanup (struct lshpack_enc *); 142 143/** 144 * @brief Encode one name/value pair 145 * 146 * @param[in,out] henc - A pointer to a valid HPACK API struct 147 * @param[out] dst - A pointer to destination buffer 148 * @param[out] dst_end - A pointer to end of destination buffer 149 * @param[in] name - A pointer to the item name 150 * @param[in] name_len - The item name's length 151 * @param[in] value - A pointer to the item value 152 * @param[in] value_len - The item value's length 153 * @param[in] indexed_type - 0, Add, 1,: without, 2: never 154 * 155 * @return The (possibly advanced) dst pointer. If the destination 156 * pointer was not advanced, an error must have occurred. 157 */ 158unsigned char * 159lshpack_enc_encode2 (struct lshpack_enc *henc, unsigned char *dst, 160 unsigned char *dst_end, const char *name, lshpack_strlen_t name_len, 161 const char *value, lshpack_strlen_t value_len, int indexed_type); 162 163 164/** 165 * @brief Encode one name/value pair 166 * 167 * @param[in,out] henc - A pointer to a valid HPACK API struct 168 * @param[out] dst - A pointer to destination buffer 169 * @param[out] dst_end - A pointer to end of destination buffer 170 * @param[in] hpack_idx - The position of header name in static table, 171 * 0 = unknown, < 0 not in static table, 1 - 63 the position 172 * @param[in] hdr - the header name and value 173 * @param[in] indexed_type - 0, Add, 1,: without, 2: never 174 * 175 * @return The (possibly advanced) dst pointer. If the destination 176 * pointer was not advanced, an error must have occurred. 177 */ 178unsigned char * 179lshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst, 180 unsigned char *dst_end, int hpack_idx, 181 const lshpack_header_t *hdr, int indexed_type); 182 183void 184lshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned); 185 186/** 187 * Initialize HPACK decoder structure. 188 */ 189void 190lshpack_dec_init (struct lshpack_dec *); 191 192/** 193 * Clean up HPACK decoder structure, freeing all allocated memory. 194 */ 195void 196lshpack_dec_cleanup (struct lshpack_dec *); 197 198/* 199 * Returns 0 on success, a negative value on failure. 200 * 201 * If 0 is returned, `src' is advanced. Calling with a zero-length input 202 * buffer results in an error. 203 */ 204int 205lshpack_dec_decode (struct lshpack_dec *dec, 206 const unsigned char **src, const unsigned char *src_end, 207 char *dst, char *const dst_end, lshpack_strlen_t *name_len, 208 lshpack_strlen_t *val_len, uint32_t *name_idx); 209 210void 211lshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned); 212 213/* Some internals follow. Struct definitions are exposed to save a malloc. 214 * These structures are not very complicated. 215 */ 216 217#include <sys/queue.h> 218 219struct lshpack_enc_table_entry; 220 221STAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry); 222struct lshpack_double_enc_head; 223 224struct lshpack_enc 225{ 226 unsigned hpe_cur_capacity; 227 unsigned hpe_max_capacity; 228 229 /* Each new dynamic table entry gets the next number. It is used to 230 * calculate the entry's position in the decoder table without having 231 * to maintain an actual array. 232 */ 233 unsigned hpe_next_id; 234 235 /* Dynamic table entries (struct enc_table_entry) live in two hash 236 * tables: name/value hash table and name hash table. These tables 237 * are the same size. 238 */ 239 unsigned hpe_nelem; 240 unsigned hpe_nbits; 241 struct lshpack_enc_head 242 hpe_all_entries; 243 struct lshpack_double_enc_head 244 *hpe_buckets; 245}; 246 247struct lshpack_arr 248{ 249 unsigned nalloc, 250 nelem, 251 off; 252 uintptr_t *els; 253}; 254 255struct lshpack_dec 256{ 257 unsigned hpd_max_capacity; /* Maximum set by caller */ 258 unsigned hpd_cur_max_capacity; /* Adjusted at runtime */ 259 unsigned hpd_cur_capacity; 260 struct lshpack_arr hpd_dyn_table; 261}; 262 263unsigned 264lshpack_enc_get_stx_tab_id (const char *name, lshpack_strlen_t name_len, 265 const char *val, lshpack_strlen_t val_len, int *val_matched); 266 267#ifdef __cplusplus 268} 269#endif 270 271#endif 272