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;