summaryrefslogtreecommitdiff
path: root/src/ls-hpack/lsxpack_header.h
blob: 1f7a0058df9f3da60f2ca18cc6efaca370a597a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#ifndef LSXPACK_HEADER_H_v207
#define LSXPACK_HEADER_H_v207

#ifdef __cplusplus
extern "C" {
#endif

#include <assert.h>
#include <stdint.h>
#include <string.h>

#ifndef LSXPACK_MAX_STRLEN
#define LSXPACK_MAX_STRLEN UINT16_MAX
#endif

#if LSXPACK_MAX_STRLEN == UINT16_MAX
typedef uint16_t lsxpack_strlen_t;
#elif LSXPACK_MAX_STRLEN == UINT32_MAX
typedef uint32_t lsxpack_strlen_t;
#else
#error unexpected LSXPACK_MAX_STRLEN
#endif

#define LSXPACK_DEL  ((char *)NULL)

enum lsxpack_flag
{
    LSXPACK_HPACK_VAL_MATCHED = 1,
    LSXPACK_QPACK_IDX = 2,
    LSXPACK_APP_IDX   = 4,
    LSXPACK_NAME_HASH = 8,
    LSXPACK_NAMEVAL_HASH = 16,
    LSXPACK_VAL_MATCHED = 32,
    LSXPACK_NEVER_INDEX = 64,
};

/**
 * When header are decoded, it should be stored to @buf starting from @name_offset,
 *    <name>: <value>\r\n
 * So, it can be used directly as HTTP/1.1 header. there are 4 extra characters
 * added.
 *
 * limitation: we currently does not support total header size > 64KB.
 */

struct lsxpack_header
{
    char             *buf;          /* the buffer for headers */
    uint32_t          name_hash;    /* hash value for name */
    uint32_t          nameval_hash; /* hash value for name + value */
    lsxpack_strlen_t  name_offset;  /* the offset for name in the buffer */
    lsxpack_strlen_t  name_len;     /* the length of name */
    lsxpack_strlen_t  val_offset;   /* the offset for value in the buffer */
    lsxpack_strlen_t  val_len;      /* the length of value */
    uint16_t          chain_next_idx; /* mainly for cookie value chain */
    uint8_t           hpack_index;  /* HPACK static table index */
    uint8_t           qpack_index;  /* QPACK static table index */
    uint8_t           app_index;    /* APP header index */
    enum lsxpack_flag flags:8;      /* combination of lsxpack_flag */
    uint8_t           indexed_type; /* control to disable index or not */
    uint8_t           dec_overhead; /* num of extra bytes written to decoded buffer */
};

typedef struct lsxpack_header lsxpack_header_t;


static inline void
lsxpack_header_set_idx(lsxpack_header_t *hdr, int hpack_idx,
                       const char *val, size_t val_len)
{
    memset(hdr, 0, sizeof(*hdr));
    hdr->buf = (char *)val;
    hdr->hpack_index = (uint8_t)hpack_idx;
    assert(hpack_idx != 0);
    assert(val_len <= LSXPACK_MAX_STRLEN);
    hdr->val_len = (lsxpack_strlen_t)val_len;
}


static inline void
lsxpack_header_set_qpack_idx(lsxpack_header_t *hdr, int qpack_idx,
                       const char *val, size_t val_len)
{
    memset(hdr, 0, sizeof(*hdr));
    hdr->buf = (char *)val;
    hdr->qpack_index = (uint8_t)qpack_idx;
    assert(qpack_idx != -1);
    hdr->flags = LSXPACK_QPACK_IDX;
    assert(val_len <= LSXPACK_MAX_STRLEN);
    hdr->val_len = (lsxpack_strlen_t)val_len;
}


static inline void
lsxpack_header_set_offset(lsxpack_header_t *hdr, const char *buf,
                          size_t name_offset, size_t name_len,
                          size_t val_len)
{
    memset(hdr, 0, sizeof(*hdr));
    hdr->buf = (char *)buf;
    hdr->name_offset = (lsxpack_strlen_t)name_offset;
    assert(name_len <= LSXPACK_MAX_STRLEN);
    hdr->name_len = (lsxpack_strlen_t)name_len;
    assert(name_offset + name_len + 2 <= LSXPACK_MAX_STRLEN);
    hdr->val_offset = (lsxpack_strlen_t)(name_offset + name_len + 2);
    assert(val_len <= LSXPACK_MAX_STRLEN);
    hdr->val_len = (lsxpack_strlen_t)val_len;
}


static inline void
lsxpack_header_set_offset2(lsxpack_header_t *hdr, const char *buf,
                           size_t name_offset, size_t name_len,
                           size_t val_offset, size_t val_len)
{
    memset(hdr, 0, sizeof(*hdr));
    hdr->buf = (char *)buf;
    hdr->name_offset = (lsxpack_strlen_t)name_offset;
    assert(name_len <= LSXPACK_MAX_STRLEN);
    hdr->name_len = (lsxpack_strlen_t)name_len;
    assert(val_offset <= LSXPACK_MAX_STRLEN);
    hdr->val_offset = (lsxpack_strlen_t)val_offset;
    assert(val_len <= LSXPACK_MAX_STRLEN);
    hdr->val_len = (lsxpack_strlen_t)val_len;
}


static inline void
lsxpack_header_prepare_decode(lsxpack_header_t *hdr,
                              char *out, size_t offset, size_t len)
{
    memset(hdr, 0, sizeof(*hdr));
    hdr->buf = out;
    assert(offset <= LSXPACK_MAX_STRLEN);
    hdr->name_offset = (lsxpack_strlen_t)offset;
    if (len > LSXPACK_MAX_STRLEN)
        hdr->val_len = LSXPACK_MAX_STRLEN;
    else
        hdr->val_len = (lsxpack_strlen_t)len;
}


static inline const char *
lsxpack_header_get_name(const lsxpack_header_t *hdr)
{
    return (hdr->name_len)? hdr->buf + hdr->name_offset : NULL;
}


static inline const char *
lsxpack_header_get_value(const lsxpack_header_t *hdr)
{   return hdr->buf + hdr->val_offset;  }

static inline size_t
lsxpack_header_get_dec_size(const lsxpack_header_t *hdr)
{   return hdr->name_len + hdr->val_len + hdr->dec_overhead;    }

static inline void
lsxpack_header_mark_val_changed(lsxpack_header_t *hdr)
{
    hdr->flags = (enum lsxpack_flag)(hdr->flags &
       ~(LSXPACK_HPACK_VAL_MATCHED|LSXPACK_VAL_MATCHED|LSXPACK_NAMEVAL_HASH));
}
#ifdef __cplusplus
}
#endif

#endif //LSXPACK_HEADER_H_v207