lshpack.h revision 6a4060db
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#include <sys/uio.h> 35 36/** 37 * Strings up to 65535 characters in length are supported. 38 */ 39typedef uint16_t lshpack_strlen_t; 40 41/** Maximum length is defined for convenience */ 42#define LSHPACK_MAX_STRLEN UINT16_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, lshpack_strlen_t name_len, 157 const char *value, lshpack_strlen_t 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 * Initialize HPACK decoder structure. 184 */ 185void 186lshpack_dec_init (struct lshpack_dec *); 187 188/** 189 * Clean up HPACK decoder structure, freeing all allocated memory. 190 */ 191void 192lshpack_dec_cleanup (struct lshpack_dec *); 193 194/* 195 * Returns 0 on success, a negative value on failure. 196 * 197 * If 0 is returned, `src' is advanced. Calling with a zero-length input 198 * buffer results in an error. 199 */ 200int 201lshpack_dec_decode (struct lshpack_dec *dec, 202 const unsigned char **src, const unsigned char *src_end, 203 char *dst, char *const dst_end, lshpack_strlen_t *name_len, 204 lshpack_strlen_t *val_len, uint32_t *name_idx); 205 206void 207lshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned); 208 209/* Some internals follow. Struct definitions are exposed to save a malloc. 210 * These structures are not very complicated. 211 */ 212 213#include <sys/queue.h> 214 215struct lshpack_enc_table_entry; 216 217STAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry); 218struct lshpack_double_enc_head; 219 220struct lshpack_enc 221{ 222 unsigned hpe_cur_capacity; 223 unsigned hpe_max_capacity; 224 225 /* Each new dynamic table entry gets the next number. It is used to 226 * calculate the entry's position in the decoder table without having 227 * to maintain an actual array. 228 */ 229 unsigned hpe_next_id; 230 231 /* Dynamic table entries (struct enc_table_entry) live in two hash 232 * tables: name/value hash table and name hash table. These tables 233 * are the same size. 234 */ 235 unsigned hpe_nelem; 236 unsigned hpe_nbits; 237 struct lshpack_enc_head 238 hpe_all_entries; 239 struct lshpack_double_enc_head 240 *hpe_buckets; 241}; 242 243struct lshpack_arr 244{ 245 unsigned nalloc, 246 nelem, 247 off; 248 uintptr_t *els; 249}; 250 251struct lshpack_dec 252{ 253 unsigned hpd_max_capacity; /* Maximum set by caller */ 254 unsigned hpd_cur_max_capacity; /* Adjusted at runtime */ 255 unsigned hpd_cur_capacity; 256 struct lshpack_arr hpd_dyn_table; 257}; 258 259unsigned 260lshpack_enc_get_stx_tab_id (const char *name, lshpack_strlen_t name_len, 261 const char *val, lshpack_strlen_t val_len, int *val_matched); 262 263#ifdef __cplusplus 264} 265#endif 266 267#endif 268