corecdtl 0.1.5 → 0.1.7

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.
@@ -1,1503 +0,0 @@
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
- std::cout << state << "\n";
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
- /*
273
- case 'r': case 'R':
274
- vStart = __offset;
275
- __offset++;
276
- state = ST_HN_R;
277
- continue;
278
- */
279
- case 's': case 'S':
280
- vStart = __offset;
281
- __offset++;
282
- state = ST_HN_S;
283
- continue;
284
- case 't': case 'T':
285
- vStart = __offset;
286
- __offset++;
287
- state = ST_HN_T;
288
- continue;
289
- case 'u': case 'U':
290
- vStart = __offset;
291
- __offset++;
292
- state = ST_HN_U;
293
- continue;
294
- case 'v': case 'V':
295
- vStart = __offset;
296
- __offset++;
297
- state = ST_HN_V;
298
- continue;
299
- case 'w': case 'W':
300
- vStart = __offset;
301
- __offset++;
302
- state = ST_HN_W;
303
- continue;
304
- case 'x': case 'X':
305
- vStart = __offset;
306
- __offset++;
307
- state = ST_HN_X;
308
- continue;
309
- case 'h': case 'H':
310
- vStart = __offset;
311
- __offset++;
312
- state = ST_HN_H;
313
- continue;
314
-
315
- default:
316
- vStart = __offset;
317
- state = ST_HN_UNKNOWN;
318
- continue;
319
- }
320
- }
321
-
322
- // ================= SPACE =================
323
- case ST_HN_SPACE: {
324
- __offset++;
325
- state = ST_HV_CONCAT;
326
- continue;
327
- }
328
-
329
- // ================= UNKNOWN =================
330
- case ST_HN_UNKNOWN: {
331
- while (true) {
332
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
333
-
334
- char c = buf[__offset];
335
- if (c == ':') {
336
- __offset++;
337
- hdrId = HDR_UNKNOWN;
338
- headerUnknownName.assign(buf + vStart, __offset - vStart - 1);
339
- std::transform(headerUnknownName.begin(), headerUnknownName.end(), headerUnknownName.begin(),
340
- [](unsigned char c){ return std::tolower(c); });
341
- state = ST_HV_CONCAT;
342
- break;
343
- }
344
- if (c == ' ' || c == '\t') {
345
- return FLAG_INVALID_HEADER;
346
- }
347
- unsigned char uc = (unsigned char)c;
348
- if (uc < 33 || uc > 126) {
349
- return FLAG_INVALID_HEADER;
350
- }
351
- __offset++;
352
- if (__offset - vStart > maxHeaderNameSize) return FLAG_MAX_HEADER_NAME_SIZE;
353
- }
354
- continue;
355
- }
356
-
357
- // ================= H =================
358
- case ST_HN_H: {
359
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
360
-
361
- uint64_t v = load_u64(buf + __offset);
362
- uint64_t lv = ascii_lower_u64(v);
363
- if ((lv & MASK_U64_3BYTE) == PACK8("ost")) {
364
- __offset += 3;
365
- if (buf[__offset] == ':') {
366
- if (outHeaders->Has("host"))
367
- return FLAG_DUPLICATE_SINGLE_HEADER;
368
- hdrId = HDR_HOST;
369
- state = ST_HN_SPACE;
370
- continue;
371
- }
372
- }
373
- state = ST_HN_UNKNOWN;
374
- continue;
375
- }
376
-
377
- // ================= A =================
378
- case ST_HN_A: {
379
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
380
- uint8_t lv = ascii_lower(buf[__offset]);
381
-
382
- // accept*
383
- if (lv == 'c') {
384
-
385
- if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
386
-
387
- uint64_t w = load_u64(buf + (++__offset));
388
- uint64_t lw = ascii_lower_u64(w);
389
-
390
- // "cept"
391
- if ((lw & MASK_U64_4BYTE) == PACK8("cept")) {
392
- __offset += 4;
393
-
394
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
395
-
396
- char c = buf[__offset];
397
- // --------------------
398
- // ACCEPT (plain)
399
- // --------------------
400
- if (c == ':' || c == ' ' || c == '\t') {
401
- hdrId = HDR_ACCEPT;
402
- state = ST_HN_SPACE;
403
- continue;
404
- }
405
-
406
- // --------------------
407
- // ACCEPT-*
408
- // --------------------
409
- if (c == '-') {
410
- if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
411
-
412
- uint8_t n = ascii_lower(buf[++__offset]);
413
-
414
- // accept-language
415
- if (n == 'l') {
416
- w = load_u64(buf + (__offset + 1));
417
- lw = ascii_lower_u64(w);
418
- if ((lw & MASK_U64_7BYTE) == PACK8("anguage")) {
419
- __offset += 8;
420
- if (buf[__offset] == ':') {
421
- hdrMergeable = true;
422
- hdrId = HDR_ACCEPT_LANGUAGE;
423
- state = ST_HN_SPACE;
424
- continue;
425
- }
426
- }
427
- }
428
- // accept-encoding
429
- else if (n == 'e') {
430
- w = load_u64(buf + (__offset + 1));
431
- lw = ascii_lower_u64(w);
432
- if ((lw & MASK_U64_7BYTE) == PACK8("ncoding")) {
433
- __offset += 8;
434
- if (buf[__offset] == ':') {
435
- hdrMergeable = true;
436
- hdrId = HDR_ACCEPT_ENCODING;
437
- state = ST_HN_SPACE;
438
- continue;
439
- }
440
- }
441
- }
442
- // accept-ranges
443
- else if (n == 'r') {
444
- w = load_u64(buf + (__offset + 1));
445
- lw = ascii_lower_u64(w);
446
- if ((lw & MASK_U64_5BYTE) == PACK8("anges")) {
447
- __offset += 6;
448
- if (buf[__offset] == ':') {
449
- hdrMergeable = true;
450
- hdrId = HDR_ACCEPT_RANGES;
451
- state = ST_HN_SPACE;
452
- continue;
453
- }
454
- }
455
- }
456
- }
457
- }
458
- }
459
-
460
- // allow
461
- else if (lv == 'l') {
462
- uint64_t w = load_u64(buf + __offset);
463
- uint64_t lw = ascii_lower_u64(w);
464
- if ((lw & MASK_U64_3BYTE) == PACK8("low")) {
465
- __offset += 4;
466
- if (buf[__offset] == ':') {
467
- hdrMergeable = true;
468
- hdrId = HDR_ALLOW;
469
- state = ST_HN_SPACE;
470
- continue;
471
- }
472
- }
473
- }
474
-
475
- // authorization
476
- else if (lv == 'u') {
477
- if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
478
- Pack128 P_THORIZATION = PACK16_11('t','h','o','r','i','z','a','t','i','o','n');
479
- __offset++;
480
- uint128_t v = load_u128(buf + (__offset));
481
- v = ascii_lower_u128(v);
482
- if (simd_eq_n(v, load_const128(P_THORIZATION), 11)) {
483
- __offset += 11;
484
- if (buf[__offset] == ':') {
485
- if (outHeaders->Has("authorization"))
486
- return FLAG_DUPLICATE_SINGLE_HEADER;
487
-
488
- hdrId = HDR_AUTHORIZATION;
489
- state = ST_HN_SPACE;
490
- continue;
491
- }
492
- }
493
- }
494
-
495
- state = ST_HN_UNKNOWN;
496
- continue;
497
- }
498
-
499
- // ================= C =================
500
- case ST_HN_C: {
501
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
502
- uint8_t lv = ascii_lower(buf[__offset]);
503
-
504
- // -------------------------------------------------
505
- // ca* → cache-control
506
- // -------------------------------------------------
507
- if (lv == 'a') {
508
- if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
509
-
510
- uint64_t w = load_u64(buf + (__offset + 1));
511
- uint64_t lw = ascii_lower_u64(w);
512
-
513
- // "che-cont"
514
- if (lw == PACK8("che-cont")) {
515
- w = load_u64(buf + (__offset + 9));
516
- lw = ascii_lower_u64(w);
517
-
518
- // "rol"
519
- if ((lw & MASK_U64_3BYTE) == PACK8("rol")) {
520
- __offset += 12;
521
- if (buf[__offset] == ':') {
522
- hdrMergeable = true;
523
- hdrId = HDR_CACHE_CONTROL;
524
- state = ST_HN_SPACE;
525
- continue;
526
- }
527
- }
528
- }
529
- }
530
-
531
- // -------------------------------------------------
532
- // co*
533
- // -------------------------------------------------
534
- else if (lv == 'o') {
535
- if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
536
- uint8_t n = ascii_lower(buf[++__offset]);
537
-
538
- // ---------------------------------------------
539
- // coo* → cookie
540
- // ---------------------------------------------
541
- if (n == 'o') {
542
- if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
543
-
544
- uint64_t w = load_u64(buf + (__offset + 1));
545
- uint64_t lw = ascii_lower_u64(w);
546
-
547
- // "kie"
548
- if ((lw & MASK_U64_3BYTE) == PACK8("kie")) {
549
- __offset += 4;
550
- if (buf[__offset] == ':') {
551
- hdrId = HDR_COOKIE;
552
- state = ST_HN_SPACE;
553
- continue;
554
- }
555
- }
556
- }
557
-
558
- // ---------------------------------------------
559
- // con*
560
- // ---------------------------------------------
561
- else if (n == 'n') {
562
- if (__offset + 1 >= total) return FLAG_UNTERMINATED_HEADERS;
563
- uint8_t t = ascii_lower(buf[++__offset]);
564
-
565
- // -----------------------------------------
566
- // conn* → connection
567
- // -----------------------------------------
568
- if (t == 'n') {
569
- if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
570
-
571
- uint64_t w = load_u64(buf + (__offset + 1));
572
- uint64_t lw = ascii_lower_u64(w);
573
-
574
- // "ection"
575
- if ((lw & MASK_U64_6BYTE) == PACK8("ection")) {
576
- __offset += 7;
577
- if (buf[__offset] == ':') {
578
- hdrMergeable = true;
579
- hdrId = HDR_CONNECTION;
580
- state = ST_HN_SPACE;
581
- continue;
582
- }
583
- }
584
- }
585
-
586
- // -----------------------------------------
587
- // cont* → content-*
588
- // -----------------------------------------
589
- else if (t == 't') {
590
- if (__offset + 4 > total) return FLAG_UNTERMINATED_HEADERS;
591
- __offset++;
592
- uint64_t w = load_u64(buf + (__offset));
593
- uint64_t lw = ascii_lower_u64(w);
594
- // "ent-"
595
- if ((lw & MASK_U64_4BYTE) == PACK8("ent-")) {
596
- __offset += 4;
597
-
598
-
599
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
600
- uint8_t k = ascii_lower(buf[__offset]);
601
-
602
- // content-length
603
- if (k == 'l') {
604
- w = load_u64(buf + (__offset + 1));
605
- lw = ascii_lower_u64(w);
606
- if ((lw & MASK_U64_5BYTE) == PACK8("ength")) {
607
- __offset += 6;
608
- if (buf[__offset] == ':') {
609
- if (outHeaders->Has("content-length"))
610
- return FLAG_DUPLICATE_SINGLE_HEADER;
611
- if (outHeaders->Has("transfer-encoding"))
612
- return FLAG_BAD_REQUEST;
613
-
614
- hdrId = HDR_CONTENT_LENGTH;
615
- state = ST_HN_SPACE;
616
- continue;
617
- }
618
- }
619
- }
620
- // content-type
621
- else if (k == 't') {
622
- w = load_u64(buf + (__offset + 1));
623
- lw = ascii_lower_u64(w);
624
- if ((lw & MASK_U64_3BYTE) == PACK8("ype")) {
625
- __offset += 4;
626
- if (buf[__offset] == ':') {
627
- if (outHeaders->Has("content-type"))
628
- return FLAG_DUPLICATE_SINGLE_HEADER;
629
- hdrId = HDR_CONTENT_TYPE;
630
- state = ST_HN_SPACE;
631
- continue;
632
- }
633
- }
634
- }
635
- // content-range
636
- else if (k == 'r') {
637
- w = load_u64(buf + (__offset + 1));
638
- lw = ascii_lower_u64(w);
639
- if ((lw & MASK_U64_4BYTE) == PACK8("ange")) {
640
- __offset += 5;
641
- if (buf[__offset] == ':') {
642
- if (outHeaders->Has("content-range"))
643
- return FLAG_DUPLICATE_SINGLE_HEADER;
644
- hdrId = HDR_CONTENT_RANGE;
645
- state = ST_HN_SPACE;
646
- continue;
647
- }
648
- }
649
- }
650
- }
651
- }
652
- }
653
- }
654
- state = ST_HN_UNKNOWN;
655
- break;
656
- }
657
-
658
- // ================= D =================
659
- case ST_HN_D: {
660
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
661
- uint8_t lv = ascii_lower(buf[__offset]);
662
-
663
- // -------------------------------------------------
664
- // da* → date
665
- // -------------------------------------------------
666
- if (lv == 'a') {
667
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
668
- uint32_t w =
669
- (uint32_t)(ascii_lower(buf[__offset + 1]) << 16) |
670
- (uint32_t)(ascii_lower(buf[__offset + 2]) << 8);
671
-
672
- // "te"
673
- if (w == (('t' << 16) | ('e' << 8))) {
674
- __offset += 3;
675
- if (buf[__offset] == ':') {
676
- if (outHeaders->Has("date"))
677
- return FLAG_DUPLICATE_SINGLE_HEADER;
678
- hdrId = HDR_DATE;
679
- state = ST_HN_SPACE;
680
- continue;
681
- }
682
- }
683
- }
684
-
685
- // -------------------------------------------------
686
- // dn* → dnt
687
- // -------------------------------------------------
688
- else if (lv == 'n') {
689
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
690
-
691
- uint16_t w = ascii_lower(buf[__offset + 1]);
692
- // "t"
693
- if (w == 't') {
694
- __offset += 2;
695
- if (buf[__offset] == ':') {
696
- hdrId = HDR_DNT;
697
- state = ST_HN_SPACE;
698
- continue;
699
- }
700
- }
701
- }
702
-
703
- state = ST_HN_UNKNOWN;
704
- break;
705
- }
706
-
707
- // ================= I =================
708
- case ST_HN_I: {
709
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
710
-
711
- uint64_t w = load_u64(buf + __offset);
712
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
713
- // -------------------------------------------------
714
- // if-n → if-none-match
715
- // -------------------------------------------------
716
- if (lw == PACK8("f-n")) {
717
- // need "one-match" (9)
718
- __offset += 3;
719
- if (__offset + 9 > total) return FLAG_UNTERMINATED_HEADERS;
720
-
721
- Pack128 P_ONE_MATCH =
722
- PACK16_9('o','n','e','-','m','a','t','c','h');
723
-
724
- uint128_t v = load_u128(buf + __offset);
725
- v = ascii_lower_u128(v);
726
-
727
- if (simd_eq_n(v, load_const128(P_ONE_MATCH), 9)) {
728
- __offset += 9; // "if-none-match"
729
- if (buf[__offset] == ':') {
730
- if (outHeaders->Has("if-none-match"))
731
- return FLAG_DUPLICATE_SINGLE_HEADER;
732
- hdrId = HDR_IF_NONE_MATCH;
733
- state = ST_HN_SPACE;
734
- continue;
735
- }
736
- }
737
- }
738
-
739
- // -------------------------------------------------
740
- // if-m → if-match | if-modified-since
741
- // -------------------------------------------------
742
- else if (lw == PACK8("f-m")) {
743
- // short path: "atch"
744
- __offset += 3;
745
- if (__offset + 4 > total) return FLAG_UNTERMINATED_HEADERS;
746
-
747
- uint64_t t = load_u64(buf + (__offset));
748
- uint64_t lt = ascii_lower_u64(t) & MASK_U64_4BYTE;
749
-
750
- if (lt == PACK8("atch")) {
751
- __offset += 4; // "if-match"
752
- if (buf[__offset] == ':') {
753
- if (outHeaders->Has("if-match"))
754
- return FLAG_DUPLICATE_SINGLE_HEADER;
755
- hdrId = HDR_IF_MATCH;
756
- state = ST_HN_SPACE;
757
- continue;
758
- }
759
- }
760
-
761
- // long path: "odified-since"
762
- if (__offset + 13 > total) return FLAG_UNTERMINATED_HEADERS;
763
-
764
- Pack128 P_ODIFIED_SINCE =
765
- PACK16_13('o','d','i','f','i','e','d','-',
766
- 's','i','n','c','e');
767
-
768
- uint128_t v = load_u128(buf + __offset);
769
- v = ascii_lower_u128(v);
770
-
771
- if (simd_eq_n(v, load_const128(P_ODIFIED_SINCE), 13)) {
772
- __offset += 13; // "if-modified-since"
773
- if (buf[__offset] == ':') {
774
- if (outHeaders->Has("if-modified-since"))
775
- return FLAG_DUPLICATE_SINGLE_HEADER;
776
- hdrId = HDR_IF_MODIFIED_SINCE;
777
- state = ST_HN_SPACE;
778
- continue;
779
- }
780
- }
781
- }
782
-
783
- // -------------------------------------------------
784
- // if-u → if-unmodified-since
785
- // -------------------------------------------------
786
- else if (lw == PACK8("f-u")) {
787
- __offset += 3;
788
- if (__offset + 15 > total) return FLAG_UNTERMINATED_HEADERS;
789
-
790
- Pack128 P_UNMODIFIED_SINCE =
791
- PACK16_15('n','m','o','d','i','f','i','e','d','-',
792
- 's','i','n','c','e');
793
-
794
- uint128_t v = load_u128(buf + (__offset + 3));
795
- v = ascii_lower_u128(v);
796
-
797
- if (simd_eq_n(v, load_const128(P_UNMODIFIED_SINCE), 15)) {
798
- __offset += 15; // "if-unmodified-since"
799
- if (buf[__offset] == ':') {
800
- if (outHeaders->Has("if-unmodified-since"))
801
- return FLAG_DUPLICATE_SINGLE_HEADER;
802
- hdrId = HDR_IF_UNMODIFIED_SINCE;
803
- state = ST_HN_SPACE;
804
- continue;
805
- }
806
- }
807
- }
808
-
809
- state = ST_HN_UNKNOWN;
810
- break;
811
- }
812
-
813
- // ================= L =================
814
- case ST_HN_L: {
815
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
816
- uint8_t lv = ascii_lower(buf[__offset]);
817
-
818
- // -------------------------------------------------
819
- // li* → link
820
- // -------------------------------------------------
821
- if (lv == 'i') {
822
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
823
-
824
- uint64_t w = load_u64(buf + (__offset + 1));
825
- uint64_t lw = ascii_lower_u64(w);
826
-
827
- // "nk"
828
- if ((lw & MASK_U64_2BYTE) == PACK8("nk")) {
829
- __offset += 3;
830
- if (buf[__offset] == ':') {
831
- hdrId = HDR_LINK;
832
- state = ST_HN_SPACE;
833
- continue;
834
- }
835
- }
836
- }
837
-
838
- // -------------------------------------------------
839
- // la* → last-modified
840
- // -------------------------------------------------
841
- else if (lv == 'a') {
842
- if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
843
-
844
- uint64_t w = load_u64(buf + (__offset + 1));
845
- uint64_t lw = ascii_lower_u64(w);
846
-
847
- // "st-modif"
848
- if (lw == PACK8("st-modif")) {
849
- w = load_u64(buf + (__offset + 9));
850
- lw = ascii_lower_u64(w);
851
-
852
- // "ied"
853
- if ((lw & MASK_U64_3BYTE) == PACK8("ied")) {
854
- __offset += 12;
855
- if (buf[__offset] == ':') {
856
- hdrId = HDR_LAST_MODIFIED;
857
- state = ST_HN_SPACE;
858
- continue;
859
- }
860
- }
861
- }
862
- }
863
-
864
- // -------------------------------------------------
865
- // lo* → location
866
- // -------------------------------------------------
867
- else if (lv == 'o') {
868
- if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
869
-
870
- uint64_t w = load_u64(buf + (__offset + 1));
871
- uint64_t lw = ascii_lower_u64(w);
872
-
873
- // "cation"
874
- if ((lw & MASK_U64_6BYTE) == PACK8("cation")) {
875
- __offset += 7;
876
- if (buf[__offset] == ':') {
877
- hdrId = HDR_LOCATION;
878
- state = ST_HN_SPACE;
879
- continue;
880
- }
881
- }
882
- }
883
-
884
- state = ST_HN_UNKNOWN;
885
- break;
886
- }
887
-
888
- // ================= O =================
889
- case ST_HN_O: {
890
- if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
891
- uint64_t w = load_u64(buf + __offset);
892
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
893
-
894
- // -------------------------------------------------
895
- // rigin
896
- // -------------------------------------------------
897
- if (lw == PACK8("rigin")) {
898
-
899
- __offset += 5;
900
- if (buf[__offset] == ':') {
901
- if (outHeaders->Has("origin"))
902
- return FLAG_DUPLICATE_SINGLE_HEADER;
903
- hdrId = HDR_ORIGIN;
904
- state = ST_HN_SPACE;
905
- continue;
906
- }
907
- }
908
-
909
- state = ST_HN_UNKNOWN;
910
- break;
911
- }
912
-
913
- // ================= P =================
914
- case ST_HN_P: {
915
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
916
- uint64_t w = load_u64(buf + __offset);
917
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
918
-
919
- // -------------------------------------------------
920
- // pro*
921
- // -------------------------------------------------
922
- if (lw == PACK8("ro")) {
923
- __offset += 2;
924
- if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
925
- w = load_u64(buf + __offset);
926
- lw = ascii_lower_u64(w);
927
-
928
- if (lw == PACK8("xy-authe")) {
929
- __offset += 8;
930
- if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
931
- w = load_u64(buf + __offset);
932
- lw = ascii_lower_u64(w) & MASK_U64_7BYTE;
933
-
934
- if (lw == PACK8("nticate")) {
935
- __offset += 7;
936
- if (buf[__offset] == ':') {
937
- hdrId = HDR_PROXY_AUTHENTICATE;
938
- state = ST_HN_SPACE;
939
- continue;
940
- }
941
- }
942
- }
943
-
944
- else if (lw == PACK8("xy-autho")) {
945
- __offset += 8;
946
- if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
947
- w = load_u64(buf + __offset);
948
- lw = ascii_lower_u64(w);
949
-
950
- if (lw == PACK8("rization")) {
951
- __offset += 8;
952
- if (buf[__offset] == ':') {
953
- if (outHeaders->Has("proxy-authorization"))
954
- return FLAG_DUPLICATE_SINGLE_HEADER;
955
- hdrId = HDR_PROXY_AUTHORIZATION;
956
- state = ST_HN_SPACE;
957
- continue;
958
- }
959
- }
960
- }
961
- }
962
-
963
- // -------------------------------------------------
964
- // pra*
965
- // -------------------------------------------------
966
- else if (lw == PACK8("ra")) {
967
- __offset += 2;
968
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
969
- w = load_u64(buf + __offset);
970
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
971
-
972
- if (lw == PACK8("gma")) {
973
- __offset += 3;
974
- if (buf[__offset] == ':') {
975
- hdrId = HDR_PRAGMA;
976
- hdrMergeable = true;
977
- state = ST_HN_SPACE;
978
- continue;
979
- }
980
- }
981
- }
982
-
983
- state = ST_HN_UNKNOWN;
984
- break;
985
- }
986
-
987
- // ================= S =================
988
- case ST_HN_S: {
989
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
990
- uint64_t w = load_u64(buf + __offset);
991
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
992
-
993
- if (lw == PACK8("ec")) {
994
- __offset += 2;
995
- if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
996
- w = load_u64(buf + __offset);
997
- lw = ascii_lower_u64(w);
998
-
999
- // -------------------------------------------------
1000
- // sec-fetch-site
1001
- // -------------------------------------------------
1002
- if (lw == PACK8("-fetch-s")) {
1003
- __offset += 8;
1004
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1005
- w = load_u64(buf + __offset);
1006
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
1007
-
1008
- if (lw == PACK8("ite")) {
1009
- __offset += 3;
1010
- if (buf[__offset] == ':') {
1011
- hdrId = HDR_SEC_FETCH_SITE;
1012
- state = ST_HN_SPACE;
1013
- continue;
1014
- }
1015
- }
1016
- }
1017
-
1018
- // -------------------------------------------------
1019
- // sec-fetch-site
1020
- // -------------------------------------------------
1021
- else if (lw == PACK8("-fetch-m")) {
1022
- __offset += 8;
1023
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1024
- w = load_u64(buf + __offset);
1025
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
1026
-
1027
- if (lw == PACK8("ode")) {
1028
- __offset += 3;
1029
- if (buf[__offset] == ':') {
1030
- hdrId = HDR_SEC_FETCH_MODE;
1031
- state = ST_HN_SPACE;
1032
- continue;
1033
- }
1034
- }
1035
- }
1036
-
1037
- // -------------------------------------------------
1038
- // sec-fetch-dest
1039
- // -------------------------------------------------
1040
- else if (lw == PACK8("-fetch-d")) {
1041
- __offset += 8;
1042
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1043
- w = load_u64(buf + __offset);
1044
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
1045
-
1046
- if (lw == PACK8("est")) {
1047
- __offset += 3;
1048
- if (buf[__offset] == ':') {
1049
- hdrId = HDR_SEC_FETCH_DEST;
1050
- state = ST_HN_SPACE;
1051
- continue;
1052
- }
1053
- }
1054
- }
1055
-
1056
- // -------------------------------------------------
1057
- // sec-fetch-user
1058
- // -------------------------------------------------
1059
- else if (lw == PACK8("-fetch-u")) {
1060
- __offset += 8;
1061
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1062
- w = load_u64(buf + __offset);
1063
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
1064
-
1065
- if (lw == PACK8("ser")) {
1066
- __offset += 3;
1067
- if (buf[__offset] == ':') {
1068
- hdrId = HDR_SEC_FETCH_USER;
1069
- state = ST_HN_SPACE;
1070
- continue;
1071
- }
1072
- }
1073
- }
1074
-
1075
- }
1076
-
1077
- // -------------------------------------------------
1078
- // server
1079
- // -------------------------------------------------
1080
- else if(lw == PACK8("er")) {
1081
- __offset += 2;
1082
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1083
- w = load_u64(buf + __offset);
1084
- lw = ascii_lower_u64(w) & MASK_U64_3BYTE;
1085
- if (lw == PACK8("ver")) {
1086
- __offset += 3;
1087
- if (buf[__offset] == ':') {
1088
- hdrId = HDR_SERVER;
1089
- state = ST_HN_SPACE;
1090
- continue;
1091
- }
1092
- }
1093
- }
1094
-
1095
- // -------------------------------------------------
1096
- // set-cookie
1097
- // -------------------------------------------------
1098
- else if(lw == PACK8("et")) {
1099
- __offset += 2;
1100
- if (__offset + 7 > total) return FLAG_UNTERMINATED_HEADERS;
1101
- w = load_u64(buf + __offset);
1102
- lw = ascii_lower_u64(w) & MASK_U64_7BYTE;
1103
-
1104
- if (lw == PACK8("-cookie")) {
1105
- __offset += 7;
1106
- if (buf[__offset] == ':') {
1107
- hdrId = HDR_SET_COOKIE;
1108
- state = ST_HN_SPACE;
1109
- continue;
1110
- }
1111
- }
1112
- }
1113
-
1114
- state = ST_HN_UNKNOWN;
1115
- break;
1116
- }
1117
-
1118
- // ================= T =================
1119
- case ST_HN_T: {
1120
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1121
- uint8_t lv = ascii_lower(buf[__offset]);
1122
-
1123
- // -------------------------------------------------
1124
- // te → TE
1125
- // -------------------------------------------------
1126
- if (lv == 'e') {
1127
- __offset++;
1128
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1129
-
1130
- char c = buf[__offset];
1131
- if (c == ':') {
1132
- hdrMergeable = true;
1133
- hdrId = HDR_TE;
1134
- state = ST_HN_SPACE;
1135
- continue;
1136
- }
1137
- }
1138
-
1139
- // -------------------------------------------------
1140
- // tr*
1141
- // -------------------------------------------------
1142
- else if (lv == 'r') {
1143
- if (__offset + 3 >= total) return FLAG_UNTERMINATED_HEADERS;
1144
- uint64_t w = load_u64(buf + (++__offset));
1145
- uint64_t lw = ascii_lower_u64(w);
1146
- lw = lw & MASK_U64_2BYTE;
1147
-
1148
- // ---------------------------------------------
1149
- // tran*
1150
- // ---------------------------------------------
1151
- if (lw == PACK8("an")) {
1152
- __offset += 2;
1153
- if (__offset + 13 > total) return FLAG_UNTERMINATED_HEADERS;
1154
- Pack128 P_SFER_ENCODING_ = PACK16_13('s','f','e','r','-','e','n','c','o','d','i','n','g');
1155
- uint128_t v = load_u128(buf + (__offset));
1156
- v = ascii_lower_u128(v);
1157
-
1158
- // -----------------------------------------
1159
- // tran* → transfer-encoding
1160
- // -----------------------------------------
1161
- if (simd_eq_n(v, load_const128(P_SFER_ENCODING_), 13)) {
1162
- __offset += 13;
1163
- if (buf[__offset] == ':') {
1164
- if (outHeaders->Has("transfer-encoding"))
1165
- return FLAG_DUPLICATE_SINGLE_HEADER;
1166
- if (outHeaders->Has("content-length"))
1167
- return FLAG_BAD_REQUEST;
1168
-
1169
- hdrId = HDR_TRANSFER_ENCODING;
1170
- state = ST_HN_SPACE;
1171
- continue;
1172
- }
1173
- }
1174
- }
1175
-
1176
- // -----------------------------------------
1177
- // trai* → trailer
1178
- // -----------------------------------------
1179
- else if(lw == PACK8("ai")) {
1180
- __offset += 2;
1181
- if (__offset + 3 > total) return FLAG_UNTERMINATED_HEADERS;
1182
-
1183
- w = load_u64(buf + __offset);
1184
- lw = ascii_lower_u64(w);
1185
-
1186
- // "ler"
1187
- if ((lw & MASK_U64_3BYTE) == PACK8("ler")) {
1188
- __offset += 4;
1189
- if (buf[__offset] == ':') {
1190
- hdrMergeable = true;
1191
- hdrId = HDR_TRAILER;
1192
- state = ST_HN_SPACE;
1193
- continue;
1194
- }
1195
- }
1196
- }
1197
- }
1198
-
1199
- state = ST_HN_UNKNOWN;
1200
- break;
1201
- }
1202
-
1203
- // ================= U =================
1204
- case ST_HN_U: {
1205
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1206
- uint8_t lv = ascii_lower(buf[__offset]);
1207
-
1208
- if (lv == 's') {
1209
- __offset++;
1210
- if (__offset + 8 > total) return FLAG_UNTERMINATED_HEADERS;
1211
- uint64_t w = load_u64(buf + __offset);
1212
- uint64_t lw = ascii_lower_u64(w);
1213
-
1214
- if (lw == PACK8("er-agent")) {
1215
- __offset += 8;
1216
- if (buf[__offset] == ':') {
1217
- if (outHeaders->Has("user-agent"))
1218
- return FLAG_DUPLICATE_SINGLE_HEADER;
1219
- hdrId = HDR_USER_AGENT;
1220
- state = ST_HN_SPACE;
1221
- continue;
1222
- }
1223
- }
1224
- }
1225
-
1226
- // -------------------------------------------------
1227
- // upgrade
1228
- // -------------------------------------------------
1229
- else if (lv == 'p') {
1230
- __offset++;
1231
- if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
1232
- uint64_t w = load_u64(buf + __offset);
1233
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
1234
-
1235
- if (lw == PACK8("grade")) {
1236
- __offset += 5;
1237
- if (buf[__offset] == ':') {
1238
- hdrId = HDR_UPGRADE;
1239
- hdrMergeable = true;
1240
- state = ST_HN_SPACE;
1241
- continue;
1242
- }
1243
- }
1244
- }
1245
-
1246
- state = ST_HN_UNKNOWN;
1247
- break;
1248
- }
1249
-
1250
- // ================= V =================
1251
- case ST_HN_V: {
1252
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
1253
- uint64_t w = load_u64(buf + __offset);
1254
- uint64_t lw = ascii_lower_u64(w) % MASK_U64_2BYTE;
1255
-
1256
- // -------------------------------------------------
1257
- // via
1258
- // -------------------------------------------------
1259
- if (lw == PACK8("ia")) {
1260
- __offset += 2;
1261
- if (buf[__offset] == ':') {
1262
- hdrId = HDR_VIA;
1263
- state = ST_HN_SPACE;
1264
- continue;
1265
- }
1266
- }
1267
-
1268
- // -------------------------------------------------
1269
- // vary
1270
- // -------------------------------------------------
1271
- else if(lw == PACK8("ar")) {
1272
- __offset += 2;
1273
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1274
- uint8_t lv = ascii_lower(buf[__offset]);
1275
-
1276
- if (lv == 'y') {
1277
- __offset += 1;
1278
- if (buf[__offset] == ':') {
1279
- hdrId = HDR_VARY;
1280
- state = ST_HN_SPACE;
1281
- continue;
1282
- }
1283
- }
1284
- }
1285
-
1286
- state = ST_HN_UNKNOWN;
1287
- break;
1288
- }
1289
-
1290
- // ================= W =================
1291
- case ST_HN_W: {
1292
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1293
- uint8_t lv = ascii_lower(buf[__offset]);
1294
-
1295
- if (lv == 'w') {
1296
- __offset++;
1297
- if (__offset + 14 > total) return FLAG_UNTERMINATED_HEADERS;
1298
- Pack128 P_W_AUTHENTICATE_ = PACK16_14('w','-','a','u','t','h','e','n','t','i','c','a','t','e');
1299
- uint128_t v = load_u128(buf + (__offset));
1300
- v = ascii_lower_u128(v);
1301
-
1302
- // -----------------------------------------
1303
- // ww* → www-authenticate
1304
- // -----------------------------------------
1305
- if (simd_eq_n(v, load_const128(P_W_AUTHENTICATE_), 14)) {
1306
- __offset += 14;
1307
- if (buf[__offset] == ':') {
1308
- hdrId = HDR_WWW_AUTHENTICATE;
1309
- state = ST_HN_SPACE;
1310
- continue;
1311
- }
1312
- }
1313
- }
1314
-
1315
- // -------------------------------------------------
1316
- // warning
1317
- // -------------------------------------------------
1318
- else if(lv == 'a') {
1319
- __offset++;
1320
- if (__offset + 5 > total) return FLAG_UNTERMINATED_HEADERS;
1321
- uint64_t w = load_u64(buf + __offset);
1322
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_5BYTE;
1323
-
1324
- if (lw == PACK8("rning")) {
1325
- __offset += 5;
1326
- if (buf[__offset] == ':') {
1327
- hdrId = HDR_WARNING;
1328
- state = ST_HN_SPACE;
1329
- continue;
1330
- }
1331
- }
1332
- }
1333
-
1334
- state = ST_HN_UNKNOWN;
1335
- break;
1336
- }
1337
-
1338
- // ================= X =================
1339
- case ST_HN_X: {
1340
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
1341
- uint64_t w = load_u64(buf + __offset);
1342
- uint64_t lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
1343
-
1344
- if (lw == PACK8("-f")) {
1345
- __offset += 2;
1346
- // orwarded-for
1347
- // orwarded-pro
1348
- // orwarded-hos
1349
- if (__offset + 12 > total) return FLAG_UNTERMINATED_HEADERS;
1350
-
1351
- uint128_t v = load_u128(buf + (__offset));
1352
- v = ascii_lower_u128(v);
1353
-
1354
- Pack128 P_ORWARDED_FOR = PACK16_12('o','r','w','a','r','d','e','d','-','f','o','r');
1355
- Pack128 P_ORWARDED_PRO = PACK16_12('o','r','w','a','r','d','e','d','-','p','r','o');
1356
- Pack128 P_ORWARDED_HOS = PACK16_12('o','r','w','a','r','d','e','d','-','h','o','s');
1357
-
1358
- if (simd_eq_n(v, load_const128(P_ORWARDED_FOR), 12)) {
1359
- __offset += 12;
1360
- if (buf[__offset] == ':') {
1361
- hdrId = HDR_X_FORWARDED_FOR;
1362
- state = ST_HN_SPACE;
1363
- continue;
1364
- }
1365
- }
1366
-
1367
- else if (simd_eq_n(v, load_const128(P_ORWARDED_HOS), 12)) {
1368
- __offset += 12;
1369
- if (__offset >= total) return FLAG_UNTERMINATED_HEADERS;
1370
- uint8_t v = ascii_lower(buf[__offset]);
1371
-
1372
- if (v == 't') {
1373
- __offset++;
1374
- if (buf[__offset] == ':') {
1375
- hdrId = HDR_X_FORWARDED_HOST;
1376
- state = ST_HN_SPACE;
1377
- continue;
1378
- }
1379
- }
1380
- }
1381
-
1382
- else if (simd_eq_n(v, load_const128(P_ORWARDED_PRO), 12)) {
1383
- __offset += 12;
1384
- if (__offset + 2 > total) return FLAG_UNTERMINATED_HEADERS;
1385
- w = load_u64(buf + __offset);
1386
- lw = ascii_lower_u64(w) & MASK_U64_2BYTE;
1387
- if (lw == PACK8("to")) {
1388
- __offset += 2;
1389
- if (buf[__offset] == ':') {
1390
- hdrId = HDR_X_FORWARDED_PROTO;
1391
- state = ST_HN_SPACE;
1392
- continue;
1393
- }
1394
- }
1395
- }
1396
- }
1397
-
1398
- else if(lw == PACK8("-r")) {
1399
- __offset += 2;
1400
- if (__offset + 6 > total) return FLAG_UNTERMINATED_HEADERS;
1401
- w = load_u64(buf + __offset);
1402
- lw = ascii_lower_u64(w) & MASK_U64_6BYTE;
1403
-
1404
- if (lw == PACK8("eal-ip")) {
1405
- __offset +=6;
1406
- if (buf[__offset] == ':') {
1407
- hdrId = HDR_X_REAL_IP;
1408
- state = ST_HN_SPACE;
1409
- continue;
1410
- }
1411
- }
1412
- }
1413
-
1414
- state = ST_HN_UNKNOWN;
1415
- break;
1416
- }
1417
-
1418
- // =============== VALUE ===============
1419
- case ST_HV_CONCAT: {
1420
- // ---- Skip leading OWS ----
1421
- while (__offset < total &&
1422
- (buf[__offset] == ' ' || buf[__offset] == '\t'))
1423
- __offset++;
1424
-
1425
- // ---- Scan header value ----
1426
- auto hv = std::make_unique<std::string>();
1427
- FlagBits ret = HEADERS[hdrId].value_parser(
1428
- buf, &__offset, total, maxHeaderValueSize, hv
1429
- );
1430
-
1431
- if (ret != FLAG_OK) {
1432
- return ret;
1433
- }
1434
-
1435
- // ---- Consume CRLF or LF ----
1436
- if (buf[__offset] == '\r') {
1437
- if (__offset + 1 >= total || buf[__offset + 1] != '\n')
1438
- return FLAG_INVALID_HEADER_VALUE;
1439
- __offset += 2;
1440
- }
1441
- else if (buf[__offset] == '\n') {
1442
- __offset += 1;
1443
- }
1444
-
1445
- // ---- Commit offset for next header ----
1446
- *offset = __offset;
1447
-
1448
- // ---- Store header value ----
1449
- auto value = Napi::String::New(
1450
- env,
1451
- hv->c_str()
1452
- );
1453
-
1454
- if (hdrId == HDR_UNKNOWN) {
1455
- outHeaders->Set(headerUnknownName, value);
1456
- } else {
1457
- const char* name = HEADERS[hdrId].name;
1458
-
1459
- if (hdrMergeable && outHeaders->Has(name)) {
1460
- auto oldVal =
1461
- outHeaders->Get(name)
1462
- .As<Napi::String>()
1463
- .Utf8Value();
1464
-
1465
- outHeaders->Set(
1466
- name,
1467
- Napi::String::New(
1468
- env,
1469
- oldVal + ", " + value.Utf8Value()
1470
- )
1471
- );
1472
- hdrMergeable = false;
1473
- } else {
1474
- outHeaders->Set(name, value);
1475
- }
1476
- }
1477
-
1478
- // ---- HEADER BLOCK END? (CRLF CRLF) ----
1479
-
1480
- if (__offset + 1 < total &&
1481
- buf[__offset] == '\r' &&
1482
- buf[__offset + 1] == '\n') {
1483
-
1484
- // consume final CRLF
1485
- *offset = __offset + 2;
1486
- return FLAG_OK;
1487
- }
1488
-
1489
-
1490
- // ---- Reset per-header state ----
1491
- hdrId = HDR_UNKNOWN;
1492
- hdrMergeable = false;
1493
- headerUnknownName.clear();
1494
-
1495
- // ---- Continue parsing next header ----
1496
- state = ST_STARTUP;
1497
- continue;
1498
- }
1499
- } // switch
1500
- }
1501
-
1502
- return FLAG_OK;
1503
- }