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