xref: /lighttpd1.4/src/ls-hpack/lshpack.h (revision f2e4e83a)
1 /*
2 MIT License
3 
4 Copyright (c) 2018 - 2020 LiteSpeed Technologies Inc
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 #ifndef LITESPEED_HPACK_H
26 #define LITESPEED_HPACK_H 1
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #include <limits.h>
33 #include <stdint.h>
34 #include "lsxpack_header.h"
35 
36 #define LSHPACK_MAJOR_VERSION 2
37 #define LSHPACK_MINOR_VERSION 2
38 #define LSHPACK_PATCH_VERSION 1
39 
40 #define lshpack_strlen_t lsxpack_strlen_t
41 #define LSHPACK_MAX_STRLEN LSXPACK_MAX_STRLEN
42 
43 /*(lighttpd customization)*/
44 /* decoder provides "field-name: value\r\n"; define to 0 to omit ": " and "\r\n" */
45 #define LSHPACK_DEC_HTTP1X_OUTPUT 0
46 
47 #ifndef LSHPACK_DEC_HTTP1X_OUTPUT
48 #define LSHPACK_DEC_HTTP1X_OUTPUT 1
49 #endif
50 #ifndef LSHPACK_DEC_CALC_HASH
51 #define LSHPACK_DEC_CALC_HASH 1
52 #endif
53 
54 struct lshpack_enc;
55 struct lshpack_dec;
56 
57 enum lshpack_static_hdr_idx
58 {
59     LSHPACK_HDR_UNKNOWN,
60     LSHPACK_HDR_AUTHORITY,
61     LSHPACK_HDR_METHOD_GET,
62     LSHPACK_HDR_METHOD_POST,
63     LSHPACK_HDR_PATH,
64     LSHPACK_HDR_PATH_INDEX_HTML,
65     LSHPACK_HDR_SCHEME_HTTP,
66     LSHPACK_HDR_SCHEME_HTTPS,
67     LSHPACK_HDR_STATUS_200,
68     LSHPACK_HDR_STATUS_204,
69     LSHPACK_HDR_STATUS_206,
70     LSHPACK_HDR_STATUS_304,
71     LSHPACK_HDR_STATUS_400,
72     LSHPACK_HDR_STATUS_404,
73     LSHPACK_HDR_STATUS_500,
74     LSHPACK_HDR_ACCEPT_CHARSET,
75     LSHPACK_HDR_ACCEPT_ENCODING,
76     LSHPACK_HDR_ACCEPT_LANGUAGE,
77     LSHPACK_HDR_ACCEPT_RANGES,
78     LSHPACK_HDR_ACCEPT,
79     LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN,
80     LSHPACK_HDR_AGE,
81     LSHPACK_HDR_ALLOW,
82     LSHPACK_HDR_AUTHORIZATION,
83     LSHPACK_HDR_CACHE_CONTROL,
84     LSHPACK_HDR_CONTENT_DISPOSITION,
85     LSHPACK_HDR_CONTENT_ENCODING,
86     LSHPACK_HDR_CONTENT_LANGUAGE,
87     LSHPACK_HDR_CONTENT_LENGTH,
88     LSHPACK_HDR_CONTENT_LOCATION,
89     LSHPACK_HDR_CONTENT_RANGE,
90     LSHPACK_HDR_CONTENT_TYPE,
91     LSHPACK_HDR_COOKIE,
92     LSHPACK_HDR_DATE,
93     LSHPACK_HDR_ETAG,
94     LSHPACK_HDR_EXPECT,
95     LSHPACK_HDR_EXPIRES,
96     LSHPACK_HDR_FROM,
97     LSHPACK_HDR_HOST,
98     LSHPACK_HDR_IF_MATCH,
99     LSHPACK_HDR_IF_MODIFIED_SINCE,
100     LSHPACK_HDR_IF_NONE_MATCH,
101     LSHPACK_HDR_IF_RANGE,
102     LSHPACK_HDR_IF_UNMODIFIED_SINCE,
103     LSHPACK_HDR_LAST_MODIFIED,
104     LSHPACK_HDR_LINK,
105     LSHPACK_HDR_LOCATION,
106     LSHPACK_HDR_MAX_FORWARDS,
107     LSHPACK_HDR_PROXY_AUTHENTICATE,
108     LSHPACK_HDR_PROXY_AUTHORIZATION,
109     LSHPACK_HDR_RANGE,
110     LSHPACK_HDR_REFERER,
111     LSHPACK_HDR_REFRESH,
112     LSHPACK_HDR_RETRY_AFTER,
113     LSHPACK_HDR_SERVER,
114     LSHPACK_HDR_SET_COOKIE,
115     LSHPACK_HDR_STRICT_TRANSPORT_SECURITY,
116     LSHPACK_HDR_TRANSFER_ENCODING,
117     LSHPACK_HDR_USER_AGENT,
118     LSHPACK_HDR_VARY,
119     LSHPACK_HDR_VIA,
120     LSHPACK_HDR_WWW_AUTHENTICATE,
121     LSHPACK_HDR_TOBE_INDEXED = 255
122 };
123 
124 #define LSHPACK_MAX_INDEX           61
125 
126 #define LSHPACK_ERR_MORE_BUF        (-3)
127 #define LSHPACK_ERR_TOO_LARGE       (-2)
128 #define LSHPACK_ERR_BAD_DATA        (-1)
129 #define LSHPACK_OK                  (0)
130 
131 /**
132  * Initialization routine allocates memory.  -1 is returned if memory
133  * could not be allocated.  0 is returned on success.
134  */
135 int
136 lshpack_enc_init (struct lshpack_enc *);
137 
138 /**
139  * Clean up HPACK encoder, freeing all allocated memory.
140  */
141 void
142 lshpack_enc_cleanup (struct lshpack_enc *);
143 
144 /**
145  * @brief Encode one name/value pair
146  *
147  * @param[in,out] henc - A pointer to a valid HPACK API struct
148  * @param[out] dst - A pointer to destination buffer
149  * @param[out] dst_end - A pointer to end of destination buffer
150  * @param[in] input - Header to encode
151  *
152  * @return The (possibly advanced) dst pointer.  If the destination
153  * pointer was not advanced, an error must have occurred.
154  */
155 unsigned char *
156 lshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst,
157         unsigned char *dst_end, struct lsxpack_header *input);
158 
159 void
160 lshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned);
161 
162 /**
163  * Turn history on or off.  Turning history on may fail (malloc), in
164  * which case -1 is returned.
165  */
166 int
167 lshpack_enc_use_hist (struct lshpack_enc *, int on);
168 
169 /**
170  * Return true if history is used, false otherwise.  By default,
171  * history is off.
172  */
173 int
174 lshpack_enc_hist_used (const struct lshpack_enc *);
175 
176 /**
177  * Initialize HPACK decoder structure.
178  */
179 void
180 lshpack_dec_init (struct lshpack_dec *);
181 
182 /**
183  * Clean up HPACK decoder structure, freeing all allocated memory.
184  */
185 void
186 lshpack_dec_cleanup (struct lshpack_dec *);
187 
188 /*
189  * Returns 0 on success, a negative value on failure.
190  *
191  * If 0 is returned, `src' is advanced.  Calling with a zero-length input
192  * buffer results in an error.
193  *
194  * To calculate number of bytes written to the output buffer:
195  *  output->name_len + output->val_len + lshpack_dec_extra_bytes(dec)
196  */
197 int
198 lshpack_dec_decode (struct lshpack_dec *dec,
199     const unsigned char **src, const unsigned char *src_end,
200     struct lsxpack_header *output);
201 
202 /* Return number of extra bytes per header */
203 #if LSHPACK_DEC_HTTP1X_OUTPUT
204 #define LSHPACK_DEC_HTTP1X_EXTRA  (2)
205 #define lshpack_dec_extra_bytes(dec_) (4)
206 #else
207 #define LSHPACK_DEC_HTTP1X_EXTRA  (0)
208 #define lshpack_dec_extra_bytes(dec_) (0)
209 #endif
210 
211 void
212 lshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned);
213 
214 /* Some internals follow.  Struct definitions are exposed to save a malloc.
215  * These structures are not very complicated.
216  */
217 
218 #include <sys/queue.h>
219 
220 struct lshpack_enc_table_entry;
221 
222 STAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry);
223 struct lshpack_double_enc_head;
224 
225 struct lshpack_enc
226 {
227     unsigned            hpe_cur_capacity;
228     unsigned            hpe_max_capacity;
229 
230     /* Each new dynamic table entry gets the next number.  It is used to
231      * calculate the entry's position in the decoder table without having
232      * to maintain an actual array.
233      */
234     unsigned            hpe_next_id;
235 
236     /* Dynamic table entries (struct enc_table_entry) live in two hash
237      * tables: name/value hash table and name hash table.  These tables
238      * are the same size.
239      */
240     unsigned            hpe_nelem;
241     unsigned            hpe_nbits;
242     struct lshpack_enc_head
243                         hpe_all_entries;
244     struct lshpack_double_enc_head
245                        *hpe_buckets;
246 
247     uint32_t           *hpe_hist_buf;
248     unsigned            hpe_hist_size, hpe_hist_idx;
249     int                 hpe_hist_wrapped;
250     enum {
251         LSHPACK_ENC_USE_HIST    = 1 << 0,
252     }                   hpe_flags;
253 };
254 
255 struct lshpack_arr
256 {
257     unsigned        nalloc,
258                     nelem,
259                     off;
260     uintptr_t      *els;
261 };
262 
263 struct lshpack_dec
264 {
265     struct lshpack_arr hpd_dyn_table;
266     unsigned           hpd_max_capacity;       /* Maximum set by caller */
267     unsigned           hpd_cur_max_capacity;   /* Adjusted at runtime */
268     unsigned           hpd_cur_capacity;
269     unsigned           hpd_state;
270 };
271 
272 /* This function may update hash values and flags */
273 unsigned
274 lshpack_enc_get_stx_tab_id (struct lsxpack_header *);
275 
276 #ifdef __cplusplus
277 }
278 #endif
279 
280 #endif
281