1aba8e86eSDmitri Tikhonov/*
2aba8e86eSDmitri TikhonovMIT License
3aba8e86eSDmitri Tikhonov
4d4b9b92cSGeorge WangCopyright (c) 2018 - 2021 LiteSpeed Technologies Inc
5aba8e86eSDmitri Tikhonov
6aba8e86eSDmitri TikhonovPermission is hereby granted, free of charge, to any person obtaining a copy
7aba8e86eSDmitri Tikhonovof this software and associated documentation files (the "Software"), to deal
8aba8e86eSDmitri Tikhonovin the Software without restriction, including without limitation the rights
9aba8e86eSDmitri Tikhonovto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10aba8e86eSDmitri Tikhonovcopies of the Software, and to permit persons to whom the Software is
11aba8e86eSDmitri Tikhonovfurnished to do so, subject to the following conditions:
12aba8e86eSDmitri Tikhonov
13aba8e86eSDmitri TikhonovThe above copyright notice and this permission notice shall be included in all
14aba8e86eSDmitri Tikhonovcopies or substantial portions of the Software.
15aba8e86eSDmitri Tikhonov
16aba8e86eSDmitri TikhonovTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17aba8e86eSDmitri TikhonovIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18aba8e86eSDmitri TikhonovFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19aba8e86eSDmitri TikhonovAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20aba8e86eSDmitri TikhonovLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21aba8e86eSDmitri TikhonovOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22aba8e86eSDmitri TikhonovSOFTWARE.
23aba8e86eSDmitri Tikhonov*/
24aba8e86eSDmitri Tikhonov
25868e25b9SDmitri Tikhonov#ifndef LITESPEED_HPACK_H
26868e25b9SDmitri Tikhonov#define LITESPEED_HPACK_H 1
27868e25b9SDmitri Tikhonov
28868e25b9SDmitri Tikhonov#ifdef __cplusplus
29868e25b9SDmitri Tikhonovextern "C" {
30868e25b9SDmitri Tikhonov#endif
31868e25b9SDmitri Tikhonov
32226eedebSDmitri Tikhonov#include <limits.h>
33868e25b9SDmitri Tikhonov#include <stdint.h>
34c298a38cSGlenn Strauss#include "lsxpack_header.h"
35868e25b9SDmitri Tikhonov
36226eedebSDmitri Tikhonov#define LSHPACK_MAJOR_VERSION 2
37d4b9b92cSGeorge Wang#define LSHPACK_MINOR_VERSION 3
38d4b9b92cSGeorge Wang#define LSHPACK_PATCH_VERSION 0
395ed13cadSDmitri Tikhonov
40226eedebSDmitri Tikhonov#define lshpack_strlen_t lsxpack_strlen_t
41226eedebSDmitri Tikhonov#define LSHPACK_MAX_STRLEN LSXPACK_MAX_STRLEN
42868e25b9SDmitri Tikhonov
43600751b9SDmitri Tikhonov#ifndef LSHPACK_DEC_HTTP1X_OUTPUT
44600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_OUTPUT 1
45600751b9SDmitri Tikhonov#endif
46600751b9SDmitri Tikhonov#ifndef LSHPACK_DEC_CALC_HASH
47600751b9SDmitri Tikhonov#define LSHPACK_DEC_CALC_HASH 1
48600751b9SDmitri Tikhonov#endif
49600751b9SDmitri Tikhonov
50868e25b9SDmitri Tikhonovstruct lshpack_enc;
51868e25b9SDmitri Tikhonovstruct lshpack_dec;
52868e25b9SDmitri Tikhonov
53226eedebSDmitri Tikhonovenum lshpack_static_hdr_idx
54226eedebSDmitri Tikhonov{
55226eedebSDmitri Tikhonov    LSHPACK_HDR_UNKNOWN,
56226eedebSDmitri Tikhonov    LSHPACK_HDR_AUTHORITY,
57226eedebSDmitri Tikhonov    LSHPACK_HDR_METHOD_GET,
58226eedebSDmitri Tikhonov    LSHPACK_HDR_METHOD_POST,
59226eedebSDmitri Tikhonov    LSHPACK_HDR_PATH,
60226eedebSDmitri Tikhonov    LSHPACK_HDR_PATH_INDEX_HTML,
61226eedebSDmitri Tikhonov    LSHPACK_HDR_SCHEME_HTTP,
62226eedebSDmitri Tikhonov    LSHPACK_HDR_SCHEME_HTTPS,
63226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_200,
64226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_204,
65226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_206,
66226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_304,
67226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_400,
68226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_404,
69226eedebSDmitri Tikhonov    LSHPACK_HDR_STATUS_500,
70226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCEPT_CHARSET,
71226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCEPT_ENCODING,
72226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCEPT_LANGUAGE,
73226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCEPT_RANGES,
74226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCEPT,
75226eedebSDmitri Tikhonov    LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN,
76226eedebSDmitri Tikhonov    LSHPACK_HDR_AGE,
77226eedebSDmitri Tikhonov    LSHPACK_HDR_ALLOW,
78226eedebSDmitri Tikhonov    LSHPACK_HDR_AUTHORIZATION,
79226eedebSDmitri Tikhonov    LSHPACK_HDR_CACHE_CONTROL,
80226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_DISPOSITION,
81226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_ENCODING,
82226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_LANGUAGE,
83226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_LENGTH,
84226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_LOCATION,
85226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_RANGE,
86226eedebSDmitri Tikhonov    LSHPACK_HDR_CONTENT_TYPE,
87226eedebSDmitri Tikhonov    LSHPACK_HDR_COOKIE,
88226eedebSDmitri Tikhonov    LSHPACK_HDR_DATE,
89226eedebSDmitri Tikhonov    LSHPACK_HDR_ETAG,
90226eedebSDmitri Tikhonov    LSHPACK_HDR_EXPECT,
91226eedebSDmitri Tikhonov    LSHPACK_HDR_EXPIRES,
92226eedebSDmitri Tikhonov    LSHPACK_HDR_FROM,
93226eedebSDmitri Tikhonov    LSHPACK_HDR_HOST,
94226eedebSDmitri Tikhonov    LSHPACK_HDR_IF_MATCH,
95226eedebSDmitri Tikhonov    LSHPACK_HDR_IF_MODIFIED_SINCE,
96226eedebSDmitri Tikhonov    LSHPACK_HDR_IF_NONE_MATCH,
97226eedebSDmitri Tikhonov    LSHPACK_HDR_IF_RANGE,
98226eedebSDmitri Tikhonov    LSHPACK_HDR_IF_UNMODIFIED_SINCE,
99226eedebSDmitri Tikhonov    LSHPACK_HDR_LAST_MODIFIED,
100226eedebSDmitri Tikhonov    LSHPACK_HDR_LINK,
101226eedebSDmitri Tikhonov    LSHPACK_HDR_LOCATION,
102226eedebSDmitri Tikhonov    LSHPACK_HDR_MAX_FORWARDS,
103226eedebSDmitri Tikhonov    LSHPACK_HDR_PROXY_AUTHENTICATE,
104226eedebSDmitri Tikhonov    LSHPACK_HDR_PROXY_AUTHORIZATION,
105226eedebSDmitri Tikhonov    LSHPACK_HDR_RANGE,
106226eedebSDmitri Tikhonov    LSHPACK_HDR_REFERER,
107226eedebSDmitri Tikhonov    LSHPACK_HDR_REFRESH,
108226eedebSDmitri Tikhonov    LSHPACK_HDR_RETRY_AFTER,
109226eedebSDmitri Tikhonov    LSHPACK_HDR_SERVER,
110226eedebSDmitri Tikhonov    LSHPACK_HDR_SET_COOKIE,
111226eedebSDmitri Tikhonov    LSHPACK_HDR_STRICT_TRANSPORT_SECURITY,
112226eedebSDmitri Tikhonov    LSHPACK_HDR_TRANSFER_ENCODING,
113226eedebSDmitri Tikhonov    LSHPACK_HDR_USER_AGENT,
114226eedebSDmitri Tikhonov    LSHPACK_HDR_VARY,
115226eedebSDmitri Tikhonov    LSHPACK_HDR_VIA,
116600751b9SDmitri Tikhonov    LSHPACK_HDR_WWW_AUTHENTICATE,
117600751b9SDmitri Tikhonov    LSHPACK_HDR_TOBE_INDEXED = 255
118226eedebSDmitri Tikhonov};
119226eedebSDmitri Tikhonov
12054378593SGeorge Wang#define LSHPACK_MAX_INDEX           61
12154378593SGeorge Wang
122226eedebSDmitri Tikhonov#define LSHPACK_ERR_MORE_BUF        (-3)
123226eedebSDmitri Tikhonov#define LSHPACK_ERR_TOO_LARGE       (-2)
124226eedebSDmitri Tikhonov#define LSHPACK_ERR_BAD_DATA        (-1)
125226eedebSDmitri Tikhonov#define LSHPACK_OK                  (0)
126226eedebSDmitri Tikhonov
127868e25b9SDmitri Tikhonov/**
128868e25b9SDmitri Tikhonov * Initialization routine allocates memory.  -1 is returned if memory
129868e25b9SDmitri Tikhonov * could not be allocated.  0 is returned on success.
130868e25b9SDmitri Tikhonov */
131868e25b9SDmitri Tikhonovint
132868e25b9SDmitri Tikhonovlshpack_enc_init (struct lshpack_enc *);
133868e25b9SDmitri Tikhonov
134868e25b9SDmitri Tikhonov/**
135868e25b9SDmitri Tikhonov * Clean up HPACK encoder, freeing all allocated memory.
136868e25b9SDmitri Tikhonov */
137868e25b9SDmitri Tikhonovvoid
138868e25b9SDmitri Tikhonovlshpack_enc_cleanup (struct lshpack_enc *);
139868e25b9SDmitri Tikhonov
140868e25b9SDmitri Tikhonov/**
141868e25b9SDmitri Tikhonov * @brief Encode one name/value pair
142868e25b9SDmitri Tikhonov *
143868e25b9SDmitri Tikhonov * @param[in,out] henc - A pointer to a valid HPACK API struct
144868e25b9SDmitri Tikhonov * @param[out] dst - A pointer to destination buffer
145868e25b9SDmitri Tikhonov * @param[out] dst_end - A pointer to end of destination buffer
146226eedebSDmitri Tikhonov * @param[in] input - Header to encode
147868e25b9SDmitri Tikhonov *
148868e25b9SDmitri Tikhonov * @return The (possibly advanced) dst pointer.  If the destination
149868e25b9SDmitri Tikhonov * pointer was not advanced, an error must have occurred.
150868e25b9SDmitri Tikhonov */
151868e25b9SDmitri Tikhonovunsigned char *
152868e25b9SDmitri Tikhonovlshpack_enc_encode (struct lshpack_enc *henc, unsigned char *dst,
153226eedebSDmitri Tikhonov        unsigned char *dst_end, struct lsxpack_header *input);
154868e25b9SDmitri Tikhonov
155868e25b9SDmitri Tikhonovvoid
156868e25b9SDmitri Tikhonovlshpack_enc_set_max_capacity (struct lshpack_enc *, unsigned);
157868e25b9SDmitri Tikhonov
158868e25b9SDmitri Tikhonov/**
15972061d40SDmitri Tikhonov * Turn history on or off.  Turning history on may fail (malloc), in
16072061d40SDmitri Tikhonov * which case -1 is returned.
16172061d40SDmitri Tikhonov */
16272061d40SDmitri Tikhonovint
16372061d40SDmitri Tikhonovlshpack_enc_use_hist (struct lshpack_enc *, int on);
16472061d40SDmitri Tikhonov
16572061d40SDmitri Tikhonov/**
16672061d40SDmitri Tikhonov * Return true if history is used, false otherwise.  By default,
16772061d40SDmitri Tikhonov * history is off.
16872061d40SDmitri Tikhonov */
16972061d40SDmitri Tikhonovint
17072061d40SDmitri Tikhonovlshpack_enc_hist_used (const struct lshpack_enc *);
17172061d40SDmitri Tikhonov
17272061d40SDmitri Tikhonov/**
173868e25b9SDmitri Tikhonov * Initialize HPACK decoder structure.
174868e25b9SDmitri Tikhonov */
175868e25b9SDmitri Tikhonovvoid
176600751b9SDmitri Tikhonovlshpack_dec_init (struct lshpack_dec *);
177868e25b9SDmitri Tikhonov
178868e25b9SDmitri Tikhonov/**
179868e25b9SDmitri Tikhonov * Clean up HPACK decoder structure, freeing all allocated memory.
180868e25b9SDmitri Tikhonov */
181868e25b9SDmitri Tikhonovvoid
182868e25b9SDmitri Tikhonovlshpack_dec_cleanup (struct lshpack_dec *);
183868e25b9SDmitri Tikhonov
184868e25b9SDmitri Tikhonov/*
185868e25b9SDmitri Tikhonov * Returns 0 on success, a negative value on failure.
186868e25b9SDmitri Tikhonov *
187868e25b9SDmitri Tikhonov * If 0 is returned, `src' is advanced.  Calling with a zero-length input
188868e25b9SDmitri Tikhonov * buffer results in an error.
189226eedebSDmitri Tikhonov *
190226eedebSDmitri Tikhonov * To calculate number of bytes written to the output buffer:
191226eedebSDmitri Tikhonov *  output->name_len + output->val_len + lshpack_dec_extra_bytes(dec)
192868e25b9SDmitri Tikhonov */
193868e25b9SDmitri Tikhonovint
194868e25b9SDmitri Tikhonovlshpack_dec_decode (struct lshpack_dec *dec,
195868e25b9SDmitri Tikhonov    const unsigned char **src, const unsigned char *src_end,
196226eedebSDmitri Tikhonov    struct lsxpack_header *output);
197226eedebSDmitri Tikhonov
198226eedebSDmitri Tikhonov/* Return number of extra bytes per header */
199600751b9SDmitri Tikhonov#if LSHPACK_DEC_HTTP1X_OUTPUT
200600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_EXTRA  (2)
201600751b9SDmitri Tikhonov#define lshpack_dec_extra_bytes(dec_) (4)
202600751b9SDmitri Tikhonov#else
203600751b9SDmitri Tikhonov#define LSHPACK_DEC_HTTP1X_EXTRA  (0)
204600751b9SDmitri Tikhonov#define lshpack_dec_extra_bytes(dec_) (0)
205600751b9SDmitri Tikhonov#endif
206868e25b9SDmitri Tikhonov
207868e25b9SDmitri Tikhonovvoid
208868e25b9SDmitri Tikhonovlshpack_dec_set_max_capacity (struct lshpack_dec *, unsigned);
209868e25b9SDmitri Tikhonov
210868e25b9SDmitri Tikhonov/* Some internals follow.  Struct definitions are exposed to save a malloc.
211868e25b9SDmitri Tikhonov * These structures are not very complicated.
212868e25b9SDmitri Tikhonov */
213868e25b9SDmitri Tikhonov
214868e25b9SDmitri Tikhonov#include <sys/queue.h>
215868e25b9SDmitri Tikhonov
2165459745fSGlenn Strauss#ifdef __OpenBSD__
2175459745fSGlenn Strauss#define STAILQ_HEAD             SIMPLEQ_HEAD
2185459745fSGlenn Strauss#define STAILQ_ENTRY            SIMPLEQ_ENTRY
2195459745fSGlenn Strauss#define STAILQ_INIT             SIMPLEQ_INIT
2205459745fSGlenn Strauss#define STAILQ_INSERT_TAIL      SIMPLEQ_INSERT_TAIL
2215459745fSGlenn Strauss#define STAILQ_EMPTY            SIMPLEQ_EMPTY
2225459745fSGlenn Strauss#define STAILQ_FIRST            SIMPLEQ_FIRST
2235459745fSGlenn Strauss#define STAILQ_NEXT             SIMPLEQ_NEXT
2245459745fSGlenn Strauss#define STAILQ_REMOVE_HEAD      SIMPLEQ_REMOVE_HEAD
2255459745fSGlenn Strauss#define STAILQ_FOREACH          SIMPLEQ_FOREACH
2265459745fSGlenn Strauss#endif
2275459745fSGlenn Strauss
2283ba42754SDmitri Tikhonovstruct lshpack_enc_table_entry;
229868e25b9SDmitri Tikhonov
2303ba42754SDmitri TikhonovSTAILQ_HEAD(lshpack_enc_head, lshpack_enc_table_entry);
2313ba42754SDmitri Tikhonovstruct lshpack_double_enc_head;
232868e25b9SDmitri Tikhonov
233868e25b9SDmitri Tikhonovstruct lshpack_enc
234868e25b9SDmitri Tikhonov{
235868e25b9SDmitri Tikhonov    unsigned            hpe_cur_capacity;
236868e25b9SDmitri Tikhonov    unsigned            hpe_max_capacity;
237868e25b9SDmitri Tikhonov
238868e25b9SDmitri Tikhonov    /* Each new dynamic table entry gets the next number.  It is used to
239868e25b9SDmitri Tikhonov     * calculate the entry's position in the decoder table without having
240868e25b9SDmitri Tikhonov     * to maintain an actual array.
241868e25b9SDmitri Tikhonov     */
242868e25b9SDmitri Tikhonov    unsigned            hpe_next_id;
243868e25b9SDmitri Tikhonov
244868e25b9SDmitri Tikhonov    /* Dynamic table entries (struct enc_table_entry) live in two hash
245868e25b9SDmitri Tikhonov     * tables: name/value hash table and name hash table.  These tables
246868e25b9SDmitri Tikhonov     * are the same size.
247868e25b9SDmitri Tikhonov     */
248868e25b9SDmitri Tikhonov    unsigned            hpe_nelem;
249868e25b9SDmitri Tikhonov    unsigned            hpe_nbits;
2503ba42754SDmitri Tikhonov    struct lshpack_enc_head
2513ba42754SDmitri Tikhonov                        hpe_all_entries;
2523ba42754SDmitri Tikhonov    struct lshpack_double_enc_head
253868e25b9SDmitri Tikhonov                       *hpe_buckets;
25472061d40SDmitri Tikhonov
25572061d40SDmitri Tikhonov    uint32_t           *hpe_hist_buf;
25672061d40SDmitri Tikhonov    unsigned            hpe_hist_size, hpe_hist_idx;
25772061d40SDmitri Tikhonov    int                 hpe_hist_wrapped;
25872061d40SDmitri Tikhonov    enum {
25972061d40SDmitri Tikhonov        LSHPACK_ENC_USE_HIST    = 1 << 0,
26072061d40SDmitri Tikhonov    }                   hpe_flags;
261868e25b9SDmitri Tikhonov};
262868e25b9SDmitri Tikhonov
263868e25b9SDmitri Tikhonovstruct lshpack_arr
264868e25b9SDmitri Tikhonov{
265868e25b9SDmitri Tikhonov    unsigned        nalloc,
266868e25b9SDmitri Tikhonov                    nelem,
267868e25b9SDmitri Tikhonov                    off;
268868e25b9SDmitri Tikhonov    uintptr_t      *els;
269868e25b9SDmitri Tikhonov};
270868e25b9SDmitri Tikhonov
271868e25b9SDmitri Tikhonovstruct lshpack_dec
272868e25b9SDmitri Tikhonov{
273226eedebSDmitri Tikhonov    struct lshpack_arr hpd_dyn_table;
274868e25b9SDmitri Tikhonov    unsigned           hpd_max_capacity;       /* Maximum set by caller */
275868e25b9SDmitri Tikhonov    unsigned           hpd_cur_max_capacity;   /* Adjusted at runtime */
276868e25b9SDmitri Tikhonov    unsigned           hpd_cur_capacity;
277226eedebSDmitri Tikhonov    unsigned           hpd_state;
278868e25b9SDmitri Tikhonov};
279868e25b9SDmitri Tikhonov
280226eedebSDmitri Tikhonov/* This function may update hash values and flags */
281226eedebSDmitri Tikhonovunsigned
282226eedebSDmitri Tikhonovlshpack_enc_get_stx_tab_id (struct lsxpack_header *);
283fa385e06SDmitri Tikhonov
284868e25b9SDmitri Tikhonov#ifdef __cplusplus
285868e25b9SDmitri Tikhonov}
286868e25b9SDmitri Tikhonov#endif
287868e25b9SDmitri Tikhonov
288868e25b9SDmitri Tikhonov#endif
289