lshpack.h revision d539a752
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);
266
267#ifdef __cplusplus
268}
269#endif
270
271#endif
272