lsxpack_header.h revision a5fa05f9
1a5fa05f9SDmitri Tikhonov/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2a5fa05f9SDmitri Tikhonov#ifndef LSXPACK_HEADER_H_v203
3a5fa05f9SDmitri Tikhonov#define LSXPACK_HEADER_H_v203
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
25a5fa05f9SDmitri Tikhonovenum lsxpack_flag
26a5fa05f9SDmitri Tikhonov{
27a5fa05f9SDmitri Tikhonov    LSXPACK_HPACK_IDX = 1,
28a5fa05f9SDmitri Tikhonov    LSXPACK_QPACK_IDX = 2,
29a5fa05f9SDmitri Tikhonov    LSXPACK_APP_IDX   = 4,
30a5fa05f9SDmitri Tikhonov    LSXPACK_NAME_HASH = 8,
31a5fa05f9SDmitri Tikhonov    LSXPACK_NAMEVAL_HASH = 16,
32a5fa05f9SDmitri Tikhonov    LSXPACK_VAL_MATCHED = 32,
33a5fa05f9SDmitri Tikhonov    LSXPACK_NEVER_INDEX = 64,
34a5fa05f9SDmitri Tikhonov};
35a5fa05f9SDmitri Tikhonov
36a5fa05f9SDmitri Tikhonov/**
37a5fa05f9SDmitri Tikhonov * When header are decoded, it should be stored to @buf starting from @name_offset,
38a5fa05f9SDmitri Tikhonov *    <name>: <value>\r\n
39a5fa05f9SDmitri Tikhonov * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters
40a5fa05f9SDmitri Tikhonov * added.
41a5fa05f9SDmitri Tikhonov *
42a5fa05f9SDmitri Tikhonov * limitation: we currently does not support total header size > 64KB.
43a5fa05f9SDmitri Tikhonov */
44a5fa05f9SDmitri Tikhonov
45a5fa05f9SDmitri Tikhonovstruct lsxpack_header
46a5fa05f9SDmitri Tikhonov{
47a5fa05f9SDmitri Tikhonov    char             *buf;          /* the buffer for headers */
48a5fa05f9SDmitri Tikhonov    const char       *name_ptr;     /* the name pointer can be optionally set for encoding */
49a5fa05f9SDmitri Tikhonov    uint32_t          name_hash;    /* hash value for name */
50a5fa05f9SDmitri Tikhonov    uint32_t          nameval_hash; /* hash value for name + value */
51a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  name_offset;  /* the offset for name in the buffer */
52a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  name_len;     /* the length of name */
53a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  val_offset;   /* the offset for value in the buffer */
54a5fa05f9SDmitri Tikhonov    lsxpack_strlen_t  val_len;      /* the length of value */
55a5fa05f9SDmitri Tikhonov    uint8_t           hpack_index;  /* HPACK static table index */
56a5fa05f9SDmitri Tikhonov    uint8_t           qpack_index;  /* QPACK static table index */
57a5fa05f9SDmitri Tikhonov    uint8_t           app_index;    /* APP header index */
58a5fa05f9SDmitri Tikhonov    enum lsxpack_flag flags:8;      /* combination of lsxpack_flag */
59a5fa05f9SDmitri Tikhonov    uint8_t           indexed_type; /* control to disable index or not */
60a5fa05f9SDmitri Tikhonov    uint8_t           dec_overhead; /* num of extra bytes written to decoded buffer */
61a5fa05f9SDmitri Tikhonov};
62a5fa05f9SDmitri Tikhonov
63a5fa05f9SDmitri Tikhonovtypedef struct lsxpack_header lsxpack_header_t;
64a5fa05f9SDmitri Tikhonov
65a5fa05f9SDmitri Tikhonov
66a5fa05f9SDmitri Tikhonovstatic inline void
67a5fa05f9SDmitri Tikhonovlsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
68a5fa05f9SDmitri Tikhonov                       const char *val, size_t val_len)
69a5fa05f9SDmitri Tikhonov{
70a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
71a5fa05f9SDmitri Tikhonov    hdr->buf = (char *)val;
72a5fa05f9SDmitri Tikhonov    hdr->hpack_index = hpack_idx;
73a5fa05f9SDmitri Tikhonov    assert(hpack_idx != 0);
74a5fa05f9SDmitri Tikhonov    hdr->flags = LSXPACK_HPACK_IDX;
75a5fa05f9SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
76a5fa05f9SDmitri Tikhonov    hdr->val_len = val_len;
77a5fa05f9SDmitri Tikhonov}
78a5fa05f9SDmitri Tikhonov
79a5fa05f9SDmitri Tikhonov
80a5fa05f9SDmitri Tikhonovstatic inline void
81a5fa05f9SDmitri Tikhonovlsxpack_header_set_ptr(lsxpack_header_t *hdr,
82a5fa05f9SDmitri Tikhonov                       const char *name, size_t name_len,
83a5fa05f9SDmitri Tikhonov                       const char *val, size_t val_len)
84a5fa05f9SDmitri Tikhonov{
85a5fa05f9SDmitri Tikhonov    memset(hdr, 0, sizeof(*hdr));
86a5fa05f9SDmitri Tikhonov    hdr->buf = (char *)val;
87a5fa05f9SDmitri Tikhonov    assert(val_len <= LSXPACK_MAX_STRLEN);
88a5fa05f9SDmitri Tikhonov    hdr->val_len = val_len;
89a5fa05f9SDmitri Tikhonov    hdr->name_ptr = name;
90a5fa05f9SDmitri Tikhonov    assert(name_len <= LSXPACK_MAX_STRLEN);
91a5fa05f9SDmitri Tikhonov    hdr->name_len = name_len;
92a5fa05f9SDmitri Tikhonov}
93a5fa05f9SDmitri Tikhonov
94a5fa05f9SDmitri Tikhonov
95a5fa05f9SDmitri 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{
147a5fa05f9SDmitri Tikhonov    return hdr->name_ptr ? hdr->name_ptr
148a5fa05f9SDmitri Tikhonov                         : (hdr->name_len) ? hdr->buf + hdr->name_offset
149a5fa05f9SDmitri Tikhonov                                           : NULL;
150a5fa05f9SDmitri Tikhonov}
151a5fa05f9SDmitri Tikhonov
152a5fa05f9SDmitri Tikhonov
153a5fa05f9SDmitri Tikhonovstatic inline const char *
154a5fa05f9SDmitri Tikhonovlsxpack_header_get_value(const lsxpack_header_t *hdr)
155a5fa05f9SDmitri Tikhonov{   return hdr->buf + hdr->val_offset;  }
156a5fa05f9SDmitri Tikhonov
157a5fa05f9SDmitri Tikhonovstatic inline size_t
158a5fa05f9SDmitri Tikhonovlsxpack_header_get_dec_size(const lsxpack_header_t *hdr)
159a5fa05f9SDmitri Tikhonov{   return hdr->name_len + hdr->val_len + hdr->dec_overhead;    }
160a5fa05f9SDmitri Tikhonov
161a5fa05f9SDmitri Tikhonov#ifdef __cplusplus
162a5fa05f9SDmitri Tikhonov}
163a5fa05f9SDmitri Tikhonov#endif
164a5fa05f9SDmitri Tikhonov
165a5fa05f9SDmitri Tikhonov#endif //LSXPACK_HEADER_H_v203
166