nxt_http_parse.c (16:c382e548cbb6) nxt_http_parse.c (19:385969e9f503)
1
2/*
3 * Copyright (C) NGINX, Inc.
4 * Copyright (C) Valentin V. Bartenev
5 */
6
7#include <nxt_main.h>
8
1
2/*
3 * Copyright (C) NGINX, Inc.
4 * Copyright (C) Valentin V. Bartenev
5 */
6
7#include <nxt_main.h>
8
9#ifdef __SSE4_2__
10#include <x86intrin.h>
11#endif
12
9
13
14typedef struct {
15 nxt_http_field_handler_t handler;
16 uintptr_t data;
17 union {
18 uint8_t str[8];
19 uint64_t ui64;
20 } key[];
21} nxt_http_fields_hash_entry_t;

--- 101 unchanged lines hidden (view full) ---

123 }
124
125 *pos = p;
126
127 return trap;
128}
129
130
10typedef struct {
11 nxt_http_field_handler_t handler;
12 uintptr_t data;
13 union {
14 uint8_t str[8];
15 uint64_t ui64;
16 } key[];
17} nxt_http_fields_hash_entry_t;

--- 101 unchanged lines hidden (view full) ---

119 }
120
121 *pos = p;
122
123 return trap;
124}
125
126
131#ifdef __SSE4_2__
132
133nxt_inline nxt_http_target_traps_e
134nxt_http_parse_target_rest(u_char **pos, u_char *end)
135{
136 int n;
137 u_char *p;
138 nxt_uint_t i;
139
140 static const u_char stop_chars[16] nxt_aligned(16) = " #\r\n";
141
142 __m128i pattern = _mm_load_si128((__m128i *) stop_chars);
143
144 p = *pos;
145
146 for (n = (end - p) / 16; nxt_fast_path(n != 0); n--) {
147
148 __m128i test = _mm_loadu_si128((__m128i *) p);
149
150 i = _mm_cmpistri(pattern, test, _SIDD_LEAST_SIGNIFICANT
151 | _SIDD_CMP_EQUAL_ANY
152 | _SIDD_UBYTE_OPS);
153
154 p += i;
155
156 if (i != 16) {
157 *pos = p;
158 return nxt_http_target_chars[*p];
159 }
160 }
161
162 *pos = p;
163
164 return nxt_http_parse_target(pos, end);
165}
166
167#else
168#define nxt_http_parse_target_rest nxt_http_parse_target
169#endif
170
171
172nxt_int_t
173nxt_http_parse_request(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b)
174{
175 nxt_int_t rc;
176
177 if (rp->handler == NULL) {
178 rp->handler = &nxt_http_parse_request_line;
179 }

--- 73 unchanged lines hidden (view full) ---

253 p++;
254
255 if (nxt_slow_path(p == end)) {
256 return NXT_AGAIN;
257 }
258
259 /* target */
260
127nxt_int_t
128nxt_http_parse_request(nxt_http_request_parse_t *rp, nxt_buf_mem_t *b)
129{
130 nxt_int_t rc;
131
132 if (rp->handler == NULL) {
133 rp->handler = &nxt_http_parse_request_line;
134 }

--- 73 unchanged lines hidden (view full) ---

208 p++;
209
210 if (nxt_slow_path(p == end)) {
211 return NXT_AGAIN;
212 }
213
214 /* target */
215
261 nxt_prefetch(&nxt_http_target_chars[' ']);
262 nxt_prefetch(&nxt_http_target_chars['@']);
263 nxt_prefetch(&nxt_http_target_chars['`']);
264
265 ch = *p;
266
267 if (nxt_slow_path(ch != '/')) {
268 rc = nxt_http_parse_unusual_target(rp, &p, end);
269
270 if (nxt_slow_path(rc != NXT_OK)) {
271 return rc;
272 }

--- 59 unchanged lines hidden (view full) ---

332 nxt_unreachable();
333 }
334
335rest_of_target:
336
337 for ( ;; ) {
338 p++;
339
216 ch = *p;
217
218 if (nxt_slow_path(ch != '/')) {
219 rc = nxt_http_parse_unusual_target(rp, &p, end);
220
221 if (nxt_slow_path(rc != NXT_OK)) {
222 return rc;
223 }

--- 59 unchanged lines hidden (view full) ---

283 nxt_unreachable();
284 }
285
286rest_of_target:
287
288 for ( ;; ) {
289 p++;
290
340 trap = nxt_http_parse_target_rest(&p, end);
291 trap = nxt_http_parse_target(&p, end);
341
342 switch (trap) {
343 case NXT_HTTP_TARGET_SPACE:
344 rp->target_end = p;
345 goto space_after_target;
346
347 case NXT_HTTP_TARGET_HASH:
348 rp->complex_target = 1;

--- 122 unchanged lines hidden (view full) ---

471 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
472 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
473 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
474 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
475
476 p = *pos;
477
478 size = end - p;
292
293 switch (trap) {
294 case NXT_HTTP_TARGET_SPACE:
295 rp->target_end = p;
296 goto space_after_target;
297
298 case NXT_HTTP_TARGET_HASH:
299 rp->complex_target = 1;

--- 122 unchanged lines hidden (view full) ---

422 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
423 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
424 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
425 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
426
427 p = *pos;
428
429 size = end - p;
430 i = rp->offset;
479
431
480 for (i = rp->offset; i != size; i++) {
432#define nxt_http_parse_field_name_step \
433 { \
434 ch = p[i]; \
435 c = normal[ch]; \
436 \
437 if (nxt_slow_path(c == '\0')) { \
438 goto name_end; \
439 } \
440 \
441 rp->field_name_key.str[i % 32] = c; \
442 i++; \
443 }
481
444
482 ch = p[i];
445 while (nxt_fast_path(size - i >= 8)) {
446 nxt_http_parse_field_name_step
447 nxt_http_parse_field_name_step
448 nxt_http_parse_field_name_step
449 nxt_http_parse_field_name_step
483
450
484 c = normal[ch];
451 nxt_http_parse_field_name_step
452 nxt_http_parse_field_name_step
453 nxt_http_parse_field_name_step
454 nxt_http_parse_field_name_step
455 }
485
456
486 if (nxt_fast_path(c != '\0')) {
487 rp->field_name_key.str[i % 32] = c;
488 continue;
489 }
457 while (nxt_fast_path(i != size)) {
458 nxt_http_parse_field_name_step
459 }
490
460
491 if (nxt_fast_path(ch == ':')) {
492 if (nxt_slow_path(i == 0)) {
493 return NXT_ERROR;
494 }
461#undef nxt_http_parse_field_name_step
495
462
496 *pos = &p[i] + 1;
463 rp->offset = i;
464 rp->handler = &nxt_http_parse_field_name;
497
465
498 rp->field_name.start = p;
499 rp->field_name.length = i;
466 return NXT_AGAIN;
500
467
501 rp->offset = 0;
468name_end:
502
469
503 return nxt_http_parse_field_value(rp, pos, end);
470 if (nxt_fast_path(ch == ':')) {
471 if (nxt_slow_path(i == 0)) {
472 return NXT_ERROR;
504 }
505
473 }
474
506 *pos = &p[i];
475 *pos = &p[i] + 1;
507
476
508 rp->field_name.length = 0;
477 rp->field_name.start = p;
478 rp->field_name.length = i;
509
479
510 return nxt_http_parse_field_end(rp, pos, end);
480 rp->offset = 0;
481
482 return nxt_http_parse_field_value(rp, pos, end);
511 }
512
483 }
484
513 rp->offset = i;
514 rp->handler = &nxt_http_parse_field_name;
485 *pos = &p[i];
515
486
516 return NXT_AGAIN;
487 rp->field_name.length = 0;
488
489 return nxt_http_parse_field_end(rp, pos, end);
517}
518
519
520static nxt_int_t
521nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
522 u_char *end)
523{
524 u_char *p, ch;

--- 54 unchanged lines hidden (view full) ---

579 return nxt_http_parse_field_end(rp, pos, end);
580}
581
582
583static u_char *
584nxt_http_lookup_field_end(u_char *p, u_char *end)
585{
586 nxt_uint_t n;
490}
491
492
493static nxt_int_t
494nxt_http_parse_field_value(nxt_http_request_parse_t *rp, u_char **pos,
495 u_char *end)
496{
497 u_char *p, ch;

--- 54 unchanged lines hidden (view full) ---

552 return nxt_http_parse_field_end(rp, pos, end);
553}
554
555
556static u_char *
557nxt_http_lookup_field_end(u_char *p, u_char *end)
558{
559 nxt_uint_t n;
587#ifdef __SSE4_2__
588 nxt_uint_t i;
589
560
590 static const u_char end_chars[16] nxt_aligned(16) = "\r\n";
591
592 __m128i pattern = _mm_load_si128((__m128i *) end_chars);
593
594 for (n = (end - p) / 16; nxt_fast_path(n != 0); n--) {
595
596 __m128i test = _mm_loadu_si128((__m128i *) p);
597
598 i = _mm_cmpistri(pattern, test, _SIDD_LEAST_SIGNIFICANT
599 | _SIDD_CMP_EQUAL_ANY
600 | _SIDD_UBYTE_OPS);
601
602 p += i;
603
604 if (i != 16) {
605 return p;
606 }
607 }
608#endif
609
610#define nxt_http_lookup_field_end_step \
611 { \
561#define nxt_http_lookup_field_end_step \
562 { \
612 if (nxt_slow_path(*p <= '\r')) { \
563 if (nxt_slow_path(*p < 0x10)) { \
613 return p; \
614 } \
615 \
616 p++; \
617 }
618
564 return p; \
565 } \
566 \
567 p++; \
568 }
569
619 for (n = (end - p) / 8; nxt_fast_path(n != 0); n--) {
570 for (n = (end - p) / 16; nxt_fast_path(n != 0); n--) {
620 nxt_http_lookup_field_end_step
621 nxt_http_lookup_field_end_step
622 nxt_http_lookup_field_end_step
623 nxt_http_lookup_field_end_step
624
625 nxt_http_lookup_field_end_step
626 nxt_http_lookup_field_end_step
627 nxt_http_lookup_field_end_step
628 nxt_http_lookup_field_end_step
571 nxt_http_lookup_field_end_step
572 nxt_http_lookup_field_end_step
573 nxt_http_lookup_field_end_step
574 nxt_http_lookup_field_end_step
575
576 nxt_http_lookup_field_end_step
577 nxt_http_lookup_field_end_step
578 nxt_http_lookup_field_end_step
579 nxt_http_lookup_field_end_step
580
581 nxt_http_lookup_field_end_step
582 nxt_http_lookup_field_end_step
583 nxt_http_lookup_field_end_step
584 nxt_http_lookup_field_end_step
585
586 nxt_http_lookup_field_end_step
587 nxt_http_lookup_field_end_step
588 nxt_http_lookup_field_end_step
589 nxt_http_lookup_field_end_step
629 }
630
590 }
591
631 switch (end - p) {
632 case 7:
592 for (n = (end - p) / 4; nxt_fast_path(n != 0); n--) {
633 nxt_http_lookup_field_end_step
593 nxt_http_lookup_field_end_step
634 case 6:
635 nxt_http_lookup_field_end_step
594 nxt_http_lookup_field_end_step
636 case 5:
637 nxt_http_lookup_field_end_step
595 nxt_http_lookup_field_end_step
638 case 4:
639 nxt_http_lookup_field_end_step
596 nxt_http_lookup_field_end_step
597 }
598
599 switch (end - p) {
640 case 3:
641 nxt_http_lookup_field_end_step
642 case 2:
643 nxt_http_lookup_field_end_step
644 case 1:
645 nxt_http_lookup_field_end_step
646 case 0:
647 break;

--- 26 unchanged lines hidden (view full) ---

674 }
675 }
676
677 if (nxt_fast_path(*p == '\n')) {
678 *pos = p + 1;
679
680 if (rp->field_name.length != 0) {
681 entry = nxt_http_fields_hash_lookup(rp->hash,
600 case 3:
601 nxt_http_lookup_field_end_step
602 case 2:
603 nxt_http_lookup_field_end_step
604 case 1:
605 nxt_http_lookup_field_end_step
606 case 0:
607 break;

--- 26 unchanged lines hidden (view full) ---

634 }
635 }
636
637 if (nxt_fast_path(*p == '\n')) {
638 *pos = p + 1;
639
640 if (rp->field_name.length != 0) {
641 entry = nxt_http_fields_hash_lookup(rp->hash,
682 rp->field_name_key.ui64,
683 &rp->field_name);
642 rp->field_name_key.ui64,
643 &rp->field_name);
684
685 if (entry != NULL) {
686 rc = entry->handler(rp->ctx, &rp->field_name, &rp->field_value,
687 entry->data);
688
689 if (nxt_slow_path(rc != NXT_OK)) {
690 return NXT_ERROR;
691 }

--- 198 unchanged lines hidden ---
644
645 if (entry != NULL) {
646 rc = entry->handler(rp->ctx, &rp->field_name, &rp->field_value,
647 entry->data);
648
649 if (nxt_slow_path(rc != NXT_OK)) {
650 return NXT_ERROR;
651 }

--- 198 unchanged lines hidden ---