Mercurial > hg > nginx
annotate src/http/v3/ngx_http_v3_streams.c @ 8226:268f4389130d quic
Refactored HTTP/3 parser.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Wed, 18 Mar 2020 13:46:35 +0300 |
parents | 38c0898b6df7 |
children | ac41c53e446d |
rev | line source |
---|---|
8215 | 1 |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
13 typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
14 u_char ch); |
8215 | 15 |
16 | |
17 typedef struct { | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
18 uint32_t signature; /* QSTR */ |
8215 | 19 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
20 ngx_http_v3_handler_pt handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
21 void *data; |
8215 | 22 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
23 ngx_uint_t type; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
24 ngx_uint_t client; /* unsigned client:1; */ |
8215 | 25 } ngx_http_v3_uni_stream_t; |
26 | |
27 | |
28 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | |
29 static void ngx_http_v3_uni_stream_cleanup(void *data); | |
30 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
31 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); |
8215 | 32 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, |
33 ngx_uint_t type); | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
34 static ngx_connection_t *ngx_http_v3_get_control(ngx_connection_t *c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
35 static ngx_connection_t *ngx_http_v3_get_encoder(ngx_connection_t *c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
36 static ngx_connection_t *ngx_http_v3_get_decoder(ngx_connection_t *c); |
8215 | 37 |
38 | |
39 void | |
40 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) | |
41 { | |
42 ngx_pool_cleanup_t *cln; | |
43 ngx_http_v3_uni_stream_t *us; | |
44 | |
45 c->log->connection = c->number; | |
46 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
47 /* XXX */ |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
48 (void) ngx_http_v3_get_control(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
49 (void) ngx_http_v3_get_encoder(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
50 (void) ngx_http_v3_get_decoder(c); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
51 |
8215 | 52 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
53 "http3 new uni stream id:0x%uxL", c->qs->id); |
8215 | 54 |
55 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
56 if (us == NULL) { | |
57 ngx_http_v3_close_uni_stream(c); | |
58 return; | |
59 } | |
60 | |
61 us->signature = NGX_HTTP_V3_STREAM; | |
62 us->client = 1; | |
63 us->type = (ngx_uint_t) -1; | |
64 | |
65 c->data = us; | |
66 | |
67 cln = ngx_pool_cleanup_add(c->pool, 0); | |
68 if (cln == NULL) { | |
69 ngx_http_v3_close_uni_stream(c); | |
70 return; | |
71 } | |
72 | |
73 cln->handler = ngx_http_v3_uni_stream_cleanup; | |
74 cln->data = c; | |
75 | |
76 c->read->handler = ngx_http_v3_read_uni_stream_type; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
77 ngx_http_v3_read_uni_stream_type(c->read); |
8215 | 78 } |
79 | |
80 | |
81 static void | |
82 ngx_http_v3_close_uni_stream(ngx_connection_t *c) | |
83 { | |
84 ngx_pool_t *pool; | |
85 | |
86 c->destroyed = 1; | |
87 | |
88 pool = c->pool; | |
89 | |
90 ngx_close_connection(c); | |
91 | |
92 ngx_destroy_pool(pool); | |
93 } | |
94 | |
95 | |
96 static void | |
97 ngx_http_v3_uni_stream_cleanup(void *data) | |
98 { | |
99 ngx_connection_t *c = data; | |
100 | |
101 ngx_http_v3_connection_t *h3c; | |
102 ngx_http_v3_uni_stream_t *us; | |
103 | |
104 us = c->data; | |
105 h3c = c->qs->parent->data; | |
106 | |
107 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); | |
108 | |
109 switch (us->type) { | |
110 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
111 case NGX_HTTP_V3_STREAM_ENCODER: |
8215 | 112 |
113 if (us->client) { | |
114 h3c->client_encoder = NULL; | |
115 } else { | |
116 h3c->server_encoder = NULL; | |
117 } | |
118 | |
119 break; | |
120 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
121 case NGX_HTTP_V3_STREAM_DECODER: |
8215 | 122 |
123 if (us->client) { | |
124 h3c->client_decoder = NULL; | |
125 } else { | |
126 h3c->server_decoder = NULL; | |
127 } | |
128 | |
129 break; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
130 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
131 case NGX_HTTP_V3_STREAM_CONTROL: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
132 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
133 if (us->client) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
134 h3c->client_control = NULL; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
135 } else { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
136 h3c->server_control = NULL; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
137 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
138 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
139 break; |
8215 | 140 } |
141 } | |
142 | |
143 | |
144 static void | |
145 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) | |
146 { | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
147 u_char ch; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
148 ssize_t n; |
8215 | 149 ngx_connection_t *c; |
150 ngx_http_v3_connection_t *h3c; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
151 ngx_http_v3_uni_stream_t *st; |
8215 | 152 |
153 c = rev->data; | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
154 st = c->data; |
8215 | 155 h3c = c->qs->parent->data; |
156 | |
157 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); | |
158 | |
159 while (rev->ready) { | |
160 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
161 n = c->recv(c, &ch, 1); |
8215 | 162 |
163 if (n == NGX_ERROR) { | |
164 goto failed; | |
165 } | |
166 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
167 if (n == NGX_AGAIN || n != 1) { |
8215 | 168 break; |
169 } | |
170 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
171 st->type = ch; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
172 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
173 switch (st->type) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
174 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
175 case NGX_HTTP_V3_STREAM_ENCODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
176 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
177 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
178 "http3 encoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
179 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
180 if (h3c->client_encoder) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
181 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
182 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
183 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
184 h3c->client_encoder = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
185 st->handler = ngx_http_v3_parse_encoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
186 n = sizeof(ngx_http_v3_parse_encoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
187 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
188 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
189 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
190 case NGX_HTTP_V3_STREAM_DECODER: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
191 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
192 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
193 "http3 decoder stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
194 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
195 if (h3c->client_decoder) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
196 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
197 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
198 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
199 h3c->client_decoder = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
200 st->handler = ngx_http_v3_parse_decoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
201 n = sizeof(ngx_http_v3_parse_decoder_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
202 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
203 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
204 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
205 case NGX_HTTP_V3_STREAM_CONTROL: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
206 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
207 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
208 "http3 control stream"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
209 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
210 if (h3c->client_control) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
211 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
212 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
213 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
214 h3c->client_control = c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
215 st->handler = ngx_http_v3_parse_control; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
216 n = sizeof(ngx_http_v3_parse_control_t); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
217 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
218 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
219 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
220 default: |
8215 | 221 |
222 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
223 "http3 stream 0x%02xi", st->type); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
224 n = 0; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
225 } |
8215 | 226 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
227 if (n) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
228 st->data = ngx_pcalloc(c->pool, n); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
229 if (st->data == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
230 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
231 } |
8215 | 232 } |
233 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
234 rev->handler = ngx_http_v3_uni_read_handler; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
235 ngx_http_v3_uni_read_handler(rev); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
236 return; |
8215 | 237 } |
238 | |
239 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
240 goto failed; | |
241 } | |
242 | |
243 return; | |
244 | |
245 failed: | |
246 | |
247 ngx_http_v3_close_uni_stream(c); | |
248 } | |
249 | |
250 | |
251 static void | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
252 ngx_http_v3_uni_read_handler(ngx_event_t *rev) |
8215 | 253 { |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
254 u_char buf[128]; |
8215 | 255 ssize_t n; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
256 ngx_int_t rc, i; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
257 ngx_connection_t *c; |
8215 | 258 ngx_http_v3_uni_stream_t *st; |
259 | |
260 c = rev->data; | |
261 st = c->data; | |
262 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
263 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); |
8215 | 264 |
265 while (rev->ready) { | |
266 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
267 n = c->recv(c, buf, sizeof(buf)); |
8215 | 268 |
269 if (n == NGX_ERROR || n == 0) { | |
270 goto failed; | |
271 } | |
272 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
273 if (n == NGX_AGAIN) { |
8215 | 274 break; |
275 } | |
276 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
277 if (st->handler == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
278 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
279 } |
8215 | 280 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
281 for (i = 0; i < n; i++) { |
8215 | 282 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
283 rc = st->handler(c, st->data, buf[i]); |
8215 | 284 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
285 if (rc == NGX_ERROR) { |
8215 | 286 goto failed; |
287 } | |
288 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
289 if (rc == NGX_DONE) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
290 goto done; |
8215 | 291 } |
292 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
293 /* rc == NGX_AGAIN */ |
8215 | 294 } |
295 } | |
296 | |
297 if (ngx_handle_read_event(rev, 0) != NGX_OK) { | |
298 goto failed; | |
299 } | |
300 | |
301 return; | |
302 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
303 done: |
8215 | 304 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
305 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read done"); |
8215 | 306 |
307 failed: | |
308 | |
309 ngx_http_v3_close_uni_stream(c); | |
310 } | |
311 | |
312 | |
313 /* XXX async & buffered stream writes */ | |
314 | |
315 static ngx_connection_t * | |
316 ngx_http_v3_create_uni_stream(ngx_connection_t *c, ngx_uint_t type) | |
317 { | |
318 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; | |
319 size_t n; | |
320 ngx_connection_t *sc; | |
321 ngx_pool_cleanup_t *cln; | |
322 ngx_http_v3_uni_stream_t *us; | |
323 | |
324 sc = ngx_quic_create_uni_stream(c->qs->parent); | |
325 if (sc == NULL) { | |
326 return NULL; | |
327 } | |
328 | |
329 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
330 "http3 create uni stream, type:%ui", type); | |
331 | |
332 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t)); | |
333 if (us == NULL) { | |
334 goto failed; | |
335 } | |
336 | |
337 us->signature = NGX_HTTP_V3_STREAM; | |
338 us->type = type; | |
339 sc->data = us; | |
340 | |
341 cln = ngx_pool_cleanup_add(sc->pool, 0); | |
342 if (cln == NULL) { | |
343 goto failed; | |
344 } | |
345 | |
346 cln->handler = ngx_http_v3_uni_stream_cleanup; | |
347 cln->data = sc; | |
348 | |
349 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; | |
350 | |
351 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
352 goto failed; | |
353 } | |
354 | |
355 return sc; | |
356 | |
357 failed: | |
358 | |
359 ngx_http_v3_close_uni_stream(sc); | |
360 | |
361 return NULL; | |
362 } | |
363 | |
364 | |
365 static ngx_connection_t * | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
366 ngx_http_v3_get_control(ngx_connection_t *c) |
8215 | 367 { |
368 ngx_http_v3_connection_t *h3c; | |
369 | |
370 h3c = c->qs->parent->data; | |
371 | |
372 if (h3c->server_encoder == NULL) { | |
373 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
374 NGX_HTTP_V3_STREAM_CONTROL); |
8215 | 375 } |
376 | |
377 return h3c->server_encoder; | |
378 } | |
379 | |
380 | |
381 static ngx_connection_t * | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
382 ngx_http_v3_get_encoder(ngx_connection_t *c) |
8215 | 383 { |
384 ngx_http_v3_connection_t *h3c; | |
385 | |
386 h3c = c->qs->parent->data; | |
387 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
388 if (h3c->server_encoder == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
389 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
390 NGX_HTTP_V3_STREAM_ENCODER); |
8215 | 391 } |
392 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
393 return h3c->server_encoder; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
394 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
395 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
396 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
397 static ngx_connection_t * |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
398 ngx_http_v3_get_decoder(ngx_connection_t *c) |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
399 { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
400 ngx_http_v3_connection_t *h3c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
401 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
402 h3c = c->qs->parent->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
403 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
404 if (h3c->server_encoder == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
405 h3c->server_encoder = ngx_http_v3_create_uni_stream(c, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
406 NGX_HTTP_V3_STREAM_DECODER); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
407 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
408 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
409 return h3c->server_encoder; |
8215 | 410 } |
411 | |
412 | |
413 ngx_int_t | |
414 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, | |
415 ngx_uint_t index, ngx_str_t *value) | |
416 { | |
417 u_char *p, buf[NGX_HTTP_V3_PREFIX_INT_LEN * 2]; | |
418 size_t n; | |
419 ngx_connection_t *ec; | |
420 | |
421 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
422 "http3 client ref insert, %s[%ui] \"%V\"", | |
423 dynamic ? "dynamic" : "static", index, value); | |
424 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
425 ec = ngx_http_v3_get_encoder(c); |
8215 | 426 if (ec == NULL) { |
427 return NGX_ERROR; | |
428 } | |
429 | |
430 p = buf; | |
431 | |
432 *p = (dynamic ? 0x80 : 0xc0); | |
433 p = (u_char *) ngx_http_v3_encode_prefix_int(p, index, 6); | |
434 | |
435 /* XXX option for huffman? */ | |
436 *p = 0; | |
437 p = (u_char *) ngx_http_v3_encode_prefix_int(p, value->len, 7); | |
438 | |
439 n = p - buf; | |
440 | |
441 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
442 goto failed; | |
443 } | |
444 | |
445 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
446 goto failed; | |
447 } | |
448 | |
449 return NGX_OK; | |
450 | |
451 failed: | |
452 | |
453 ngx_http_v3_close_uni_stream(ec); | |
454 | |
455 return NGX_ERROR; | |
456 } | |
457 | |
458 | |
459 ngx_int_t | |
460 ngx_http_v3_client_insert(ngx_connection_t *c, ngx_str_t *name, | |
461 ngx_str_t *value) | |
462 { | |
463 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
464 size_t n; | |
465 ngx_connection_t *ec; | |
466 | |
467 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
468 "http3 client insert \"%V\":\"%V\"", name, value); | |
469 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
470 ec = ngx_http_v3_get_encoder(c); |
8215 | 471 if (ec == NULL) { |
472 return NGX_ERROR; | |
473 } | |
474 | |
475 /* XXX option for huffman? */ | |
476 buf[0] = 0x40; | |
477 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, name->len, 5) - buf; | |
478 | |
479 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
480 goto failed; | |
481 } | |
482 | |
483 if (ec->send(ec, name->data, name->len) != (ssize_t) name->len) { | |
484 goto failed; | |
485 } | |
486 | |
487 /* XXX option for huffman? */ | |
488 buf[0] = 0; | |
489 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, value->len, 7) - buf; | |
490 | |
491 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
492 goto failed; | |
493 } | |
494 | |
495 if (ec->send(ec, value->data, value->len) != (ssize_t) value->len) { | |
496 goto failed; | |
497 } | |
498 | |
499 return NGX_OK; | |
500 | |
501 failed: | |
502 | |
503 ngx_http_v3_close_uni_stream(ec); | |
504 | |
505 return NGX_ERROR; | |
506 } | |
507 | |
508 | |
509 ngx_int_t | |
510 ngx_http_v3_client_set_capacity(ngx_connection_t *c, ngx_uint_t capacity) | |
511 { | |
512 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
513 size_t n; | |
514 ngx_connection_t *ec; | |
515 | |
516 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
517 "http3 client set capacity %ui", capacity); | |
518 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
519 ec = ngx_http_v3_get_encoder(c); |
8215 | 520 if (ec == NULL) { |
521 return NGX_ERROR; | |
522 } | |
523 | |
524 buf[0] = 0x20; | |
525 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, capacity, 5) - buf; | |
526 | |
527 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
528 ngx_http_v3_close_uni_stream(ec); | |
529 return NGX_ERROR; | |
530 } | |
531 | |
532 return NGX_OK; | |
533 } | |
534 | |
535 | |
536 ngx_int_t | |
537 ngx_http_v3_client_duplicate(ngx_connection_t *c, ngx_uint_t index) | |
538 { | |
539 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
540 size_t n; | |
541 ngx_connection_t *ec; | |
542 | |
543 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
544 "http3 client duplicate %ui", index); | |
545 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
546 ec = ngx_http_v3_get_encoder(c); |
8215 | 547 if (ec == NULL) { |
548 return NGX_ERROR; | |
549 } | |
550 | |
551 buf[0] = 0; | |
552 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, index, 5) - buf; | |
553 | |
554 if (ec->send(ec, buf, n) != (ssize_t) n) { | |
555 ngx_http_v3_close_uni_stream(ec); | |
556 return NGX_ERROR; | |
557 } | |
558 | |
559 return NGX_OK; | |
560 } | |
561 | |
562 | |
563 ngx_int_t | |
564 ngx_http_v3_client_ack_header(ngx_connection_t *c, ngx_uint_t stream_id) | |
565 { | |
566 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
567 size_t n; | |
568 ngx_connection_t *dc; | |
569 | |
570 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
571 "http3 client ack header %ui", stream_id); | |
572 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
573 dc = ngx_http_v3_get_decoder(c); |
8215 | 574 if (dc == NULL) { |
575 return NGX_ERROR; | |
576 } | |
577 | |
578 buf[0] = 0x80; | |
579 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 7) - buf; | |
580 | |
581 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
582 ngx_http_v3_close_uni_stream(dc); | |
583 return NGX_ERROR; | |
584 } | |
585 | |
586 return NGX_OK; | |
587 } | |
588 | |
589 | |
590 ngx_int_t | |
591 ngx_http_v3_client_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) | |
592 { | |
593 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
594 size_t n; | |
595 ngx_connection_t *dc; | |
596 | |
597 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
598 "http3 client cancel stream %ui", stream_id); | |
599 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
600 dc = ngx_http_v3_get_decoder(c); |
8215 | 601 if (dc == NULL) { |
602 return NGX_ERROR; | |
603 } | |
604 | |
605 buf[0] = 0x40; | |
606 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, stream_id, 6) - buf; | |
607 | |
608 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
609 ngx_http_v3_close_uni_stream(dc); | |
610 return NGX_ERROR; | |
611 } | |
612 | |
613 return NGX_OK; | |
614 } | |
615 | |
616 | |
617 ngx_int_t | |
618 ngx_http_v3_client_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) | |
619 { | |
620 u_char buf[NGX_HTTP_V3_PREFIX_INT_LEN]; | |
621 size_t n; | |
622 ngx_connection_t *dc; | |
623 | |
624 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
625 "http3 client increment insert count %ui", inc); | |
626 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8215
diff
changeset
|
627 dc = ngx_http_v3_get_decoder(c); |
8215 | 628 if (dc == NULL) { |
629 return NGX_ERROR; | |
630 } | |
631 | |
632 buf[0] = 0; | |
633 n = (u_char *) ngx_http_v3_encode_prefix_int(buf, inc, 6) - buf; | |
634 | |
635 if (dc->send(dc, buf, n) != (ssize_t) n) { | |
636 ngx_http_v3_close_uni_stream(dc); | |
637 return NGX_ERROR; | |
638 } | |
639 | |
640 return NGX_OK; | |
641 } |