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.
@@ -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
+ }