1600751b9SDmitri Tikhonov#ifndef LSXPACK_HEADER_H_v206
2600751b9SDmitri Tikhonov#define LSXPACK_HEADER_H_v206
3226eedebSDmitri Tikhonov
4226eedebSDmitri Tikhonov#ifdef __cplusplus
5226eedebSDmitri Tikhonovextern "C" {
6226eedebSDmitri Tikhonov#endif
7226eedebSDmitri Tikhonov
8226eedebSDmitri Tikhonov#include <assert.h>
9226eedebSDmitri Tikhonov#include <stdint.h>
10226eedebSDmitri Tikhonov#include <string.h>
11226eedebSDmitri Tikhonov
12226eedebSDmitri Tikhonov#ifndef LSXPACK_MAX_STRLEN
13226eedebSDmitri Tikhonov#define LSXPACK_MAX_STRLEN UINT16_MAX
14226eedebSDmitri Tikhonov#endif
15226eedebSDmitri Tikhonov
16226eedebSDmitri Tikhonov#if LSXPACK_MAX_STRLEN == UINT16_MAX
17226eedebSDmitri Tikhonovtypedef uint16_t lsxpack_strlen_t;
18226eedebSDmitri Tikhonov#elif LSXPACK_MAX_STRLEN == UINT32_MAX
19226eedebSDmitri Tikhonovtypedef uint32_t lsxpack_strlen_t;
20226eedebSDmitri Tikhonov#else
21226eedebSDmitri Tikhonov#error unexpected LSXPACK_MAX_STRLEN
22226eedebSDmitri Tikhonov#endif
23226eedebSDmitri Tikhonov
24d3fda3e7SGeorge Wang#define LSXPACK_DEL  ((char *)NULL)
25d3fda3e7SGeorge Wang
26226eedebSDmitri Tikhonovenum lsxpack_flag
27226eedebSDmitri Tikhonov{
28600751b9SDmitri Tikhonov    LSXPACK_HPACK_VAL_MATCHED = 1,
29226eedebSDmitri Tikhonov    LSXPACK_QPACK_IDX = 2,
30226eedebSDmitri Tikhonov    LSXPACK_APP_IDX   = 4,
31226eedebSDmitri Tikhonov    LSXPACK_NAME_HASH = 8,
32226eedebSDmitri Tikhonov    LSXPACK_NAMEVAL_HASH = 16,
33226eedebSDmitri Tikhonov    LSXPACK_VAL_MATCHED = 32,
34226eedebSDmitri Tikhonov    LSXPACK_NEVER_INDEX = 64,
35226eedebSDmitri Tikhonov};
36226eedebSDmitri Tikhonov
37226eedebSDmitri Tikhonov/**
38226eedebSDmitri Tikhonov * When header are decoded, it should be stored to @buf starting from @name_offset,
39226eedebSDmitri Tikhonov *    <name>: <value>\r\n
40226eedebSDmitri Tikhonov * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters
41226eedebSDmitri Tikhonov * added.
42226eedebSDmitri Tikhonov *
43226eedebSDmitri Tikhonov * limitation: we currently does not support total header size > 64KB.
44226eedebSDmitri Tikhonov */
45226eedebSDmitri Tikhonov
46226eedebSDmitri Tikhonovstruct lsxpack_header
47226eedebSDmitri Tikhonov{
48226eedebSDmitri Tikhonov    char             *buf;          /* the buffer for headers */
49226eedebSDmitri Tikhonov    uint32_t          name_hash;    /* hash value for name */
50226eedebSDmitri Tikhonov    uint32_t          nameval_hash; /* hash value for name + value */
51226eedebSDmitri Tikhonov    lsxpack_strlen_t  name_offset;  /* the offset for name in the buffer */
52226eedebSDmitri Tikhonov    lsxpack_strlen_t  name_len;     /* the length of name */
53226eedebSDmitri Tikhonov    lsxpack_strlen_t  val_offset;   /* the offset for value in the buffer */
54226eedebSDmitri Tikhonov    lsxpack_strlen_t  val_len;      /* the length of value */
55d3fda3e7SGeorge Wang    uint16_t          chain_next_idx; /* mainly for cookie value chain */
56226eedebSDmitri Tikhonov    uint8_t           hpack_index;  /* HPACK static table index */
57226eedebSDmitri Tikhonov    uint8_t           qpack_index;  /* QPACK static table index */
58226eedebSDmitri Tikhonov    uint8_t           app_index;    /* APP header index */
59226eedebSDmitri Tikhonov    enum lsxpack_flag flags:8;      /* combination of lsxpack_flag */
60226eedebSDmitri Tikhonov    uint8_t           indexed_type; /* control to disable index or not */
61226eedebSDmitri Tikhonov    uint8_t           dec_overhead; /* num of extra bytes written to decoded buffer */
62226eedebSDmitri Tikhonov};
63226eedebSDmitri Tikhonov
64226eedebSDmitri Tikhonovtypedef struct lsxpack_header lsxpack_header_t;
65226eedebSDmitri Tikhonov
66226eedebSDmitri Tikhonov
67226eedebSDmitri Tikhonovstatic inline void
68226eedebSDmitri Tikhonovlsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
69226eedebSDmitri Tikhonov                       const char *val, size_t val_len)
70226eedebSDmitri Tikhonov{
71226eedebSDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
72226eedebSDmitri Tikhonov    hdr->buf = (char *)val;
73226eedebSDmitri Tikhonov    hdr->hpack_index = hpack_idx;
74226eedebSDmitri Tikhonov    assert(hpack_idx != 0);
75226eedebSDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
76226eedebSDmitri Tikhonov    hdr->val_len = val_len;
77226eedebSDmitri Tikhonov}
78226eedebSDmitri Tikhonov
79226eedebSDmitri Tikhonov
80226eedebSDmitri Tikhonovstatic inline void
81d3fda3e7SGeorge Wanglsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx,
82d3fda3e7SGeorge Wang                       const char *val, size_t val_len)
83d3fda3e7SGeorge Wang{
84d3fda3e7SGeorge Wang    memset(hdr, 0, sizeof(*hdr));
85d3fda3e7SGeorge Wang    hdr->buf = (char *)val;
86d3fda3e7SGeorge Wang    hdr->qpack_index = qpack_idx;
87d3fda3e7SGeorge Wang    assert(qpack_idx != -1);
88d3fda3e7SGeorge Wang    hdr->flags = LSXPACK_QPACK_IDX;
89d3fda3e7SGeorge Wang    assert(val_len <= LSXPACK_MAX_STRLEN);
90d3fda3e7SGeorge Wang    hdr->val_len = val_len;
91d3fda3e7SGeorge Wang}
92d3fda3e7SGeorge Wang
93d3fda3e7SGeorge Wang
94d3fda3e7SGeorge Wangstatic inline void
95226eedebSDmitri Tikhonovlsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf,
96226eedebSDmitri Tikhonov                          size_t name_offset, size_t name_len,
97226eedebSDmitri Tikhonov                          size_t val_len)
98226eedebSDmitri Tikhonov{
99226eedebSDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
100226eedebSDmitri Tikhonov    hdr->buf = (char *)buf;
101226eedebSDmitri Tikhonov    hdr->name_offset = name_offset;
102226eedebSDmitri Tikhonov    assert(name_len <= LSXPACK_MAX_STRLEN);
103226eedebSDmitri Tikhonov    hdr->name_len = name_len;
104226eedebSDmitri Tikhonov    assert(name_offset + name_len + 2 <= LSXPACK_MAX_STRLEN);
105226eedebSDmitri Tikhonov    hdr->val_offset = name_offset + name_len + 2;
106226eedebSDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
107226eedebSDmitri Tikhonov    hdr->val_len = val_len;
108226eedebSDmitri Tikhonov}
109226eedebSDmitri Tikhonov
110226eedebSDmitri Tikhonov
111226eedebSDmitri Tikhonovstatic inline void
112226eedebSDmitri Tikhonovlsxpack_header_set_offset2(lsxpack_header_t *hdr, const char *buf,
113226eedebSDmitri Tikhonov                           size_t name_offset, size_t name_len,
114226eedebSDmitri Tikhonov                           size_t val_offset, size_t val_len)
115226eedebSDmitri Tikhonov{
116226eedebSDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
117226eedebSDmitri Tikhonov    hdr->buf = (char *)buf;
118226eedebSDmitri Tikhonov    hdr->name_offset = name_offset;
119226eedebSDmitri Tikhonov    assert(name_len <= LSXPACK_MAX_STRLEN);
120226eedebSDmitri Tikhonov    hdr->name_len = name_len;
121226eedebSDmitri Tikhonov    assert(val_offset <= LSXPACK_MAX_STRLEN);
122226eedebSDmitri Tikhonov    hdr->val_offset = val_offset;
123226eedebSDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
124226eedebSDmitri Tikhonov    hdr->val_len = val_len;
125226eedebSDmitri Tikhonov}
126226eedebSDmitri Tikhonov
127226eedebSDmitri Tikhonov
128226eedebSDmitri Tikhonovstatic inline void
129226eedebSDmitri Tikhonovlsxpack_header_prepare_decode(lsxpack_header_t *hdr,
130226eedebSDmitri Tikhonov                              char *out, size_t offset, size_t len)
131226eedebSDmitri Tikhonov{
132226eedebSDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
133226eedebSDmitri Tikhonov    hdr->buf = out;
134226eedebSDmitri Tikhonov    assert(offset <= LSXPACK_MAX_STRLEN);
135226eedebSDmitri Tikhonov    hdr->name_offset = offset;
136226eedebSDmitri Tikhonov    if (len > LSXPACK_MAX_STRLEN)
137226eedebSDmitri Tikhonov        hdr->val_len = LSXPACK_MAX_STRLEN;
138226eedebSDmitri Tikhonov    else
139226eedebSDmitri Tikhonov        hdr->val_len = len;
140226eedebSDmitri Tikhonov}
141226eedebSDmitri Tikhonov
142226eedebSDmitri Tikhonov
143226eedebSDmitri Tikhonovstatic inline const char *
144226eedebSDmitri Tikhonovlsxpack_header_get_name(const lsxpack_header_t *hdr)
145226eedebSDmitri Tikhonov{
146600751b9SDmitri Tikhonov    return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL;
147226eedebSDmitri Tikhonov}
148226eedebSDmitri Tikhonov
149226eedebSDmitri Tikhonov
150226eedebSDmitri Tikhonovstatic inline const char *
151226eedebSDmitri Tikhonovlsxpack_header_get_value(const lsxpack_header_t *hdr)
152226eedebSDmitri Tikhonov{   return hdr->buf + hdr->val_offset;  }
153226eedebSDmitri Tikhonov
154226eedebSDmitri Tikhonovstatic inline size_t
155226eedebSDmitri Tikhonovlsxpack_header_get_dec_size(const lsxpack_header_t *hdr)
156226eedebSDmitri Tikhonov{   return hdr->name_len + hdr->val_len + hdr->dec_overhead;    }
157226eedebSDmitri Tikhonov
15892ff7cc6SGeorge Wangstatic inline void
15992ff7cc6SGeorge Wanglsxpack_header_mark_val_changed(lsxpack_header_t *hdr)
16092ff7cc6SGeorge Wang{
16192ff7cc6SGeorge Wang    hdr->flags = (enum lsxpack_flag)(hdr->flags &
162600751b9SDmitri Tikhonov       ~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
16392ff7cc6SGeorge Wang}
164226eedebSDmitri Tikhonov#ifdef __cplusplus
165226eedebSDmitri Tikhonov}
166226eedebSDmitri Tikhonov#endif
167226eedebSDmitri Tikhonov
168600751b9SDmitri Tikhonov#endif //LSXPACK_HEADER_H_v206
169