comparison src/http/v3/ngx_http_v3_streams.c @ 8283:dadbc66e9fca quic

Simplifed handling HTTP/3 streams.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 25 Mar 2020 12:14:24 +0300
parents 618a65de08b3
children 44cac24aaa44
comparison
equal deleted inserted replaced
8282:4cf00c14f11a 8283:dadbc66e9fca
13 typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data, 13 typedef ngx_int_t (*ngx_http_v3_handler_pt)(ngx_connection_t *c, void *data,
14 u_char ch); 14 u_char ch);
15 15
16 16
17 typedef struct { 17 typedef struct {
18 uint32_t signature; /* QSTR */
19
20 ngx_http_v3_handler_pt handler; 18 ngx_http_v3_handler_pt handler;
21 void *data; 19 void *data;
22 20 ngx_int_t index;
23 ngx_uint_t type;
24 ngx_uint_t client; /* unsigned client:1; */
25 } ngx_http_v3_uni_stream_t; 21 } ngx_http_v3_uni_stream_t;
26 22
27 23
28 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); 24 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); 25 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev);
31 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); 26 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev);
32 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); 27 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev);
33 static ngx_connection_t *ngx_http_v3_create_uni_stream(ngx_connection_t *c, 28 static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c,
34 ngx_uint_t type); 29 ngx_uint_t type);
35 static ngx_connection_t *ngx_http_v3_get_control(ngx_connection_t *c);
36 static ngx_connection_t *ngx_http_v3_get_encoder(ngx_connection_t *c);
37 static ngx_connection_t *ngx_http_v3_get_decoder(ngx_connection_t *c);
38 30
39 31
40 void 32 void
41 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c) 33 ngx_http_v3_handle_client_uni_stream(ngx_connection_t *c)
42 { 34 {
43 ngx_pool_cleanup_t *cln;
44 ngx_http_v3_uni_stream_t *us; 35 ngx_http_v3_uni_stream_t *us;
45 36
46 c->log->connection = c->number; 37 c->log->connection = c->number;
47 38
48 /* XXX */ 39 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL);
49 (void) ngx_http_v3_get_control(c); 40 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER);
50 (void) ngx_http_v3_get_encoder(c); 41 ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
51 (void) ngx_http_v3_get_decoder(c);
52 42
53 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 43 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
54 "http3 new uni stream id:0x%uxL", c->qs->id); 44 "http3 new uni stream id:0x%uxL", c->qs->id);
55 45
56 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t)); 46 us = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_uni_stream_t));
57 if (us == NULL) { 47 if (us == NULL) {
58 ngx_http_v3_close_uni_stream(c); 48 ngx_http_v3_close_uni_stream(c);
59 return; 49 return;
60 } 50 }
61 51
62 us->signature = NGX_HTTP_V3_STREAM; 52 us->index = -1;
63 us->client = 1;
64 us->type = (ngx_uint_t) -1;
65 53
66 c->data = us; 54 c->data = us;
67
68 cln = ngx_pool_cleanup_add(c->pool, 0);
69 if (cln == NULL) {
70 ngx_http_v3_close_uni_stream(c);
71 return;
72 }
73
74 cln->handler = ngx_http_v3_uni_stream_cleanup;
75 cln->data = c;
76 55
77 c->read->handler = ngx_http_v3_read_uni_stream_type; 56 c->read->handler = ngx_http_v3_read_uni_stream_type;
78 c->write->handler = ngx_http_v3_dummy_write_handler; 57 c->write->handler = ngx_http_v3_dummy_write_handler;
79 58
80 ngx_http_v3_read_uni_stream_type(c->read); 59 ngx_http_v3_read_uni_stream_type(c->read);
82 61
83 62
84 static void 63 static void
85 ngx_http_v3_close_uni_stream(ngx_connection_t *c) 64 ngx_http_v3_close_uni_stream(ngx_connection_t *c)
86 { 65 {
87 ngx_pool_t *pool; 66 ngx_pool_t *pool;
88
89 c->destroyed = 1;
90
91 pool = c->pool;
92
93 ngx_close_connection(c);
94
95 ngx_destroy_pool(pool);
96 }
97
98
99 static void
100 ngx_http_v3_uni_stream_cleanup(void *data)
101 {
102 ngx_connection_t *c = data;
103
104 ngx_http_v3_connection_t *h3c; 67 ngx_http_v3_connection_t *h3c;
105 ngx_http_v3_uni_stream_t *us; 68 ngx_http_v3_uni_stream_t *us;
106 69
107 us = c->data; 70 us = c->data;
108 h3c = c->qs->parent->data; 71 h3c = c->qs->parent->data;
109 72
110 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream"); 73 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 close stream");
111 74
112 switch (us->type) { 75 if (us->index >= 0) {
113 76 h3c->known_streams[us->index] = NULL;
114 case NGX_HTTP_V3_STREAM_ENCODER: 77 }
115 78
116 if (us->client) { 79 c->destroyed = 1;
117 h3c->client_encoder = NULL; 80
118 } else { 81 pool = c->pool;
119 h3c->server_encoder = NULL; 82
120 } 83 ngx_close_connection(c);
121 84
122 break; 85 ngx_destroy_pool(pool);
123
124 case NGX_HTTP_V3_STREAM_DECODER:
125
126 if (us->client) {
127 h3c->client_decoder = NULL;
128 } else {
129 h3c->server_decoder = NULL;
130 }
131
132 break;
133
134 case NGX_HTTP_V3_STREAM_CONTROL:
135
136 if (us->client) {
137 h3c->client_control = NULL;
138 } else {
139 h3c->server_control = NULL;
140 }
141
142 break;
143 }
144 } 86 }
145 87
146 88
147 static void 89 static void
148 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev) 90 ngx_http_v3_read_uni_stream_type(ngx_event_t *rev)
149 { 91 {
150 u_char ch; 92 u_char ch;
151 ssize_t n; 93 ssize_t n;
94 ngx_int_t index;
152 ngx_connection_t *c; 95 ngx_connection_t *c;
153 ngx_http_v3_connection_t *h3c; 96 ngx_http_v3_connection_t *h3c;
154 ngx_http_v3_uni_stream_t *st; 97 ngx_http_v3_uni_stream_t *us;
155 98
156 c = rev->data; 99 c = rev->data;
157 st = c->data; 100 us = c->data;
158 h3c = c->qs->parent->data; 101 h3c = c->qs->parent->data;
159 102
160 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type"); 103 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read stream type");
161 104
162 while (rev->ready) { 105 while (rev->ready) {
169 112
170 if (n == NGX_AGAIN || n != 1) { 113 if (n == NGX_AGAIN || n != 1) {
171 break; 114 break;
172 } 115 }
173 116
174 st->type = ch; 117 switch (ch) {
175
176 switch (st->type) {
177 118
178 case NGX_HTTP_V3_STREAM_ENCODER: 119 case NGX_HTTP_V3_STREAM_ENCODER:
179 120
180 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, 121 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
181 "http3 encoder stream"); 122 "http3 encoder stream");
182 123
183 if (h3c->client_encoder) { 124 index = NGX_HTTP_V3_STREAM_CLIENT_ENCODER;
125 us->handler = ngx_http_v3_parse_encoder;
126 n = sizeof(ngx_http_v3_parse_encoder_t);
127
128 break;
129
130 case NGX_HTTP_V3_STREAM_DECODER:
131
132 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
133 "http3 decoder stream");
134
135 index = NGX_HTTP_V3_STREAM_CLIENT_DECODER;
136 us->handler = ngx_http_v3_parse_decoder;
137 n = sizeof(ngx_http_v3_parse_decoder_t);
138
139 break;
140
141 case NGX_HTTP_V3_STREAM_CONTROL:
142
143 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
144 "http3 control stream");
145
146 index = NGX_HTTP_V3_STREAM_CLIENT_CONTROL;
147 us->handler = ngx_http_v3_parse_control;
148 n = sizeof(ngx_http_v3_parse_control_t);
149
150 break;
151
152 default:
153
154 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
155 "http3 stream 0x%02xi", (ngx_int_t) ch);
156 index = -1;
157 n = 0;
158 }
159
160 if (index >= 0) {
161 if (h3c->known_streams[index]) {
162 ngx_log_error(NGX_LOG_INFO, c->log, 0, "stream exists");
184 goto failed; 163 goto failed;
185 } 164 }
186 165
187 h3c->client_encoder = c; 166 us->index = index;
188 st->handler = ngx_http_v3_parse_encoder; 167 h3c->known_streams[index] = c;
189 n = sizeof(ngx_http_v3_parse_encoder_t);
190
191 break;
192
193 case NGX_HTTP_V3_STREAM_DECODER:
194
195 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
196 "http3 decoder stream");
197
198 if (h3c->client_decoder) {
199 goto failed;
200 }
201
202 h3c->client_decoder = c;
203 st->handler = ngx_http_v3_parse_decoder;
204 n = sizeof(ngx_http_v3_parse_decoder_t);
205
206 break;
207
208 case NGX_HTTP_V3_STREAM_CONTROL:
209
210 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
211 "http3 control stream");
212
213 if (h3c->client_control) {
214 goto failed;
215 }
216
217 h3c->client_control = c;
218 st->handler = ngx_http_v3_parse_control;
219 n = sizeof(ngx_http_v3_parse_control_t);
220
221 break;
222
223 default:
224
225 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
226 "http3 stream 0x%02xi", st->type);
227 n = 0;
228 } 168 }
229 169
230 if (n) { 170 if (n) {
231 st->data = ngx_pcalloc(c->pool, n); 171 us->data = ngx_pcalloc(c->pool, n);
232 if (st->data == NULL) { 172 if (us->data == NULL) {
233 goto failed; 173 goto failed;
234 } 174 }
235 } 175 }
236 176
237 rev->handler = ngx_http_v3_uni_read_handler; 177 rev->handler = ngx_http_v3_uni_read_handler;
256 { 196 {
257 u_char buf[128]; 197 u_char buf[128];
258 ssize_t n; 198 ssize_t n;
259 ngx_int_t rc, i; 199 ngx_int_t rc, i;
260 ngx_connection_t *c; 200 ngx_connection_t *c;
261 ngx_http_v3_uni_stream_t *st; 201 ngx_http_v3_uni_stream_t *us;
262 202
263 c = rev->data; 203 c = rev->data;
264 st = c->data; 204 us = c->data;
265 205
266 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler"); 206 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 read handler");
267 207
268 while (rev->ready) { 208 while (rev->ready) {
269 209
275 215
276 if (n == NGX_AGAIN) { 216 if (n == NGX_AGAIN) {
277 break; 217 break;
278 } 218 }
279 219
280 if (st->handler == NULL) { 220 if (us->handler == NULL) {
281 continue; 221 continue;
282 } 222 }
283 223
284 for (i = 0; i < n; i++) { 224 for (i = 0; i < n; i++) {
285 225
286 rc = st->handler(c, st->data, buf[i]); 226 rc = us->handler(c, us->data, buf[i]);
287 227
288 if (rc == NGX_ERROR) { 228 if (rc == NGX_ERROR) {
289 goto failed; 229 goto failed;
290 } 230 }
291 231
329 269
330 270
331 /* XXX async & buffered stream writes */ 271 /* XXX async & buffered stream writes */
332 272
333 static ngx_connection_t * 273 static ngx_connection_t *
334 ngx_http_v3_create_uni_stream(ngx_connection_t *c, ngx_uint_t type) 274 ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type)
335 { 275 {
336 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; 276 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN];
337 size_t n; 277 size_t n;
278 ngx_int_t index;
338 ngx_connection_t *sc; 279 ngx_connection_t *sc;
339 ngx_pool_cleanup_t *cln; 280 ngx_http_v3_connection_t *h3c;
340 ngx_http_v3_uni_stream_t *us; 281 ngx_http_v3_uni_stream_t *us;
282
283 switch (type) {
284 case NGX_HTTP_V3_STREAM_ENCODER:
285 index = NGX_HTTP_V3_STREAM_SERVER_ENCODER;
286 break;
287 case NGX_HTTP_V3_STREAM_DECODER:
288 index = NGX_HTTP_V3_STREAM_SERVER_DECODER;
289 break;
290 case NGX_HTTP_V3_STREAM_CONTROL:
291 index = NGX_HTTP_V3_STREAM_SERVER_CONTROL;
292 break;
293 default:
294 index = -1;
295 }
296
297 h3c = c->qs->parent->data;
298
299 if (index >= 0) {
300 if (h3c->known_streams[index]) {
301 return h3c->known_streams[index];
302 }
303 }
341 304
342 sc = ngx_quic_create_uni_stream(c); 305 sc = ngx_quic_create_uni_stream(c);
343 if (sc == NULL) { 306 if (sc == NULL) {
344 return NULL; 307 return NULL;
345 } 308 }
350 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t)); 313 us = ngx_pcalloc(sc->pool, sizeof(ngx_http_v3_uni_stream_t));
351 if (us == NULL) { 314 if (us == NULL) {
352 goto failed; 315 goto failed;
353 } 316 }
354 317
355 us->signature = NGX_HTTP_V3_STREAM; 318 us->index = index;
356 us->type = type; 319
357 sc->data = us; 320 sc->data = us;
358 321
359 sc->read->handler = ngx_http_v3_uni_read_handler; 322 sc->read->handler = ngx_http_v3_uni_read_handler;
360 sc->write->handler = ngx_http_v3_dummy_write_handler; 323 sc->write->handler = ngx_http_v3_dummy_write_handler;
361 324
362 cln = ngx_pool_cleanup_add(sc->pool, 0); 325 h3c->known_streams[index] = sc;
363 if (cln == NULL) {
364 goto failed;
365 }
366
367 cln->handler = ngx_http_v3_uni_stream_cleanup;
368 cln->data = sc;
369 326
370 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf; 327 n = (u_char *) ngx_http_v3_encode_varlen_int(buf, type) - buf;
371 328
372 if (sc->send(sc, buf, n) != (ssize_t) n) { 329 if (sc->send(sc, buf, n) != (ssize_t) n) {
373 goto failed; 330 goto failed;
378 failed: 335 failed:
379 336
380 ngx_http_v3_close_uni_stream(sc); 337 ngx_http_v3_close_uni_stream(sc);
381 338
382 return NULL; 339 return NULL;
383 }
384
385
386 static ngx_connection_t *
387 ngx_http_v3_get_control(ngx_connection_t *c)
388 {
389 ngx_http_v3_connection_t *h3c;
390
391 h3c = c->qs->parent->data;
392
393 if (h3c->server_control == NULL) {
394 h3c->server_control = ngx_http_v3_create_uni_stream(c,
395 NGX_HTTP_V3_STREAM_CONTROL);
396 }
397
398 return h3c->server_encoder;
399 }
400
401
402 static ngx_connection_t *
403 ngx_http_v3_get_encoder(ngx_connection_t *c)
404 {
405 ngx_http_v3_connection_t *h3c;
406
407 h3c = c->qs->parent->data;
408
409 if (h3c->server_encoder == NULL) {
410 h3c->server_encoder = ngx_http_v3_create_uni_stream(c,
411 NGX_HTTP_V3_STREAM_ENCODER);
412 }
413
414 return h3c->server_encoder;
415 }
416
417
418 static ngx_connection_t *
419 ngx_http_v3_get_decoder(ngx_connection_t *c)
420 {
421 ngx_http_v3_connection_t *h3c;
422
423 h3c = c->qs->parent->data;
424
425 if (h3c->server_decoder == NULL) {
426 h3c->server_decoder = ngx_http_v3_create_uni_stream(c,
427 NGX_HTTP_V3_STREAM_DECODER);
428 }
429
430 return h3c->server_encoder;
431 } 340 }
432 341
433 342
434 ngx_int_t 343 ngx_int_t
435 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic, 344 ngx_http_v3_client_ref_insert(ngx_connection_t *c, ngx_uint_t dynamic,
441 350
442 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, 351 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
443 "http3 client ref insert, %s[%ui] \"%V\"", 352 "http3 client ref insert, %s[%ui] \"%V\"",
444 dynamic ? "dynamic" : "static", index, value); 353 dynamic ? "dynamic" : "static", index, value);
445 354
446 ec = ngx_http_v3_get_encoder(c); 355 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER);
447 if (ec == NULL) { 356 if (ec == NULL) {
448 return NGX_ERROR; 357 return NGX_ERROR;
449 } 358 }
450 359
451 p = buf; 360 p = buf;
486 ngx_connection_t *ec; 395 ngx_connection_t *ec;
487 396
488 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, 397 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
489 "http3 client insert \"%V\":\"%V\"", name, value); 398 "http3 client insert \"%V\":\"%V\"", name, value);
490 399
491 ec = ngx_http_v3_get_encoder(c); 400 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER);
492 if (ec == NULL) { 401 if (ec == NULL) {
493 return NGX_ERROR; 402 return NGX_ERROR;
494 } 403 }
495 404
496 /* XXX option for huffman? */ 405 /* XXX option for huffman? */
535 ngx_connection_t *ec; 444 ngx_connection_t *ec;
536 445
537 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 446 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
538 "http3 client set capacity %ui", capacity); 447 "http3 client set capacity %ui", capacity);
539 448
540 ec = ngx_http_v3_get_encoder(c); 449 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER);
541 if (ec == NULL) { 450 if (ec == NULL) {
542 return NGX_ERROR; 451 return NGX_ERROR;
543 } 452 }
544 453
545 buf[0] = 0x20; 454 buf[0] = 0x20;
562 ngx_connection_t *ec; 471 ngx_connection_t *ec;
563 472
564 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 473 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
565 "http3 client duplicate %ui", index); 474 "http3 client duplicate %ui", index);
566 475
567 ec = ngx_http_v3_get_encoder(c); 476 ec = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_ENCODER);
568 if (ec == NULL) { 477 if (ec == NULL) {
569 return NGX_ERROR; 478 return NGX_ERROR;
570 } 479 }
571 480
572 buf[0] = 0; 481 buf[0] = 0;
589 ngx_connection_t *dc; 498 ngx_connection_t *dc;
590 499
591 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 500 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
592 "http3 client ack header %ui", stream_id); 501 "http3 client ack header %ui", stream_id);
593 502
594 dc = ngx_http_v3_get_decoder(c); 503 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
595 if (dc == NULL) { 504 if (dc == NULL) {
596 return NGX_ERROR; 505 return NGX_ERROR;
597 } 506 }
598 507
599 buf[0] = 0x80; 508 buf[0] = 0x80;
616 ngx_connection_t *dc; 525 ngx_connection_t *dc;
617 526
618 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 527 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
619 "http3 client cancel stream %ui", stream_id); 528 "http3 client cancel stream %ui", stream_id);
620 529
621 dc = ngx_http_v3_get_decoder(c); 530 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
622 if (dc == NULL) { 531 if (dc == NULL) {
623 return NGX_ERROR; 532 return NGX_ERROR;
624 } 533 }
625 534
626 buf[0] = 0x40; 535 buf[0] = 0x40;
643 ngx_connection_t *dc; 552 ngx_connection_t *dc;
644 553
645 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 554 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
646 "http3 client increment insert count %ui", inc); 555 "http3 client increment insert count %ui", inc);
647 556
648 dc = ngx_http_v3_get_decoder(c); 557 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
649 if (dc == NULL) { 558 if (dc == NULL) {
650 return NGX_ERROR; 559 return NGX_ERROR;
651 } 560 }
652 561
653 buf[0] = 0; 562 buf[0] = 0;