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