Mercurial > hg > nginx-quic
comparison src/http/v3/ngx_http_v3_request.c @ 7692:268f4389130d quic
Refactored HTTP/3 parser.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 18 Mar 2020 13:46:35 +0300 |
parents | 1307308c3cf1 |
children | 31f7c697b6d9 |
comparison
equal
deleted
inserted
replaced
7691:714a19dba6af | 7692:268f4389130d |
---|---|
6 | 6 |
7 | 7 |
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 | |
12 | |
13 #define NGX_HTTP_V3_FRAME_DATA 0x00 | |
14 #define NGX_HTTP_V3_FRAME_HEADERS 0x01 | |
15 #define NGX_HTTP_V3_FRAME_CANCEL_PUSH 0x03 | |
16 #define NGX_HTTP_V3_FRAME_SETTINGS 0x04 | |
17 #define NGX_HTTP_V3_FRAME_PUSH_PROMISE 0x05 | |
18 #define NGX_HTTP_V3_FRAME_GOAWAY 0x07 | |
19 #define NGX_HTTP_V3_FRAME_MAX_PUSH_ID 0x0d | |
20 | 11 |
21 | 12 |
22 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, | 13 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, |
23 ngx_str_t *name, ngx_str_t *value); | 14 ngx_str_t *name, ngx_str_t *value); |
24 | 15 |
44 { ngx_string("PATCH"), NGX_HTTP_PATCH }, | 35 { ngx_string("PATCH"), NGX_HTTP_PATCH }, |
45 { ngx_string("TRACE"), NGX_HTTP_TRACE } | 36 { ngx_string("TRACE"), NGX_HTTP_TRACE } |
46 }; | 37 }; |
47 | 38 |
48 | 39 |
40 ngx_int_t | |
41 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b) | |
42 { | |
43 ngx_int_t rc; | |
44 ngx_str_t *name, *value; | |
45 ngx_connection_t *c; | |
46 ngx_http_v3_parse_headers_t *st; | |
47 enum { | |
48 sw_start = 0, | |
49 sw_prev, | |
50 sw_headers, | |
51 sw_last, | |
52 sw_done | |
53 }; | |
54 | |
55 c = r->connection; | |
56 st = r->h3_parse; | |
57 | |
58 if (st == NULL) { | |
59 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header"); | |
60 | |
61 st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_headers_t)); | |
62 if (st == NULL) { | |
63 goto failed; | |
64 } | |
65 | |
66 r->h3_parse = st; | |
67 } | |
68 | |
69 switch (r->state) { | |
70 | |
71 case sw_prev: | |
72 r->state = sw_headers; | |
73 return NGX_OK; | |
74 | |
75 case sw_done: | |
76 goto done; | |
77 | |
78 case sw_last: | |
79 r->state = sw_done; | |
80 return NGX_OK; | |
81 | |
82 default: | |
83 break; | |
84 } | |
85 | |
86 for ( /* void */ ; b->pos < b->last; b->pos++) { | |
87 | |
88 rc = ngx_http_v3_parse_headers(c, st, *b->pos); | |
89 | |
90 if (rc == NGX_ERROR) { | |
91 goto failed; | |
92 } | |
93 | |
94 if (rc == NGX_AGAIN) { | |
95 continue; | |
96 } | |
97 | |
98 name = &st->header_rep.header.name; | |
99 value = &st->header_rep.header.value; | |
100 | |
101 if (r->state == sw_start | |
102 && ngx_http_v3_process_pseudo_header(r, name, value) != NGX_OK) | |
103 { | |
104 if (rc == NGX_DONE) { | |
105 r->state = sw_last; | |
106 } else { | |
107 r->state = sw_prev; | |
108 } | |
109 | |
110 } else if (rc == NGX_DONE) { | |
111 r->state = sw_done; | |
112 } | |
113 | |
114 if (r->state == sw_start) { | |
115 continue; | |
116 } | |
117 | |
118 r->header_name_start = name->data; | |
119 r->header_name_end = name->data + name->len; | |
120 r->header_start = value->data; | |
121 r->header_end = value->data + value->len; | |
122 r->header_hash = ngx_hash_key(name->data, name->len); | |
123 | |
124 /* XXX r->lowcase_index = i; */ | |
125 | |
126 return NGX_OK; | |
127 } | |
128 | |
129 return NGX_AGAIN; | |
130 | |
131 failed: | |
132 | |
133 return r->state == sw_start ? NGX_HTTP_PARSE_INVALID_REQUEST | |
134 : NGX_HTTP_PARSE_INVALID_HEADER; | |
135 | |
136 done: | |
137 | |
138 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done"); | |
139 | |
140 return NGX_HTTP_PARSE_HEADER_DONE; | |
141 } | |
142 | |
143 #if 0 | |
49 ngx_int_t | 144 ngx_int_t |
50 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, ngx_uint_t pseudo) | 145 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, ngx_uint_t pseudo) |
51 { | 146 { |
52 u_char *p, ch; | 147 u_char *p, ch; |
53 ngx_str_t name, value; | 148 ngx_str_t name, value; |
165 if ((length & 0xc00000) != 0x800000) { | 260 if ((length & 0xc00000) != 0x800000) { |
166 state = sw_length_3; | 261 state = sw_length_3; |
167 break; | 262 break; |
168 } | 263 } |
169 | 264 |
170 /* fall through */ | 265 length &= 0x3fffff; |
266 state = sw_header_block; | |
267 break; | |
171 | 268 |
172 case sw_length_3: | 269 case sw_length_3: |
173 | 270 |
174 length &= 0x3fffff; | 271 length = (length << 8) + ch; |
272 length &= 0x3fffffff; | |
175 state = sw_header_block; | 273 state = sw_header_block; |
176 break; | 274 break; |
177 | 275 |
178 case sw_header_block: | 276 case sw_header_block: |
179 | 277 |
565 | 663 |
566 failed: | 664 failed: |
567 | 665 |
568 return NGX_HTTP_PARSE_INVALID_REQUEST; | 666 return NGX_HTTP_PARSE_INVALID_REQUEST; |
569 } | 667 } |
668 #endif | |
570 | 669 |
571 | 670 |
572 static ngx_int_t | 671 static ngx_int_t |
573 ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, | 672 ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, |
574 ngx_str_t *value) | 673 ngx_str_t *value) |
575 { | 674 { |
576 ngx_uint_t i; | 675 ngx_uint_t i; |
577 ngx_connection_t *c; | 676 ngx_connection_t *c; |
677 | |
678 if (name->len == 0 || name->data[0] != ':') { | |
679 return NGX_DECLINED; | |
680 } | |
578 | 681 |
579 c = r->connection; | 682 c = r->connection; |
580 | 683 |
581 if (name->len == 7 && ngx_strncmp(name->data, ":method", 7) == 0) { | 684 if (name->len == 7 && ngx_strncmp(name->data, ":method", 7) == 0) { |
582 r->method_start = value->data; | 685 r->method_start = value->data; |
633 "http3 authority \"%V\"", value); | 736 "http3 authority \"%V\"", value); |
634 | 737 |
635 return NGX_OK; | 738 return NGX_OK; |
636 } | 739 } |
637 | 740 |
638 if (name->len && name->data[0] == ':') { | 741 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
639 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | 742 "http3 unknown pseudo header \"%V\" \"%V\"", name, value); |
640 "http3 unknown pseudo header \"%V\" \"%V\"", | 743 |
641 name, value); | 744 return NGX_OK; |
642 return NGX_OK; | |
643 } | |
644 | |
645 return NGX_DONE; | |
646 } | 745 } |
647 | 746 |
648 | 747 |
649 ngx_chain_t * | 748 ngx_chain_t * |
650 ngx_http_v3_create_header(ngx_http_request_t *r) | 749 ngx_http_v3_create_header(ngx_http_request_t *r) |
787 /* :status: 200 */ | 886 /* :status: 200 */ |
788 *b->last = 0x70; | 887 *b->last = 0x70; |
789 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 4); | 888 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 4); |
790 *b->last = 0; | 889 *b->last = 0; |
791 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 3, 7); | 890 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 3, 7); |
792 b->last = ngx_sprintf(b->last, "%03ui ", r->headers_out.status); | 891 b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); |
793 } | 892 } |
794 | 893 |
795 if (r->headers_out.server == NULL) { | 894 if (r->headers_out.server == NULL) { |
796 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | 895 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { |
797 p = (u_char *) NGINX_VER; | 896 p = (u_char *) NGINX_VER; |