1#ifndef LSXPACK_HEADER_H_v206
2#define LSXPACK_HEADER_H_v206
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <assert.h>
9#include <stdint.h>
10#include <string.h>
11
12#ifndef LSXPACK_MAX_STRLEN
13#define LSXPACK_MAX_STRLEN UINT16_MAX
14#endif
15
16#if LSXPACK_MAX_STRLEN == UINT16_MAX
17typedef uint16_t lsxpack_strlen_t;
18#elif LSXPACK_MAX_STRLEN == UINT32_MAX
19typedef uint32_t lsxpack_strlen_t;
20#else
21#error unexpected LSXPACK_MAX_STRLEN
22#endif
23
24#define LSXPACK_DEL  ((char *)NULL)
25
26enum lsxpack_flag
27{
28    LSXPACK_HPACK_VAL_MATCHED = 1,
29    LSXPACK_QPACK_IDX = 2,
30    LSXPACK_APP_IDX   = 4,
31    LSXPACK_NAME_HASH = 8,
32    LSXPACK_NAMEVAL_HASH = 16,
33    LSXPACK_VAL_MATCHED = 32,
34    LSXPACK_NEVER_INDEX = 64,
35};
36
37/**
38 * When header are decoded, it should be stored to @buf starting from @name_offset,
39 *    <name>: <value>\r\n
40 * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters
41 * added.
42 *
43 * limitation: we currently does not support total header size > 64KB.
44 */
45
46struct lsxpack_header
47{
48    char             *buf;          /* the buffer for headers */
49    uint32_t          name_hash;    /* hash value for name */
50    uint32_t          nameval_hash; /* hash value for name + value */
51    lsxpack_strlen_t  name_offset;  /* the offset for name in the buffer */
52    lsxpack_strlen_t  name_len;     /* the length of name */
53    lsxpack_strlen_t  val_offset;   /* the offset for value in the buffer */
54    lsxpack_strlen_t  val_len;      /* the length of value */
55    uint16_t          chain_next_idx; /* mainly for cookie value chain */
56    uint8_t           hpack_index;  /* HPACK static table index */
57    uint8_t           qpack_index;  /* QPACK static table index */
58    uint8_t           app_index;    /* APP header index */
59    enum lsxpack_flag flags:8;      /* combination of lsxpack_flag */
60    uint8_t           indexed_type; /* control to disable index or not */
61    uint8_t           dec_overhead; /* num of extra bytes written to decoded buffer */
62};
63
64typedef struct lsxpack_header lsxpack_header_t;
65
66
67static inline void
68lsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
69                       const char *val, size_t val_len)
70{
71    memset(hdr, 0, sizeof(*hdr));
72    hdr->buf = (char *)val;
73    hdr->hpack_index = hpack_idx;
74    assert(hpack_idx != 0);
75    assert(val_len <= LSXPACK_MAX_STRLEN);
76    hdr->val_len = val_len;
77}
78
79
80static inline void
81lsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx,
82                       const char *val, size_t val_len)
83{
84    memset(hdr, 0, sizeof(*hdr));
85    hdr->buf = (char *)val;
86    hdr->qpack_index = qpack_idx;
87    assert(qpack_idx != -1);
88    hdr->flags = LSXPACK_QPACK_IDX;
89    assert(val_len <= LSXPACK_MAX_STRLEN);
90    hdr->val_len = val_len;
91}
92
93
94static inline void
95lsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf,
96                          size_t name_offset, size_t name_len,
97                          size_t val_len)
98{
99    memset(hdr, 0, sizeof(*hdr));
100    hdr->buf = (char *)buf;
101    hdr->name_offset = name_offset;
102    assert(name_len <= LSXPACK_MAX_STRLEN);
103    hdr->name_len = name_len;
104    assert(name_offset + name_len + 2 <= LSXPACK_MAX_STRLEN);
105    hdr->val_offset = name_offset + name_len + 2;
106    assert(val_len <= LSXPACK_MAX_STRLEN);
107    hdr->val_len = val_len;
108}
109
110
111static inline void
112lsxpack_header_set_offset2(lsxpack_header_t *hdr, const char *buf,
113                           size_t name_offset, size_t name_len,
114                           size_t val_offset, size_t val_len)
115{
116    memset(hdr, 0, sizeof(*hdr));
117    hdr->buf = (char *)buf;
118    hdr->name_offset = name_offset;
119    assert(name_len <= LSXPACK_MAX_STRLEN);
120    hdr->name_len = name_len;
121    assert(val_offset <= LSXPACK_MAX_STRLEN);
122    hdr->val_offset = val_offset;
123    assert(val_len <= LSXPACK_MAX_STRLEN);
124    hdr->val_len = val_len;
125}
126
127
128static inline void
129lsxpack_header_prepare_decode(lsxpack_header_t *hdr,
130                              char *out, size_t offset, size_t len)
131{
132    memset(hdr, 0, sizeof(*hdr));
133    hdr->buf = out;
134    assert(offset <= LSXPACK_MAX_STRLEN);
135    hdr->name_offset = offset;
136    if (len > LSXPACK_MAX_STRLEN)
137        hdr->val_len = LSXPACK_MAX_STRLEN;
138    else
139        hdr->val_len = len;
140}
141
142
143static inline const char *
144lsxpack_header_get_name(const lsxpack_header_t *hdr)
145{
146    return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL;
147}
148
149
150static inline const char *
151lsxpack_header_get_value(const lsxpack_header_t *hdr)
152{   return hdr->buf + hdr->val_offset;  }
153
154static inline size_t
155lsxpack_header_get_dec_size(const lsxpack_header_t *hdr)
156{   return hdr->name_len + hdr->val_len + hdr->dec_overhead;    }
157
158static inline void
159lsxpack_header_mark_val_changed(lsxpack_header_t *hdr)
160{
161    hdr->flags = (enum lsxpack_flag)(hdr->flags &
162       ~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
163}
164#ifdef __cplusplus
165}
166#endif
167
168#endif //LSXPACK_HEADER_H_v206
169