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