1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc.  See LICENSE. */
2fb3e20e0SDmitri Tikhonov#ifndef LSXPACK_HEADER_H_v206
3fb3e20e0SDmitri Tikhonov#define LSXPACK_HEADER_H_v206
4a5fa05f9SDmitri Tikhonov
5a5fa05f9SDmitri Tikhonov#ifdef __cplusplus
6a5fa05f9SDmitri Tikhonovextern "C" {
7a5fa05f9SDmitri Tikhonov#endif
8a5fa05f9SDmitri Tikhonov
9a5fa05f9SDmitri Tikhonov#include <assert.h>
10a5fa05f9SDmitri Tikhonov#include <stdint.h>
11a5fa05f9SDmitri Tikhonov#include <string.h>
12a5fa05f9SDmitri Tikhonov
13a5fa05f9SDmitri Tikhonov#ifndef LSXPACK_MAX_STRLEN
14a5fa05f9SDmitri Tikhonov#define LSXPACK_MAX_STRLEN UINT16_MAX
15a5fa05f9SDmitri Tikhonov#endif
16a5fa05f9SDmitri Tikhonov
17a5fa05f9SDmitri Tikhonov#if LSXPACK_MAX_STRLEN == UINT16_MAX
18a5fa05f9SDmitri Tikhonovtypedef uint16_t lsxpack_strlen_t;
19a5fa05f9SDmitri Tikhonov#elif LSXPACK_MAX_STRLEN == UINT32_MAX
20a5fa05f9SDmitri Tikhonovtypedef uint32_t lsxpack_strlen_t;
21a5fa05f9SDmitri Tikhonov#else
22a5fa05f9SDmitri Tikhonov#error unexpected LSXPACK_MAX_STRLEN
23a5fa05f9SDmitri Tikhonov#endif
24a5fa05f9SDmitri Tikhonov
2555613f44SDmitri Tikhonov#define LSXPACK_DEL  ((char *)NULL)
2655613f44SDmitri Tikhonov
27a5fa05f9SDmitri Tikhonovenum lsxpack_flag
28a5fa05f9SDmitri Tikhonov{
29fb3e20e0SDmitri Tikhonov    LSXPACK_HPACK_VAL_MATCHED = 1,
30a5fa05f9SDmitri Tikhonov    LSXPACK_QPACK_IDX = 2,
31a5fa05f9SDmitri Tikhonov    LSXPACK_APP_IDX   = 4,
32a5fa05f9SDmitri Tikhonov    LSXPACK_NAME_HASH = 8,
33a5fa05f9SDmitri Tikhonov    LSXPACK_NAMEVAL_HASH = 16,
34a5fa05f9SDmitri Tikhonov    LSXPACK_VAL_MATCHED = 32,
35a5fa05f9SDmitri Tikhonov    LSXPACK_NEVER_INDEX = 64,
36a5fa05f9SDmitri Tikhonov};
37a5fa05f9SDmitri Tikhonov
38a5fa05f9SDmitri Tikhonov/**
39a5fa05f9SDmitri Tikhonov * When header are decoded, it should be stored to @buf starting from @name_offset,
40a5fa05f9SDmitri Tikhonov *    <name>: <value>\r\n
41a5fa05f9SDmitri Tikhonov * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters
42a5fa05f9SDmitri Tikhonov * added.
43a5fa05f9SDmitri Tikhonov *
44a5fa05f9SDmitri Tikhonov * limitation: we currently does not support total header size > 64KB.
45a5fa05f9SDmitri Tikhonov */
46a5fa05f9SDmitri Tikhonov
47a5fa05f9SDmitri Tikhonovstruct lsxpack_header
48a5fa05f9SDmitri Tikhonov{
49a5fa05f9SDmitri Tikhonov    char             *buf;          /* the buffer for headers */
50a5fa05f9SDmitri Tikhonov    uint32_t          name_hash;    /* hash value for name */
51a5fa05f9SDmitri Tikhonov    uint32_t          nameval_hash; /* hash value for name + value */
52a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  name_offset;  /* the offset for name in the buffer */
53a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  name_len;     /* the length of name */
54a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  val_offset;   /* the offset for value in the buffer */
55a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  val_len;      /* the length of value */
5655613f44SDmitri Tikhonov    uint16_t          chain_next_idx; /* mainly for cookie value chain */
57a5fa05f9SDmitri Tikhonov    uint8_t           hpack_index;  /* HPACK static table index */
58a5fa05f9SDmitri Tikhonov    uint8_t           qpack_index;  /* QPACK static table index */
59a5fa05f9SDmitri Tikhonov    uint8_t           app_index;    /* APP header index */
60a5fa05f9SDmitri Tikhonov    enum lsxpack_flag flags:8;      /* combination of lsxpack_flag */
61a5fa05f9SDmitri Tikhonov    uint8_t           indexed_type; /* control to disable index or not */
62a5fa05f9SDmitri Tikhonov    uint8_t           dec_overhead; /* num of extra bytes written to decoded buffer */
63a5fa05f9SDmitri Tikhonov};
64a5fa05f9SDmitri Tikhonov
65a5fa05f9SDmitri Tikhonovtypedef struct lsxpack_header lsxpack_header_t;
66a5fa05f9SDmitri Tikhonov
67a5fa05f9SDmitri Tikhonov
68a5fa05f9SDmitri Tikhonovstatic inline void
69a5fa05f9SDmitri Tikhonovlsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
70a5fa05f9SDmitri Tikhonov                       const char *val, size_t val_len)
71a5fa05f9SDmitri Tikhonov{
72a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
73a5fa05f9SDmitri Tikhonov    hdr->buf = (char *)val;
74a5fa05f9SDmitri Tikhonov    hdr->hpack_index = hpack_idx;
75a5fa05f9SDmitri Tikhonov    assert(hpack_idx != 0);
76a5fa05f9SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
77a5fa05f9SDmitri Tikhonov    hdr->val_len = val_len;
78a5fa05f9SDmitri Tikhonov}
79a5fa05f9SDmitri Tikhonov
80a5fa05f9SDmitri Tikhonov
81a5fa05f9SDmitri Tikhonovstatic inline void
8255613f44SDmitri Tikhonovlsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx,
8355613f44SDmitri Tikhonov                       const char *val, size_t val_len)
8455613f44SDmitri Tikhonov{
8555613f44SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
8655613f44SDmitri Tikhonov    hdr->buf = (char *)val;
8755613f44SDmitri Tikhonov    hdr->qpack_index = qpack_idx;
8855613f44SDmitri Tikhonov    assert(qpack_idx != -1);
8955613f44SDmitri Tikhonov    hdr->flags = LSXPACK_QPACK_IDX;
9055613f44SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
9155613f44SDmitri Tikhonov    hdr->val_len = val_len;
9255613f44SDmitri Tikhonov}
9355613f44SDmitri Tikhonov
9455613f44SDmitri Tikhonov
9555613f44SDmitri Tikhonovstatic inline void
96a5fa05f9SDmitri Tikhonovlsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf,
97a5fa05f9SDmitri Tikhonov                          size_t name_offset, size_t name_len,
98a5fa05f9SDmitri Tikhonov                          size_t val_len)
99a5fa05f9SDmitri Tikhonov{
100a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
101a5fa05f9SDmitri Tikhonov    hdr->buf = (char *)buf;
102a5fa05f9SDmitri Tikhonov    hdr->name_offset = name_offset;
103a5fa05f9SDmitri Tikhonov    assert(name_len <= LSXPACK_MAX_STRLEN);
104a5fa05f9SDmitri Tikhonov    hdr->name_len = name_len;
105a5fa05f9SDmitri Tikhonov    assert(name_offset + name_len + 2 <= LSXPACK_MAX_STRLEN);
106a5fa05f9SDmitri Tikhonov    hdr->val_offset = name_offset + name_len + 2;
107a5fa05f9SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
108a5fa05f9SDmitri Tikhonov    hdr->val_len = val_len;
109a5fa05f9SDmitri Tikhonov}
110a5fa05f9SDmitri Tikhonov
111a5fa05f9SDmitri Tikhonov
112a5fa05f9SDmitri Tikhonovstatic inline void
113a5fa05f9SDmitri Tikhonovlsxpack_header_set_offset2(lsxpack_header_t *hdr, const char *buf,
114a5fa05f9SDmitri Tikhonov                           size_t name_offset, size_t name_len,
115a5fa05f9SDmitri Tikhonov                           size_t val_offset, size_t val_len)
116a5fa05f9SDmitri Tikhonov{
117a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
118a5fa05f9SDmitri Tikhonov    hdr->buf = (char *)buf;
119a5fa05f9SDmitri Tikhonov    hdr->name_offset = name_offset;
120a5fa05f9SDmitri Tikhonov    assert(name_len <= LSXPACK_MAX_STRLEN);
121a5fa05f9SDmitri Tikhonov    hdr->name_len = name_len;
122a5fa05f9SDmitri Tikhonov    assert(val_offset <= LSXPACK_MAX_STRLEN);
123a5fa05f9SDmitri Tikhonov    hdr->val_offset = val_offset;
124a5fa05f9SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
125a5fa05f9SDmitri Tikhonov    hdr->val_len = val_len;
126a5fa05f9SDmitri Tikhonov}
127a5fa05f9SDmitri Tikhonov
128a5fa05f9SDmitri Tikhonov
129a5fa05f9SDmitri Tikhonovstatic inline void
130a5fa05f9SDmitri Tikhonovlsxpack_header_prepare_decode(lsxpack_header_t *hdr,
131a5fa05f9SDmitri Tikhonov                              char *out, size_t offset, size_t len)
132a5fa05f9SDmitri Tikhonov{
133a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
134a5fa05f9SDmitri Tikhonov    hdr->buf = out;
135a5fa05f9SDmitri Tikhonov    assert(offset <= LSXPACK_MAX_STRLEN);
136a5fa05f9SDmitri Tikhonov    hdr->name_offset = offset;
137a5fa05f9SDmitri Tikhonov    if (len > LSXPACK_MAX_STRLEN)
138a5fa05f9SDmitri Tikhonov        hdr->val_len = LSXPACK_MAX_STRLEN;
139a5fa05f9SDmitri Tikhonov    else
140a5fa05f9SDmitri Tikhonov        hdr->val_len = len;
141a5fa05f9SDmitri Tikhonov}
142a5fa05f9SDmitri Tikhonov
143a5fa05f9SDmitri Tikhonov
144a5fa05f9SDmitri Tikhonovstatic inline const char *
145a5fa05f9SDmitri Tikhonovlsxpack_header_get_name(const lsxpack_header_t *hdr)
146a5fa05f9SDmitri Tikhonov{
147fb3e20e0SDmitri Tikhonov    return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL;
148a5fa05f9SDmitri Tikhonov}
149a5fa05f9SDmitri Tikhonov
150a5fa05f9SDmitri Tikhonov
151a5fa05f9SDmitri Tikhonovstatic inline const char *
152a5fa05f9SDmitri Tikhonovlsxpack_header_get_value(const lsxpack_header_t *hdr)
153a5fa05f9SDmitri Tikhonov{   return hdr->buf + hdr->val_offset;  }
154a5fa05f9SDmitri Tikhonov
155a5fa05f9SDmitri Tikhonovstatic inline size_t
156a5fa05f9SDmitri Tikhonovlsxpack_header_get_dec_size(const lsxpack_header_t *hdr)
157a5fa05f9SDmitri Tikhonov{   return hdr->name_len + hdr->val_len + hdr->dec_overhead;    }
158a5fa05f9SDmitri Tikhonov
15908c45823SDmitri Tikhonovstatic inline void
16008c45823SDmitri Tikhonovlsxpack_header_mark_val_changed(lsxpack_header_t *hdr)
16108c45823SDmitri Tikhonov{
16208c45823SDmitri Tikhonov    hdr->flags = (enum lsxpack_flag)(hdr->flags &
163fb3e20e0SDmitri Tikhonov       ~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
16408c45823SDmitri Tikhonov}
165a5fa05f9SDmitri Tikhonov#ifdef __cplusplus
166a5fa05f9SDmitri Tikhonov}
167a5fa05f9SDmitri Tikhonov#endif
168a5fa05f9SDmitri Tikhonov
169fb3e20e0SDmitri Tikhonov#endif //LSXPACK_HEADER_H_v206
170