corecdtl 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +50 -0
- package/binding.gyp +14 -0
- package/native/http/core/http_core.cpp +395 -0
- package/native/http/core/http_core.h +90 -0
- package/native/http/core/http_scanner.cpp +1501 -0
- package/native/http/core/http_scanner.h +474 -0
- package/native/http/cpool/cpool.cpp +284 -0
- package/native/http/cpool/cpool.h +39 -0
- package/native/http/parser/asset_meta.cpp +31 -0
- package/native/http/parser/asset_meta.h +53 -0
- package/native/http/parser/asset_parser.cpp +52 -0
- package/native/http/parser/asset_parser.h +20 -0
- package/native/http/routes/route.h +85 -0
- package/native/http/routes/route_builder.cpp +161 -0
- package/native/http/routes/route_matching.cpp +267 -0
- package/native/http/routes/route_print.cpp +20 -0
- package/native/main.cpp +54 -0
- package/package.json +5 -11
- package/build/Release/hypernode.node +0 -0
|
@@ -0,0 +1,1501 @@
|
|
|
1
|
+
#include <string>
|
|
2
|
+
#include <napi.h>
|
|
3
|
+
#include <iostream>
|
|
4
|
+
#include <string_view>
|
|
5
|
+
#include <cstring>
|
|
6
|
+
#include <cctype>
|
|
7
|
+
#include <cstdint>
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <algorithm>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
#include "http_core.h"
|
|
13
|
+
#include "http_scanner.h"
|
|
14
|
+
|
|
15
|
+
using namespace HttpScanner;
|
|
16
|
+
|
|
17
|
+
static inline uint8_t ascii_lower(uint8_t c) {
|
|
18
|
+
return (c >= 'A' && c <= 'Z') ? (c | 0x20) : c;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static inline uint64_t load_u64(const char* p) {
|
|
22
|
+
uint64_t v;
|
|
23
|
+
__builtin_memcpy(&v, p, sizeof(v));
|
|
24
|
+
return v;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static inline uint64_t ascii_lower_u64(uint64_t v) {
|
|
28
|
+
return v | 0x2020202020202020ULL;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static inline uint128_t ascii_lower_u128(uint128_t v) {
|
|
32
|
+
#if SIMD_SSE2
|
|
33
|
+
return _mm_or_si128(v, _mm_set1_epi8(0x20));
|
|
34
|
+
#elif SIMD_NEON
|
|
35
|
+
return vorrq_u8(v, vdupq_n_u8(0x20));
|
|
36
|
+
#endif
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static inline uint128_t load_u128(const char* p) {
|
|
40
|
+
#if SIMD_SSE2
|
|
41
|
+
return _mm_loadu_si128((const __m128i*)p);
|
|
42
|
+
#elif SIMD_NEON
|
|
43
|
+
return vld1q_u8(reinterpret_cast<const uint8_t*>(p));
|
|
44
|
+
#endif
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static inline uint128_t load_const128(const Pack128& p) {
|
|
48
|
+
#if SIMD_SSE2
|
|
49
|
+
return _mm_set_epi64x(p.hi, p.lo);
|
|
50
|
+
#elif SIMD_NEON
|
|
51
|
+
return vcombine_u8(vcreate_u8(p.lo), vcreate_u8(p.hi));
|
|
52
|
+
#endif
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
static inline bool simd_eq_n(
|
|
57
|
+
uint128_t a, uint128_t b, unsigned n
|
|
58
|
+
) {
|
|
59
|
+
#if SIMD_SSE2
|
|
60
|
+
__m128i mask = mask128_sse(n);
|
|
61
|
+
__m128i diff = _mm_xor_si128(a, b);
|
|
62
|
+
diff = _mm_and_si128(diff, mask);
|
|
63
|
+
return _mm_movemask_epi8(diff) == 0;
|
|
64
|
+
#elif SIMD_NEON
|
|
65
|
+
uint8x16_t mask = mask128_neon(n);
|
|
66
|
+
uint8x16_t diff = veorq_u8(a, b);
|
|
67
|
+
diff = vandq_u8(diff, mask);
|
|
68
|
+
return vmaxvq_u8(diff) == 0;
|
|
69
|
+
#endif
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static inline bool is_hn_delim(char c) {
|
|
73
|
+
return (c == ':' || c == '-' || c == ' ');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
inline constexpr bool hv_is_valid_char(unsigned char c) {
|
|
77
|
+
// HTAB or SP
|
|
78
|
+
if (c == 9 || c == 32) return true;
|
|
79
|
+
|
|
80
|
+
// Visible ASCII
|
|
81
|
+
return (c >= 33 && c <= 126);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
enum State {
|
|
85
|
+
ST_STARTUP,
|
|
86
|
+
ST_HN_SPACE,
|
|
87
|
+
ST_HN_UNKNOWN,
|
|
88
|
+
ST_HN_H,
|
|
89
|
+
ST_HN_A,
|
|
90
|
+
ST_HN_C,
|
|
91
|
+
ST_HN_D,
|
|
92
|
+
ST_HN_I,
|
|
93
|
+
ST_HN_L,
|
|
94
|
+
ST_HN_O,
|
|
95
|
+
ST_HN_P,
|
|
96
|
+
ST_HN_R,
|
|
97
|
+
ST_HN_S,
|
|
98
|
+
ST_HN_T,
|
|
99
|
+
ST_HN_U,
|
|
100
|
+
ST_HN_V,
|
|
101
|
+
ST_HN_W,
|
|
102
|
+
ST_HN_X,
|
|
103
|
+
ST_HV_CONCAT
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
FlagBits HttpScanner::hv_get_value_number(
|
|
107
|
+
const char* __restrict buf,
|
|
108
|
+
uint32_t* __restrict __offset,
|
|
109
|
+
size_t total,
|
|
110
|
+
uint32_t maxHeaderValueSize,
|
|
111
|
+
std::unique_ptr<std::string>& hv
|
|
112
|
+
) {
|
|
113
|
+
size_t valueBegin = *__offset;
|
|
114
|
+
size_t valueEnd = *__offset;
|
|
115
|
+
bool seen_digit = false;
|
|
116
|
+
|
|
117
|
+
while (true) {
|
|
118
|
+
if (*__offset >= total) {
|
|
119
|
+
return FLAG_UNTERMINATED_HEADERS;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (*__offset - valueBegin > maxHeaderValueSize)
|
|
123
|
+
return FLAG_MAX_HEADER_VALUE_SIZE;
|
|
124
|
+
|
|
125
|
+
unsigned char c = (unsigned char)buf[*__offset];
|
|
126
|
+
|
|
127
|
+
// ---- Stop at line end ----
|
|
128
|
+
if (c == '\r' || c == '\n')
|
|
129
|
+
break;
|
|
130
|
+
|
|
131
|
+
// ---- Digit or trailing OWS only ----
|
|
132
|
+
if (c >= '0' && c <= '9') {
|
|
133
|
+
seen_digit = true;
|
|
134
|
+
valueEnd = *__offset + 1;
|
|
135
|
+
} else if (c == ' ' || c == '\t') {
|
|
136
|
+
// trailing OWS allowed, do not extend valueEnd
|
|
137
|
+
(*__offset)++;
|
|
138
|
+
while (true) {
|
|
139
|
+
if (*__offset >= total)
|
|
140
|
+
return FLAG_UNTERMINATED_HEADERS;
|
|
141
|
+
|
|
142
|
+
unsigned char c = (unsigned char)buf[*__offset];
|
|
143
|
+
if (c == '\r' || c == '\n')
|
|
144
|
+
break;
|
|
145
|
+
|
|
146
|
+
if (c != ' ' && c != '\t' )
|
|
147
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
148
|
+
|
|
149
|
+
(*__offset)++;
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
} else
|
|
153
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
154
|
+
|
|
155
|
+
(*__offset)++;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!seen_digit)
|
|
159
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
160
|
+
|
|
161
|
+
// ---- Copy value (trimmed) ----
|
|
162
|
+
hv->assign(buf + valueBegin, valueEnd - valueBegin);
|
|
163
|
+
|
|
164
|
+
return FLAG_OK;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
FlagBits HttpScanner::hv_get_value_any(
|
|
168
|
+
const char* __restrict buf,
|
|
169
|
+
uint32_t* __restrict __offset,
|
|
170
|
+
size_t total,
|
|
171
|
+
uint32_t maxHeaderValueSize,
|
|
172
|
+
std::unique_ptr<std::string>& hv
|
|
173
|
+
) {
|
|
174
|
+
size_t valueBegin = *__offset;
|
|
175
|
+
size_t valueEnd = *__offset;
|
|
176
|
+
|
|
177
|
+
while (true) {
|
|
178
|
+
if (*__offset >= total)
|
|
179
|
+
return FLAG_UNTERMINATED_HEADERS;
|
|
180
|
+
|
|
181
|
+
if (*__offset - valueBegin > maxHeaderValueSize)
|
|
182
|
+
return FLAG_MAX_HEADER_VALUE_SIZE;
|
|
183
|
+
|
|
184
|
+
unsigned char c = (unsigned char)buf[*__offset];
|
|
185
|
+
// ---- Stop at line end ----
|
|
186
|
+
if (c == '\r' || c == '\n')
|
|
187
|
+
break;
|
|
188
|
+
|
|
189
|
+
// ---- RFC-safe value char validation ----
|
|
190
|
+
if (c < 32 && c != '\t')
|
|
191
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
192
|
+
if (c == 127)
|
|
193
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
194
|
+
if (!hv_is_valid_char(c))
|
|
195
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
196
|
+
|
|
197
|
+
// ---- Trim trailing OWS ----
|
|
198
|
+
if (c != ' ' && c != '\t')
|
|
199
|
+
valueEnd = *__offset + 1;
|
|
200
|
+
|
|
201
|
+
(*__offset)++;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ---- Copy value (trimmed) ----
|
|
205
|
+
hv->assign(buf + valueBegin, valueEnd - valueBegin);
|
|
206
|
+
|
|
207
|
+
return FLAG_OK;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
FlagBits scanHeaders(
|
|
211
|
+
Napi::Env env, const char* buf, size_t total, uint32_t* offset,
|
|
212
|
+
uint32_t maxHeaderSize, uint32_t maxHeaderNameSize, uint32_t maxHeaderValueSize,
|
|
213
|
+
uint32_t currentHeaderSize, MethodType method, Napi::Object* outHeaders
|
|
214
|
+
) {
|
|
215
|
+
if (*offset + 1 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
216
|
+
|
|
217
|
+
uint32_t __offset = *offset;
|
|
218
|
+
ssize_t vStart = 0;
|
|
219
|
+
HeaderId hdrId = HDR_UNKNOWN;
|
|
220
|
+
bool hdrMergeable = false;
|
|
221
|
+
std::string headerUnknownName;
|
|
222
|
+
State state = ST_STARTUP;
|
|
223
|
+
|
|
224
|
+
while (true) {
|
|
225
|
+
if (__offset >= total && state != ST_HV_CONCAT)
|
|
226
|
+
break;
|
|
227
|
+
|
|
228
|
+
switch (state) {
|
|
229
|
+
|
|
230
|
+
// ================= STARTUP =================
|
|
231
|
+
case ST_STARTUP: {
|
|
232
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
233
|
+
|
|
234
|
+
if (__offset > maxHeaderSize) return FLAG_MAX_HEADER_SIZE;
|
|
235
|
+
|
|
236
|
+
switch (buf[__offset]) {
|
|
237
|
+
case 'a': case 'A':
|
|
238
|
+
vStart = __offset;
|
|
239
|
+
__offset++;
|
|
240
|
+
state = ST_HN_A;
|
|
241
|
+
continue;
|
|
242
|
+
case 'c': case 'C':
|
|
243
|
+
vStart = __offset;
|
|
244
|
+
__offset++;
|
|
245
|
+
state = ST_HN_C;
|
|
246
|
+
continue;
|
|
247
|
+
case 'd': case 'D':
|
|
248
|
+
vStart = __offset;
|
|
249
|
+
__offset++;
|
|
250
|
+
state = ST_HN_D;
|
|
251
|
+
continue;
|
|
252
|
+
case 'i': case 'I':
|
|
253
|
+
vStart = __offset;
|
|
254
|
+
__offset++;
|
|
255
|
+
state = ST_HN_I;
|
|
256
|
+
continue;
|
|
257
|
+
case 'l': case 'L':
|
|
258
|
+
vStart = __offset;
|
|
259
|
+
__offset++;
|
|
260
|
+
state = ST_HN_L;
|
|
261
|
+
continue;
|
|
262
|
+
case 'o': case 'O':
|
|
263
|
+
vStart = __offset;
|
|
264
|
+
__offset++;
|
|
265
|
+
state = ST_HN_O;
|
|
266
|
+
continue;
|
|
267
|
+
case 'p': case 'P':
|
|
268
|
+
vStart = __offset;
|
|
269
|
+
__offset++;
|
|
270
|
+
state = ST_HN_P;
|
|
271
|
+
continue;
|
|
272
|
+
case 'r': case 'R':
|
|
273
|
+
vStart = __offset;
|
|
274
|
+
__offset++;
|
|
275
|
+
state = ST_HN_R;
|
|
276
|
+
continue;
|
|
277
|
+
case 's': case 'S':
|
|
278
|
+
vStart = __offset;
|
|
279
|
+
__offset++;
|
|
280
|
+
state = ST_HN_S;
|
|
281
|
+
continue;
|
|
282
|
+
case 't': case 'T':
|
|
283
|
+
vStart = __offset;
|
|
284
|
+
__offset++;
|
|
285
|
+
state = ST_HN_T;
|
|
286
|
+
continue;
|
|
287
|
+
case 'u': case 'U':
|
|
288
|
+
vStart = __offset;
|
|
289
|
+
__offset++;
|
|
290
|
+
state = ST_HN_U;
|
|
291
|
+
continue;
|
|
292
|
+
case 'v': case 'V':
|
|
293
|
+
vStart = __offset;
|
|
294
|
+
__offset++;
|
|
295
|
+
state = ST_HN_V;
|
|
296
|
+
continue;
|
|
297
|
+
case 'w': case 'W':
|
|
298
|
+
vStart = __offset;
|
|
299
|
+
__offset++;
|
|
300
|
+
state = ST_HN_W;
|
|
301
|
+
continue;
|
|
302
|
+
case 'x': case 'X':
|
|
303
|
+
vStart = __offset;
|
|
304
|
+
__offset++;
|
|
305
|
+
state = ST_HN_X;
|
|
306
|
+
continue;
|
|
307
|
+
case 'h': case 'H':
|
|
308
|
+
vStart = __offset;
|
|
309
|
+
__offset++;
|
|
310
|
+
state = ST_HN_H;
|
|
311
|
+
continue;
|
|
312
|
+
|
|
313
|
+
default:
|
|
314
|
+
vStart = __offset;
|
|
315
|
+
state = ST_HN_UNKNOWN;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ================= SPACE =================
|
|
321
|
+
case ST_HN_SPACE: {
|
|
322
|
+
__offset++;
|
|
323
|
+
state = ST_HV_CONCAT;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// ================= UNKNOWN =================
|
|
328
|
+
case ST_HN_UNKNOWN: {
|
|
329
|
+
while (true) {
|
|
330
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
331
|
+
|
|
332
|
+
char c = buf[__offset];
|
|
333
|
+
if (c == ':') {
|
|
334
|
+
__offset++;
|
|
335
|
+
hdrId = HDR_UNKNOWN;
|
|
336
|
+
headerUnknownName.assign(buf + vStart, __offset - vStart - 1);
|
|
337
|
+
std::transform(headerUnknownName.begin(), headerUnknownName.end(), headerUnknownName.begin(),
|
|
338
|
+
[](unsigned char c){ return std::tolower(c); });
|
|
339
|
+
state = ST_HV_CONCAT;
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
if (c == ' ' || c == '\t') {
|
|
343
|
+
return FLAG_INVALID_HEADER;
|
|
344
|
+
}
|
|
345
|
+
unsigned char uc = (unsigned char)c;
|
|
346
|
+
if (uc < 33 || uc > 126) {
|
|
347
|
+
return FLAG_INVALID_HEADER;
|
|
348
|
+
}
|
|
349
|
+
__offset++;
|
|
350
|
+
if (__offset - vStart > maxHeaderNameSize) return FLAG_MAX_HEADER_NAME_SIZE;
|
|
351
|
+
}
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// ================= H =================
|
|
356
|
+
case ST_HN_H: {
|
|
357
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
358
|
+
|
|
359
|
+
uint64_t v = load_u64(buf + __offset);
|
|
360
|
+
uint64_t lv = ascii_lower_u64(v);
|
|
361
|
+
if ((lv & MASK_U64_3BYTE) == PACK8("ost")) {
|
|
362
|
+
__offset += 3;
|
|
363
|
+
if (buf[__offset] == ':') {
|
|
364
|
+
if (outHeaders->Has("host"))
|
|
365
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
366
|
+
hdrId = HDR_HOST;
|
|
367
|
+
state = ST_HN_SPACE;
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
state = ST_HN_UNKNOWN;
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// ================= A =================
|
|
376
|
+
case ST_HN_A: {
|
|
377
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
378
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
379
|
+
|
|
380
|
+
// accept*
|
|
381
|
+
if (lv == 'c') {
|
|
382
|
+
|
|
383
|
+
if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
384
|
+
|
|
385
|
+
uint64_t w = load_u64(buf + (++__offset));
|
|
386
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
387
|
+
|
|
388
|
+
// "cept"
|
|
389
|
+
if ((lw & MASK_U64_4BYTE) == PACK8("cept")) {
|
|
390
|
+
__offset += 4;
|
|
391
|
+
|
|
392
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
393
|
+
|
|
394
|
+
char c = buf[__offset];
|
|
395
|
+
// --------------------
|
|
396
|
+
// ACCEPT (plain)
|
|
397
|
+
// --------------------
|
|
398
|
+
if (c == ':' || c == ' ' || c == '\t') {
|
|
399
|
+
hdrId = HDR_ACCEPT;
|
|
400
|
+
state = ST_HN_SPACE;
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// --------------------
|
|
405
|
+
// ACCEPT-*
|
|
406
|
+
// --------------------
|
|
407
|
+
if (c == '-') {
|
|
408
|
+
if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
409
|
+
|
|
410
|
+
uint8_t n = ascii_lower(buf[++__offset]);
|
|
411
|
+
|
|
412
|
+
// accept-language
|
|
413
|
+
if (n == 'l') {
|
|
414
|
+
w = load_u64(buf + (__offset + 1));
|
|
415
|
+
lw = ascii_lower_u64(w);
|
|
416
|
+
if ((lw & MASK_U64_7BYTE) == PACK8("anguage")) {
|
|
417
|
+
__offset += 8;
|
|
418
|
+
if (buf[__offset] == ':') {
|
|
419
|
+
hdrMergeable = true;
|
|
420
|
+
hdrId = HDR_ACCEPT_LANGUAGE;
|
|
421
|
+
state = ST_HN_SPACE;
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
// accept-encoding
|
|
427
|
+
else if (n == 'e') {
|
|
428
|
+
w = load_u64(buf + (__offset + 1));
|
|
429
|
+
lw = ascii_lower_u64(w);
|
|
430
|
+
if ((lw & MASK_U64_7BYTE) == PACK8("ncoding")) {
|
|
431
|
+
__offset += 8;
|
|
432
|
+
if (buf[__offset] == ':') {
|
|
433
|
+
hdrMergeable = true;
|
|
434
|
+
hdrId = HDR_ACCEPT_ENCODING;
|
|
435
|
+
state = ST_HN_SPACE;
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
// accept-ranges
|
|
441
|
+
else if (n == 'r') {
|
|
442
|
+
w = load_u64(buf + (__offset + 1));
|
|
443
|
+
lw = ascii_lower_u64(w);
|
|
444
|
+
if ((lw & MASK_U64_5BYTE) == PACK8("anges")) {
|
|
445
|
+
__offset += 6;
|
|
446
|
+
if (buf[__offset] == ':') {
|
|
447
|
+
hdrMergeable = true;
|
|
448
|
+
hdrId = HDR_ACCEPT_RANGES;
|
|
449
|
+
state = ST_HN_SPACE;
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// allow
|
|
459
|
+
else if (lv == 'l') {
|
|
460
|
+
uint64_t w = load_u64(buf + __offset);
|
|
461
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
462
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("low")) {
|
|
463
|
+
__offset += 4;
|
|
464
|
+
if (buf[__offset] == ':') {
|
|
465
|
+
hdrMergeable = true;
|
|
466
|
+
hdrId = HDR_ALLOW;
|
|
467
|
+
state = ST_HN_SPACE;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// authorization
|
|
474
|
+
else if (lv == 'u') {
|
|
475
|
+
if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
476
|
+
Pack128 P_THORIZATION = PACK16_11('t','h','o','r','i','z','a','t','i','o','n');
|
|
477
|
+
__offset++;
|
|
478
|
+
uint128_t v = load_u128(buf + (__offset));
|
|
479
|
+
v = ascii_lower_u128(v);
|
|
480
|
+
if (simd_eq_n(v, load_const128(P_THORIZATION), 11)) {
|
|
481
|
+
__offset += 11;
|
|
482
|
+
if (buf[__offset] == ':') {
|
|
483
|
+
if (outHeaders->Has("authorization"))
|
|
484
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
485
|
+
|
|
486
|
+
hdrId = HDR_AUTHORIZATION;
|
|
487
|
+
state = ST_HN_SPACE;
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
state = ST_HN_UNKNOWN;
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ================= C =================
|
|
498
|
+
case ST_HN_C: {
|
|
499
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
500
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
501
|
+
|
|
502
|
+
// -------------------------------------------------
|
|
503
|
+
// ca* → cache-control
|
|
504
|
+
// -------------------------------------------------
|
|
505
|
+
if (lv == 'a') {
|
|
506
|
+
if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
507
|
+
|
|
508
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
509
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
510
|
+
|
|
511
|
+
// "che-cont"
|
|
512
|
+
if (lw == PACK8("che-cont")) {
|
|
513
|
+
w = load_u64(buf + (__offset + 9));
|
|
514
|
+
lw = ascii_lower_u64(w);
|
|
515
|
+
|
|
516
|
+
// "rol"
|
|
517
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("rol")) {
|
|
518
|
+
__offset += 12;
|
|
519
|
+
if (buf[__offset] == ':') {
|
|
520
|
+
hdrMergeable = true;
|
|
521
|
+
hdrId = HDR_CACHE_CONTROL;
|
|
522
|
+
state = ST_HN_SPACE;
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// -------------------------------------------------
|
|
530
|
+
// co*
|
|
531
|
+
// -------------------------------------------------
|
|
532
|
+
else if (lv == 'o') {
|
|
533
|
+
if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
534
|
+
uint8_t n = ascii_lower(buf[++__offset]);
|
|
535
|
+
|
|
536
|
+
// ---------------------------------------------
|
|
537
|
+
// coo* → cookie
|
|
538
|
+
// ---------------------------------------------
|
|
539
|
+
if (n == 'o') {
|
|
540
|
+
if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
541
|
+
|
|
542
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
543
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
544
|
+
|
|
545
|
+
// "kie"
|
|
546
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("kie")) {
|
|
547
|
+
__offset += 4;
|
|
548
|
+
if (buf[__offset] == ':') {
|
|
549
|
+
hdrId = HDR_COOKIE;
|
|
550
|
+
state = ST_HN_SPACE;
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// ---------------------------------------------
|
|
557
|
+
// con*
|
|
558
|
+
// ---------------------------------------------
|
|
559
|
+
else if (n == 'n') {
|
|
560
|
+
if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
561
|
+
uint8_t t = ascii_lower(buf[++__offset]);
|
|
562
|
+
|
|
563
|
+
// -----------------------------------------
|
|
564
|
+
// conn* → connection
|
|
565
|
+
// -----------------------------------------
|
|
566
|
+
if (t == 'n') {
|
|
567
|
+
if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
568
|
+
|
|
569
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
570
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
571
|
+
|
|
572
|
+
// "ection"
|
|
573
|
+
if ((lw & MASK_U64_6BYTE) == PACK8("ection")) {
|
|
574
|
+
__offset += 7;
|
|
575
|
+
if (buf[__offset] == ':') {
|
|
576
|
+
hdrMergeable = true;
|
|
577
|
+
hdrId = HDR_CONNECTION;
|
|
578
|
+
state = ST_HN_SPACE;
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// -----------------------------------------
|
|
585
|
+
// cont* → content-*
|
|
586
|
+
// -----------------------------------------
|
|
587
|
+
else if (t == 't') {
|
|
588
|
+
if (__offset + 4 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
589
|
+
__offset++;
|
|
590
|
+
uint64_t w = load_u64(buf + (__offset));
|
|
591
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
592
|
+
// "ent-"
|
|
593
|
+
if ((lw & MASK_U64_4BYTE) == PACK8("ent-")) {
|
|
594
|
+
__offset += 4;
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
598
|
+
uint8_t k = ascii_lower(buf[__offset]);
|
|
599
|
+
|
|
600
|
+
// content-length
|
|
601
|
+
if (k == 'l') {
|
|
602
|
+
w = load_u64(buf + (__offset + 1));
|
|
603
|
+
lw = ascii_lower_u64(w);
|
|
604
|
+
if ((lw & MASK_U64_5BYTE) == PACK8("ength")) {
|
|
605
|
+
__offset += 6;
|
|
606
|
+
if (buf[__offset] == ':') {
|
|
607
|
+
if (outHeaders->Has("content-length"))
|
|
608
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
609
|
+
if (outHeaders->Has("transfer-encoding"))
|
|
610
|
+
return FLAG_BAD_REQUEST;
|
|
611
|
+
|
|
612
|
+
hdrId = HDR_CONTENT_LENGTH;
|
|
613
|
+
state = ST_HN_SPACE;
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// content-type
|
|
619
|
+
else if (k == 't') {
|
|
620
|
+
w = load_u64(buf + (__offset + 1));
|
|
621
|
+
lw = ascii_lower_u64(w);
|
|
622
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("ype")) {
|
|
623
|
+
__offset += 4;
|
|
624
|
+
if (buf[__offset] == ':') {
|
|
625
|
+
if (outHeaders->Has("content-type"))
|
|
626
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
627
|
+
hdrId = HDR_CONTENT_TYPE;
|
|
628
|
+
state = ST_HN_SPACE;
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
// content-range
|
|
634
|
+
else if (k == 'r') {
|
|
635
|
+
w = load_u64(buf + (__offset + 1));
|
|
636
|
+
lw = ascii_lower_u64(w);
|
|
637
|
+
if ((lw & MASK_U64_4BYTE) == PACK8("ange")) {
|
|
638
|
+
__offset += 5;
|
|
639
|
+
if (buf[__offset] == ':') {
|
|
640
|
+
if (outHeaders->Has("content-range"))
|
|
641
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
642
|
+
hdrId = HDR_CONTENT_RANGE;
|
|
643
|
+
state = ST_HN_SPACE;
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
state = ST_HN_UNKNOWN;
|
|
653
|
+
break;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// ================= D =================
|
|
657
|
+
case ST_HN_D: {
|
|
658
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
659
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
660
|
+
|
|
661
|
+
// -------------------------------------------------
|
|
662
|
+
// da* → date
|
|
663
|
+
// -------------------------------------------------
|
|
664
|
+
if (lv == 'a') {
|
|
665
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
666
|
+
uint32_t w =
|
|
667
|
+
(uint32_t)(ascii_lower(buf[__offset + 1]) << 16) |
|
|
668
|
+
(uint32_t)(ascii_lower(buf[__offset + 2]) << 8);
|
|
669
|
+
|
|
670
|
+
// "te"
|
|
671
|
+
if (w == (('t' << 16) | ('e' << 8))) {
|
|
672
|
+
__offset += 3;
|
|
673
|
+
if (buf[__offset] == ':') {
|
|
674
|
+
if (outHeaders->Has("date"))
|
|
675
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
676
|
+
hdrId = HDR_DATE;
|
|
677
|
+
state = ST_HN_SPACE;
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// -------------------------------------------------
|
|
684
|
+
// dn* → dnt
|
|
685
|
+
// -------------------------------------------------
|
|
686
|
+
else if (lv == 'n') {
|
|
687
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
688
|
+
|
|
689
|
+
uint16_t w = ascii_lower(buf[__offset + 1]);
|
|
690
|
+
// "t"
|
|
691
|
+
if (w == 't') {
|
|
692
|
+
__offset += 2;
|
|
693
|
+
if (buf[__offset] == ':') {
|
|
694
|
+
hdrId = HDR_DNT;
|
|
695
|
+
state = ST_HN_SPACE;
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
state = ST_HN_UNKNOWN;
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// ================= I =================
|
|
706
|
+
case ST_HN_I: {
|
|
707
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
708
|
+
|
|
709
|
+
uint64_t w = load_u64(buf + __offset);
|
|
710
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
711
|
+
// -------------------------------------------------
|
|
712
|
+
// if-n → if-none-match
|
|
713
|
+
// -------------------------------------------------
|
|
714
|
+
if (lw == PACK8("f-n")) {
|
|
715
|
+
// need "one-match" (9)
|
|
716
|
+
__offset += 3;
|
|
717
|
+
if (__offset + 9 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
718
|
+
|
|
719
|
+
Pack128 P_ONE_MATCH =
|
|
720
|
+
PACK16_9('o','n','e','-','m','a','t','c','h');
|
|
721
|
+
|
|
722
|
+
uint128_t v = load_u128(buf + __offset);
|
|
723
|
+
v = ascii_lower_u128(v);
|
|
724
|
+
|
|
725
|
+
if (simd_eq_n(v, load_const128(P_ONE_MATCH), 9)) {
|
|
726
|
+
__offset += 9; // "if-none-match"
|
|
727
|
+
if (buf[__offset] == ':') {
|
|
728
|
+
if (outHeaders->Has("if-none-match"))
|
|
729
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
730
|
+
hdrId = HDR_IF_NONE_MATCH;
|
|
731
|
+
state = ST_HN_SPACE;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// -------------------------------------------------
|
|
738
|
+
// if-m → if-match | if-modified-since
|
|
739
|
+
// -------------------------------------------------
|
|
740
|
+
else if (lw == PACK8("f-m")) {
|
|
741
|
+
// short path: "atch"
|
|
742
|
+
__offset += 3;
|
|
743
|
+
if (__offset + 4 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
744
|
+
|
|
745
|
+
uint64_t t = load_u64(buf + (__offset));
|
|
746
|
+
uint64_t lt = ascii_lower_u64(t) & MASK_U64_4BYTE;
|
|
747
|
+
|
|
748
|
+
if (lt == PACK8("atch")) {
|
|
749
|
+
__offset += 4; // "if-match"
|
|
750
|
+
if (buf[__offset] == ':') {
|
|
751
|
+
if (outHeaders->Has("if-match"))
|
|
752
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
753
|
+
hdrId = HDR_IF_MATCH;
|
|
754
|
+
state = ST_HN_SPACE;
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// long path: "odified-since"
|
|
760
|
+
if (__offset + 13 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
761
|
+
|
|
762
|
+
Pack128 P_ODIFIED_SINCE =
|
|
763
|
+
PACK16_13('o','d','i','f','i','e','d','-',
|
|
764
|
+
's','i','n','c','e');
|
|
765
|
+
|
|
766
|
+
uint128_t v = load_u128(buf + __offset);
|
|
767
|
+
v = ascii_lower_u128(v);
|
|
768
|
+
|
|
769
|
+
if (simd_eq_n(v, load_const128(P_ODIFIED_SINCE), 13)) {
|
|
770
|
+
__offset += 13; // "if-modified-since"
|
|
771
|
+
if (buf[__offset] == ':') {
|
|
772
|
+
if (outHeaders->Has("if-modified-since"))
|
|
773
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
774
|
+
hdrId = HDR_IF_MODIFIED_SINCE;
|
|
775
|
+
state = ST_HN_SPACE;
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// -------------------------------------------------
|
|
782
|
+
// if-u → if-unmodified-since
|
|
783
|
+
// -------------------------------------------------
|
|
784
|
+
else if (lw == PACK8("f-u")) {
|
|
785
|
+
__offset += 3;
|
|
786
|
+
if (__offset + 15 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
787
|
+
|
|
788
|
+
Pack128 P_UNMODIFIED_SINCE =
|
|
789
|
+
PACK16_15('n','m','o','d','i','f','i','e','d','-',
|
|
790
|
+
's','i','n','c','e');
|
|
791
|
+
|
|
792
|
+
uint128_t v = load_u128(buf + (__offset + 3));
|
|
793
|
+
v = ascii_lower_u128(v);
|
|
794
|
+
|
|
795
|
+
if (simd_eq_n(v, load_const128(P_UNMODIFIED_SINCE), 15)) {
|
|
796
|
+
__offset += 15; // "if-unmodified-since"
|
|
797
|
+
if (buf[__offset] == ':') {
|
|
798
|
+
if (outHeaders->Has("if-unmodified-since"))
|
|
799
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
800
|
+
hdrId = HDR_IF_UNMODIFIED_SINCE;
|
|
801
|
+
state = ST_HN_SPACE;
|
|
802
|
+
continue;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
state = ST_HN_UNKNOWN;
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// ================= L =================
|
|
812
|
+
case ST_HN_L: {
|
|
813
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
814
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
815
|
+
|
|
816
|
+
// -------------------------------------------------
|
|
817
|
+
// li* → link
|
|
818
|
+
// -------------------------------------------------
|
|
819
|
+
if (lv == 'i') {
|
|
820
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
821
|
+
|
|
822
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
823
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
824
|
+
|
|
825
|
+
// "nk"
|
|
826
|
+
if ((lw & MASK_U64_2BYTE) == PACK8("nk")) {
|
|
827
|
+
__offset += 3;
|
|
828
|
+
if (buf[__offset] == ':') {
|
|
829
|
+
hdrId = HDR_LINK;
|
|
830
|
+
state = ST_HN_SPACE;
|
|
831
|
+
continue;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
// -------------------------------------------------
|
|
837
|
+
// la* → last-modified
|
|
838
|
+
// -------------------------------------------------
|
|
839
|
+
else if (lv == 'a') {
|
|
840
|
+
if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
841
|
+
|
|
842
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
843
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
844
|
+
|
|
845
|
+
// "st-modif"
|
|
846
|
+
if (lw == PACK8("st-modif")) {
|
|
847
|
+
w = load_u64(buf + (__offset + 9));
|
|
848
|
+
lw = ascii_lower_u64(w);
|
|
849
|
+
|
|
850
|
+
// "ied"
|
|
851
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("ied")) {
|
|
852
|
+
__offset += 12;
|
|
853
|
+
if (buf[__offset] == ':') {
|
|
854
|
+
hdrId = HDR_LAST_MODIFIED;
|
|
855
|
+
state = ST_HN_SPACE;
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// -------------------------------------------------
|
|
863
|
+
// lo* → location
|
|
864
|
+
// -------------------------------------------------
|
|
865
|
+
else if (lv == 'o') {
|
|
866
|
+
if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
867
|
+
|
|
868
|
+
uint64_t w = load_u64(buf + (__offset + 1));
|
|
869
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
870
|
+
|
|
871
|
+
// "cation"
|
|
872
|
+
if ((lw & MASK_U64_6BYTE) == PACK8("cation")) {
|
|
873
|
+
__offset += 7;
|
|
874
|
+
if (buf[__offset] == ':') {
|
|
875
|
+
hdrId = HDR_LOCATION;
|
|
876
|
+
state = ST_HN_SPACE;
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
state = ST_HN_UNKNOWN;
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// ================= O =================
|
|
887
|
+
case ST_HN_O: {
|
|
888
|
+
if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
889
|
+
uint64_t w = load_u64(buf + __offset);
|
|
890
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
|
|
891
|
+
|
|
892
|
+
// -------------------------------------------------
|
|
893
|
+
// rigin
|
|
894
|
+
// -------------------------------------------------
|
|
895
|
+
if (lw == PACK8("rigin")) {
|
|
896
|
+
|
|
897
|
+
__offset += 5;
|
|
898
|
+
if (buf[__offset] == ':') {
|
|
899
|
+
if (outHeaders->Has("origin"))
|
|
900
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
901
|
+
hdrId = HDR_ORIGIN;
|
|
902
|
+
state = ST_HN_SPACE;
|
|
903
|
+
continue;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
state = ST_HN_UNKNOWN;
|
|
908
|
+
break;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// ================= P =================
|
|
912
|
+
case ST_HN_P: {
|
|
913
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
914
|
+
uint64_t w = load_u64(buf + __offset);
|
|
915
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
|
|
916
|
+
|
|
917
|
+
// -------------------------------------------------
|
|
918
|
+
// pro*
|
|
919
|
+
// -------------------------------------------------
|
|
920
|
+
if (lw == PACK8("ro")) {
|
|
921
|
+
__offset += 2;
|
|
922
|
+
if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
923
|
+
w = load_u64(buf + __offset);
|
|
924
|
+
lw = ascii_lower_u64(w);
|
|
925
|
+
|
|
926
|
+
if (lw == PACK8("xy-authe")) {
|
|
927
|
+
__offset += 8;
|
|
928
|
+
if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
929
|
+
w = load_u64(buf + __offset);
|
|
930
|
+
lw = ascii_lower_u64(w) & MASK_U64_7BYTE;
|
|
931
|
+
|
|
932
|
+
if (lw == PACK8("nticate")) {
|
|
933
|
+
__offset += 7;
|
|
934
|
+
if (buf[__offset] == ':') {
|
|
935
|
+
hdrId = HDR_PROXY_AUTHENTICATE;
|
|
936
|
+
state = ST_HN_SPACE;
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
else if (lw == PACK8("xy-autho")) {
|
|
943
|
+
__offset += 8;
|
|
944
|
+
if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
945
|
+
w = load_u64(buf + __offset);
|
|
946
|
+
lw = ascii_lower_u64(w);
|
|
947
|
+
|
|
948
|
+
if (lw == PACK8("rization")) {
|
|
949
|
+
__offset += 8;
|
|
950
|
+
if (buf[__offset] == ':') {
|
|
951
|
+
if (outHeaders->Has("proxy-authorization"))
|
|
952
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
953
|
+
hdrId = HDR_PROXY_AUTHORIZATION;
|
|
954
|
+
state = ST_HN_SPACE;
|
|
955
|
+
continue;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// -------------------------------------------------
|
|
962
|
+
// pra*
|
|
963
|
+
// -------------------------------------------------
|
|
964
|
+
else if (lw == PACK8("ra")) {
|
|
965
|
+
__offset += 2;
|
|
966
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
967
|
+
w = load_u64(buf + __offset);
|
|
968
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
969
|
+
|
|
970
|
+
if (lw == PACK8("gma")) {
|
|
971
|
+
__offset += 3;
|
|
972
|
+
if (buf[__offset] == ':') {
|
|
973
|
+
hdrId = HDR_PRAGMA;
|
|
974
|
+
hdrMergeable = true;
|
|
975
|
+
state = ST_HN_SPACE;
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
state = ST_HN_UNKNOWN;
|
|
982
|
+
break;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
// ================= S =================
|
|
986
|
+
case ST_HN_S: {
|
|
987
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
988
|
+
uint64_t w = load_u64(buf + __offset);
|
|
989
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
|
|
990
|
+
|
|
991
|
+
if (lw == PACK8("ec")) {
|
|
992
|
+
__offset += 2;
|
|
993
|
+
if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
994
|
+
w = load_u64(buf + __offset);
|
|
995
|
+
lw = ascii_lower_u64(w);
|
|
996
|
+
|
|
997
|
+
// -------------------------------------------------
|
|
998
|
+
// sec-fetch-site
|
|
999
|
+
// -------------------------------------------------
|
|
1000
|
+
if (lw == PACK8("-fetch-s")) {
|
|
1001
|
+
__offset += 8;
|
|
1002
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1003
|
+
w = load_u64(buf + __offset);
|
|
1004
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
1005
|
+
|
|
1006
|
+
if (lw == PACK8("ite")) {
|
|
1007
|
+
__offset += 3;
|
|
1008
|
+
if (buf[__offset] == ':') {
|
|
1009
|
+
hdrId = HDR_SEC_FETCH_SITE;
|
|
1010
|
+
state = ST_HN_SPACE;
|
|
1011
|
+
continue;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// -------------------------------------------------
|
|
1017
|
+
// sec-fetch-site
|
|
1018
|
+
// -------------------------------------------------
|
|
1019
|
+
else if (lw == PACK8("-fetch-m")) {
|
|
1020
|
+
__offset += 8;
|
|
1021
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1022
|
+
w = load_u64(buf + __offset);
|
|
1023
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
1024
|
+
|
|
1025
|
+
if (lw == PACK8("ode")) {
|
|
1026
|
+
__offset += 3;
|
|
1027
|
+
if (buf[__offset] == ':') {
|
|
1028
|
+
hdrId = HDR_SEC_FETCH_MODE;
|
|
1029
|
+
state = ST_HN_SPACE;
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
// -------------------------------------------------
|
|
1036
|
+
// sec-fetch-dest
|
|
1037
|
+
// -------------------------------------------------
|
|
1038
|
+
else if (lw == PACK8("-fetch-d")) {
|
|
1039
|
+
__offset += 8;
|
|
1040
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1041
|
+
w = load_u64(buf + __offset);
|
|
1042
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
1043
|
+
|
|
1044
|
+
if (lw == PACK8("est")) {
|
|
1045
|
+
__offset += 3;
|
|
1046
|
+
if (buf[__offset] == ':') {
|
|
1047
|
+
hdrId = HDR_SEC_FETCH_DEST;
|
|
1048
|
+
state = ST_HN_SPACE;
|
|
1049
|
+
continue;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
// -------------------------------------------------
|
|
1055
|
+
// sec-fetch-user
|
|
1056
|
+
// -------------------------------------------------
|
|
1057
|
+
else if (lw == PACK8("-fetch-u")) {
|
|
1058
|
+
__offset += 8;
|
|
1059
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1060
|
+
w = load_u64(buf + __offset);
|
|
1061
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
1062
|
+
|
|
1063
|
+
if (lw == PACK8("ser")) {
|
|
1064
|
+
__offset += 3;
|
|
1065
|
+
if (buf[__offset] == ':') {
|
|
1066
|
+
hdrId = HDR_SEC_FETCH_USER;
|
|
1067
|
+
state = ST_HN_SPACE;
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// -------------------------------------------------
|
|
1076
|
+
// server
|
|
1077
|
+
// -------------------------------------------------
|
|
1078
|
+
else if(lw == PACK8("er")) {
|
|
1079
|
+
__offset += 2;
|
|
1080
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1081
|
+
w = load_u64(buf + __offset);
|
|
1082
|
+
lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
|
|
1083
|
+
if (lw == PACK8("ver")) {
|
|
1084
|
+
__offset += 3;
|
|
1085
|
+
if (buf[__offset] == ':') {
|
|
1086
|
+
hdrId = HDR_SERVER;
|
|
1087
|
+
state = ST_HN_SPACE;
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// -------------------------------------------------
|
|
1094
|
+
// set-cookie
|
|
1095
|
+
// -------------------------------------------------
|
|
1096
|
+
else if(lw == PACK8("et")) {
|
|
1097
|
+
__offset += 2;
|
|
1098
|
+
if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1099
|
+
w = load_u64(buf + __offset);
|
|
1100
|
+
lw = ascii_lower_u64(w) & MASK_U64_7BYTE;
|
|
1101
|
+
|
|
1102
|
+
if (lw == PACK8("-cookie")) {
|
|
1103
|
+
__offset += 7;
|
|
1104
|
+
if (buf[__offset] == ':') {
|
|
1105
|
+
hdrId = HDR_SET_COOKIE;
|
|
1106
|
+
state = ST_HN_SPACE;
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
state = ST_HN_UNKNOWN;
|
|
1113
|
+
break;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
// ================= T =================
|
|
1117
|
+
case ST_HN_T: {
|
|
1118
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1119
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
1120
|
+
|
|
1121
|
+
// -------------------------------------------------
|
|
1122
|
+
// te → TE
|
|
1123
|
+
// -------------------------------------------------
|
|
1124
|
+
if (lv == 'e') {
|
|
1125
|
+
__offset++;
|
|
1126
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1127
|
+
|
|
1128
|
+
char c = buf[__offset];
|
|
1129
|
+
if (c == ':') {
|
|
1130
|
+
hdrMergeable = true;
|
|
1131
|
+
hdrId = HDR_TE;
|
|
1132
|
+
state = ST_HN_SPACE;
|
|
1133
|
+
continue;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// -------------------------------------------------
|
|
1138
|
+
// tr*
|
|
1139
|
+
// -------------------------------------------------
|
|
1140
|
+
else if (lv == 'r') {
|
|
1141
|
+
if (__offset + 3 >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1142
|
+
uint64_t w = load_u64(buf + (++__offset));
|
|
1143
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
1144
|
+
lw = lw & MASK_U64_2BYTE;
|
|
1145
|
+
|
|
1146
|
+
// ---------------------------------------------
|
|
1147
|
+
// tran*
|
|
1148
|
+
// ---------------------------------------------
|
|
1149
|
+
if (lw == PACK8("an")) {
|
|
1150
|
+
__offset += 2;
|
|
1151
|
+
if (__offset + 13 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1152
|
+
Pack128 P_SFER_ENCODING_ = PACK16_13('s','f','e','r','-','e','n','c','o','d','i','n','g');
|
|
1153
|
+
uint128_t v = load_u128(buf + (__offset));
|
|
1154
|
+
v = ascii_lower_u128(v);
|
|
1155
|
+
|
|
1156
|
+
// -----------------------------------------
|
|
1157
|
+
// tran* → transfer-encoding
|
|
1158
|
+
// -----------------------------------------
|
|
1159
|
+
if (simd_eq_n(v, load_const128(P_SFER_ENCODING_), 13)) {
|
|
1160
|
+
__offset += 13;
|
|
1161
|
+
if (buf[__offset] == ':') {
|
|
1162
|
+
if (outHeaders->Has("transfer-encoding"))
|
|
1163
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
1164
|
+
if (outHeaders->Has("content-length"))
|
|
1165
|
+
return FLAG_BAD_REQUEST;
|
|
1166
|
+
|
|
1167
|
+
hdrId = HDR_TRANSFER_ENCODING;
|
|
1168
|
+
state = ST_HN_SPACE;
|
|
1169
|
+
continue;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// -----------------------------------------
|
|
1175
|
+
// trai* → trailer
|
|
1176
|
+
// -----------------------------------------
|
|
1177
|
+
else if(lw == PACK8("ai")) {
|
|
1178
|
+
__offset += 2;
|
|
1179
|
+
if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1180
|
+
|
|
1181
|
+
w = load_u64(buf + __offset);
|
|
1182
|
+
lw = ascii_lower_u64(w);
|
|
1183
|
+
|
|
1184
|
+
// "ler"
|
|
1185
|
+
if ((lw & MASK_U64_3BYTE) == PACK8("ler")) {
|
|
1186
|
+
__offset += 4;
|
|
1187
|
+
if (buf[__offset] == ':') {
|
|
1188
|
+
hdrMergeable = true;
|
|
1189
|
+
hdrId = HDR_TRAILER;
|
|
1190
|
+
state = ST_HN_SPACE;
|
|
1191
|
+
continue;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
state = ST_HN_UNKNOWN;
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// ================= U =================
|
|
1202
|
+
case ST_HN_U: {
|
|
1203
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1204
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
1205
|
+
|
|
1206
|
+
if (lv == 's') {
|
|
1207
|
+
__offset++;
|
|
1208
|
+
if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1209
|
+
uint64_t w = load_u64(buf + __offset);
|
|
1210
|
+
uint64_t lw = ascii_lower_u64(w);
|
|
1211
|
+
|
|
1212
|
+
if (lw == PACK8("er-agent")) {
|
|
1213
|
+
__offset += 8;
|
|
1214
|
+
if (buf[__offset] == ':') {
|
|
1215
|
+
if (outHeaders->Has("user-agent"))
|
|
1216
|
+
return FLAG_DUPLICATE_SINGLE_HEADER;
|
|
1217
|
+
hdrId = HDR_USER_AGENT;
|
|
1218
|
+
state = ST_HN_SPACE;
|
|
1219
|
+
continue;
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// -------------------------------------------------
|
|
1225
|
+
// upgrade
|
|
1226
|
+
// -------------------------------------------------
|
|
1227
|
+
else if (lv == 'p') {
|
|
1228
|
+
__offset++;
|
|
1229
|
+
if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1230
|
+
uint64_t w = load_u64(buf + __offset);
|
|
1231
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
|
|
1232
|
+
|
|
1233
|
+
if (lw == PACK8("grade")) {
|
|
1234
|
+
__offset += 5;
|
|
1235
|
+
if (buf[__offset] == ':') {
|
|
1236
|
+
hdrId = HDR_UPGRADE;
|
|
1237
|
+
hdrMergeable = true;
|
|
1238
|
+
state = ST_HN_SPACE;
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
state = ST_HN_UNKNOWN;
|
|
1245
|
+
break;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// ================= V =================
|
|
1249
|
+
case ST_HN_V: {
|
|
1250
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1251
|
+
uint64_t w = load_u64(buf + __offset);
|
|
1252
|
+
uint64_t lw = ascii_lower_u64(w) % MASK_U64_2BYTE;
|
|
1253
|
+
|
|
1254
|
+
// -------------------------------------------------
|
|
1255
|
+
// via
|
|
1256
|
+
// -------------------------------------------------
|
|
1257
|
+
if (lw == PACK8("ia")) {
|
|
1258
|
+
__offset += 2;
|
|
1259
|
+
if (buf[__offset] == ':') {
|
|
1260
|
+
hdrId = HDR_VIA;
|
|
1261
|
+
state = ST_HN_SPACE;
|
|
1262
|
+
continue;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// -------------------------------------------------
|
|
1267
|
+
// vary
|
|
1268
|
+
// -------------------------------------------------
|
|
1269
|
+
else if(lw == PACK8("ar")) {
|
|
1270
|
+
__offset += 2;
|
|
1271
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1272
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
1273
|
+
|
|
1274
|
+
if (lv == 'y') {
|
|
1275
|
+
__offset += 1;
|
|
1276
|
+
if (buf[__offset] == ':') {
|
|
1277
|
+
hdrId = HDR_VARY;
|
|
1278
|
+
state = ST_HN_SPACE;
|
|
1279
|
+
continue;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
state = ST_HN_UNKNOWN;
|
|
1285
|
+
break;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
// ================= W =================
|
|
1289
|
+
case ST_HN_W: {
|
|
1290
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1291
|
+
uint8_t lv = ascii_lower(buf[__offset]);
|
|
1292
|
+
|
|
1293
|
+
if (lv == 'w') {
|
|
1294
|
+
__offset++;
|
|
1295
|
+
if (__offset + 14 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1296
|
+
Pack128 P_W_AUTHENTICATE_ = PACK16_14('w','-','a','u','t','h','e','n','t','i','c','a','t','e');
|
|
1297
|
+
uint128_t v = load_u128(buf + (__offset));
|
|
1298
|
+
v = ascii_lower_u128(v);
|
|
1299
|
+
|
|
1300
|
+
// -----------------------------------------
|
|
1301
|
+
// ww* → www-authenticate
|
|
1302
|
+
// -----------------------------------------
|
|
1303
|
+
if (simd_eq_n(v, load_const128(P_W_AUTHENTICATE_), 14)) {
|
|
1304
|
+
__offset += 14;
|
|
1305
|
+
if (buf[__offset] == ':') {
|
|
1306
|
+
hdrId = HDR_WWW_AUTHENTICATE;
|
|
1307
|
+
state = ST_HN_SPACE;
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// -------------------------------------------------
|
|
1314
|
+
// warning
|
|
1315
|
+
// -------------------------------------------------
|
|
1316
|
+
else if(lv == 'a') {
|
|
1317
|
+
__offset++;
|
|
1318
|
+
if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1319
|
+
uint64_t w = load_u64(buf + __offset);
|
|
1320
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
|
|
1321
|
+
|
|
1322
|
+
if (lw == PACK8("rning")) {
|
|
1323
|
+
__offset += 5;
|
|
1324
|
+
if (buf[__offset] == ':') {
|
|
1325
|
+
hdrId = HDR_WARNING;
|
|
1326
|
+
state = ST_HN_SPACE;
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
state = ST_HN_UNKNOWN;
|
|
1333
|
+
break;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
// ================= X =================
|
|
1337
|
+
case ST_HN_X: {
|
|
1338
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1339
|
+
uint64_t w = load_u64(buf + __offset);
|
|
1340
|
+
uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
|
|
1341
|
+
|
|
1342
|
+
if (lw == PACK8("-f")) {
|
|
1343
|
+
__offset += 2;
|
|
1344
|
+
// orwarded-for
|
|
1345
|
+
// orwarded-pro
|
|
1346
|
+
// orwarded-hos
|
|
1347
|
+
if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1348
|
+
|
|
1349
|
+
uint128_t v = load_u128(buf + (__offset));
|
|
1350
|
+
v = ascii_lower_u128(v);
|
|
1351
|
+
|
|
1352
|
+
Pack128 P_ORWARDED_FOR = PACK16_12('o','r','w','a','r','d','e','d','-','f','o','r');
|
|
1353
|
+
Pack128 P_ORWARDED_PRO = PACK16_12('o','r','w','a','r','d','e','d','-','p','r','o');
|
|
1354
|
+
Pack128 P_ORWARDED_HOS = PACK16_12('o','r','w','a','r','d','e','d','-','h','o','s');
|
|
1355
|
+
|
|
1356
|
+
if (simd_eq_n(v, load_const128(P_ORWARDED_FOR), 12)) {
|
|
1357
|
+
__offset += 12;
|
|
1358
|
+
if (buf[__offset] == ':') {
|
|
1359
|
+
hdrId = HDR_X_FORWARDED_FOR;
|
|
1360
|
+
state = ST_HN_SPACE;
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
else if (simd_eq_n(v, load_const128(P_ORWARDED_HOS), 12)) {
|
|
1366
|
+
__offset += 12;
|
|
1367
|
+
if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
|
|
1368
|
+
uint8_t v = ascii_lower(buf[__offset]);
|
|
1369
|
+
|
|
1370
|
+
if (v == 't') {
|
|
1371
|
+
__offset++;
|
|
1372
|
+
if (buf[__offset] == ':') {
|
|
1373
|
+
hdrId = HDR_X_FORWARDED_HOST;
|
|
1374
|
+
state = ST_HN_SPACE;
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
else if (simd_eq_n(v, load_const128(P_ORWARDED_PRO), 12)) {
|
|
1381
|
+
__offset += 12;
|
|
1382
|
+
if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1383
|
+
w = load_u64(buf + __offset);
|
|
1384
|
+
lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
|
|
1385
|
+
if (lw == PACK8("to")) {
|
|
1386
|
+
__offset += 2;
|
|
1387
|
+
if (buf[__offset] == ':') {
|
|
1388
|
+
hdrId = HDR_X_FORWARDED_PROTO;
|
|
1389
|
+
state = ST_HN_SPACE;
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
else if(lw == PACK8("-r")) {
|
|
1397
|
+
__offset += 2;
|
|
1398
|
+
if (__offset + 6 > total) return FLAG_UNTERMINATED_HEADERS;
|
|
1399
|
+
w = load_u64(buf + __offset);
|
|
1400
|
+
lw = ascii_lower_u64(w) & MASK_U64_6BYTE;
|
|
1401
|
+
|
|
1402
|
+
if (lw == PACK8("eal-ip")) {
|
|
1403
|
+
__offset +=6;
|
|
1404
|
+
if (buf[__offset] == ':') {
|
|
1405
|
+
hdrId = HDR_X_REAL_IP;
|
|
1406
|
+
state = ST_HN_SPACE;
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
state = ST_HN_UNKNOWN;
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// =============== VALUE ===============
|
|
1417
|
+
case ST_HV_CONCAT: {
|
|
1418
|
+
// ---- Skip leading OWS ----
|
|
1419
|
+
while (__offset < total &&
|
|
1420
|
+
(buf[__offset] == ' ' || buf[__offset] == '\t'))
|
|
1421
|
+
__offset++;
|
|
1422
|
+
|
|
1423
|
+
// ---- Scan header value ----
|
|
1424
|
+
auto hv = std::make_unique<std::string>();
|
|
1425
|
+
FlagBits ret = HEADERS[hdrId].value_parser(
|
|
1426
|
+
buf, &__offset, total, maxHeaderValueSize, hv
|
|
1427
|
+
);
|
|
1428
|
+
|
|
1429
|
+
if (ret != FLAG_OK) {
|
|
1430
|
+
return ret;
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
// ---- Consume CRLF or LF ----
|
|
1434
|
+
if (buf[__offset] == '\r') {
|
|
1435
|
+
if (__offset + 1 >= total || buf[__offset + 1] != '\n')
|
|
1436
|
+
return FLAG_INVALID_HEADER_VALUE;
|
|
1437
|
+
__offset += 2;
|
|
1438
|
+
}
|
|
1439
|
+
else if (buf[__offset] == '\n') {
|
|
1440
|
+
__offset += 1;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// ---- Commit offset for next header ----
|
|
1444
|
+
*offset = __offset;
|
|
1445
|
+
|
|
1446
|
+
// ---- Store header value ----
|
|
1447
|
+
auto value = Napi::String::New(
|
|
1448
|
+
env,
|
|
1449
|
+
hv->c_str()
|
|
1450
|
+
);
|
|
1451
|
+
|
|
1452
|
+
if (hdrId == HDR_UNKNOWN) {
|
|
1453
|
+
outHeaders->Set(headerUnknownName, value);
|
|
1454
|
+
} else {
|
|
1455
|
+
const char* name = HEADERS[hdrId].name;
|
|
1456
|
+
|
|
1457
|
+
if (hdrMergeable && outHeaders->Has(name)) {
|
|
1458
|
+
auto oldVal =
|
|
1459
|
+
outHeaders->Get(name)
|
|
1460
|
+
.As<Napi::String>()
|
|
1461
|
+
.Utf8Value();
|
|
1462
|
+
|
|
1463
|
+
outHeaders->Set(
|
|
1464
|
+
name,
|
|
1465
|
+
Napi::String::New(
|
|
1466
|
+
env,
|
|
1467
|
+
oldVal + ", " + value.Utf8Value()
|
|
1468
|
+
)
|
|
1469
|
+
);
|
|
1470
|
+
hdrMergeable = false;
|
|
1471
|
+
} else {
|
|
1472
|
+
outHeaders->Set(name, value);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
// ---- HEADER BLOCK END? (CRLF CRLF) ----
|
|
1477
|
+
|
|
1478
|
+
if (__offset + 1 < total &&
|
|
1479
|
+
buf[__offset] == '\r' &&
|
|
1480
|
+
buf[__offset + 1] == '\n') {
|
|
1481
|
+
|
|
1482
|
+
// consume final CRLF
|
|
1483
|
+
*offset = __offset + 2;
|
|
1484
|
+
return FLAG_OK;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
|
|
1488
|
+
// ---- Reset per-header state ----
|
|
1489
|
+
hdrId = HDR_UNKNOWN;
|
|
1490
|
+
hdrMergeable = false;
|
|
1491
|
+
headerUnknownName.clear();
|
|
1492
|
+
|
|
1493
|
+
// ---- Continue parsing next header ----
|
|
1494
|
+
state = ST_STARTUP;
|
|
1495
|
+
continue;
|
|
1496
|
+
}
|
|
1497
|
+
} // switch
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
return FLAG_OK;
|
|
1501
|
+
}
|