Mercurial > hg > nginx
comparison src/http/v3/ngx_http_v3_streams.c @ 8497:0596fe1aee16 quic
HTTP/3: server pushes.
New directives are added:
- http3_max_concurrent_pushes
- http3_push
- http3_push_preload
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Thu, 23 Jul 2020 13:41:24 +0300 |
parents | 455a8536eaa7 |
children | 279ad36f2f4b |
comparison
equal
deleted
inserted
replaced
8496:c5324bb3a704 | 8497:0596fe1aee16 |
---|---|
19 void *data; | 19 void *data; |
20 ngx_int_t index; | 20 ngx_int_t index; |
21 } ngx_http_v3_uni_stream_t; | 21 } ngx_http_v3_uni_stream_t; |
22 | 22 |
23 | 23 |
24 typedef struct { | |
25 ngx_queue_t queue; | |
26 uint64_t id; | |
27 ngx_connection_t *connection; | |
28 ngx_uint_t *npushing; | |
29 } ngx_http_v3_push_t; | |
30 | |
31 | |
24 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); | 32 static void ngx_http_v3_close_uni_stream(ngx_connection_t *c); |
25 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); | 33 static void ngx_http_v3_read_uni_stream_type(ngx_event_t *rev); |
26 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); | 34 static void ngx_http_v3_uni_read_handler(ngx_event_t *rev); |
27 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); | 35 static void ngx_http_v3_dummy_write_handler(ngx_event_t *wev); |
36 static void ngx_http_v3_push_cleanup(void *data); | |
28 static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c, | 37 static ngx_connection_t *ngx_http_v3_get_uni_stream(ngx_connection_t *c, |
29 ngx_uint_t type); | 38 ngx_uint_t type); |
30 static ngx_int_t ngx_http_v3_send_settings(ngx_connection_t *c); | 39 static ngx_int_t ngx_http_v3_send_settings(ngx_connection_t *c); |
31 | 40 |
32 | 41 |
48 } | 57 } |
49 | 58 |
50 h3c->hc = *hc; | 59 h3c->hc = *hc; |
51 | 60 |
52 ngx_queue_init(&h3c->blocked); | 61 ngx_queue_init(&h3c->blocked); |
62 ngx_queue_init(&h3c->pushing); | |
53 | 63 |
54 c->data = h3c; | 64 c->data = h3c; |
55 return NGX_OK; | 65 return NGX_OK; |
56 } | 66 } |
57 | 67 |
318 } | 328 } |
319 } | 329 } |
320 | 330 |
321 | 331 |
322 /* XXX async & buffered stream writes */ | 332 /* XXX async & buffered stream writes */ |
333 | |
334 ngx_connection_t * | |
335 ngx_http_v3_create_push_stream(ngx_connection_t *c, uint64_t push_id) | |
336 { | |
337 u_char *p, buf[NGX_HTTP_V3_VARLEN_INT_LEN * 2]; | |
338 size_t n; | |
339 ngx_connection_t *sc; | |
340 ngx_pool_cleanup_t *cln; | |
341 ngx_http_v3_push_t *push; | |
342 ngx_http_v3_connection_t *h3c; | |
343 | |
344 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
345 "http3 create push stream id:%uL", push_id); | |
346 | |
347 sc = ngx_quic_open_stream(c, 0); | |
348 if (sc == NULL) { | |
349 return NULL; | |
350 } | |
351 | |
352 p = buf; | |
353 p = (u_char *) ngx_http_v3_encode_varlen_int(p, NGX_HTTP_V3_STREAM_PUSH); | |
354 p = (u_char *) ngx_http_v3_encode_varlen_int(p, push_id); | |
355 n = p - buf; | |
356 | |
357 if (sc->send(sc, buf, n) != (ssize_t) n) { | |
358 goto failed; | |
359 } | |
360 | |
361 cln = ngx_pool_cleanup_add(sc->pool, sizeof(ngx_http_v3_push_t)); | |
362 if (cln == NULL) { | |
363 goto failed; | |
364 } | |
365 | |
366 h3c = c->qs->parent->data; | |
367 h3c->npushing++; | |
368 | |
369 cln->handler = ngx_http_v3_push_cleanup; | |
370 | |
371 push = cln->data; | |
372 push->id = push_id; | |
373 push->connection = sc; | |
374 push->npushing = &h3c->npushing; | |
375 | |
376 ngx_queue_insert_tail(&h3c->pushing, &push->queue); | |
377 | |
378 return sc; | |
379 | |
380 failed: | |
381 | |
382 ngx_http_v3_close_uni_stream(sc); | |
383 | |
384 return NULL; | |
385 } | |
386 | |
387 | |
388 static void | |
389 ngx_http_v3_push_cleanup(void *data) | |
390 { | |
391 ngx_http_v3_push_t *push = data; | |
392 | |
393 ngx_queue_remove(&push->queue); | |
394 (*push->npushing)--; | |
395 } | |
396 | |
323 | 397 |
324 static ngx_connection_t * | 398 static ngx_connection_t * |
325 ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type) | 399 ngx_http_v3_get_uni_stream(ngx_connection_t *c, ngx_uint_t type) |
326 { | 400 { |
327 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; | 401 u_char buf[NGX_HTTP_V3_VARLEN_INT_LEN]; |
680 return NGX_ERROR; | 754 return NGX_ERROR; |
681 } | 755 } |
682 | 756 |
683 return NGX_OK; | 757 return NGX_OK; |
684 } | 758 } |
759 | |
760 | |
761 ngx_int_t | |
762 ngx_http_v3_set_max_push_id(ngx_connection_t *c, uint64_t max_push_id) | |
763 { | |
764 ngx_http_v3_connection_t *h3c; | |
765 | |
766 h3c = c->qs->parent->data; | |
767 | |
768 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
769 "http3 MAX_PUSH_ID:%uL", max_push_id); | |
770 | |
771 if (max_push_id < h3c->max_push_id) { | |
772 return NGX_HTTP_V3_ERR_ID_ERROR; | |
773 } | |
774 | |
775 h3c->max_push_id = max_push_id; | |
776 | |
777 return NGX_OK; | |
778 } | |
779 | |
780 | |
781 ngx_int_t | |
782 ngx_http_v3_cancel_push(ngx_connection_t *c, uint64_t push_id) | |
783 { | |
784 ngx_queue_t *q; | |
785 ngx_http_request_t *r; | |
786 ngx_http_v3_push_t *push; | |
787 ngx_http_v3_connection_t *h3c; | |
788 | |
789 h3c = c->qs->parent->data; | |
790 | |
791 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
792 "http3 CANCEL_PUSH:%uL", push_id); | |
793 | |
794 if (push_id >= h3c->next_push_id) { | |
795 return NGX_HTTP_V3_ERR_ID_ERROR; | |
796 } | |
797 | |
798 for (q = ngx_queue_head(&h3c->pushing); | |
799 q != ngx_queue_sentinel(&h3c->pushing); | |
800 q = ngx_queue_next(&h3c->pushing)) | |
801 { | |
802 push = (ngx_http_v3_push_t *) q; | |
803 | |
804 if (push->id != push_id) { | |
805 continue; | |
806 } | |
807 | |
808 r = push->connection->data; | |
809 | |
810 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
811 "http3 cancel push"); | |
812 | |
813 ngx_http_finalize_request(r, NGX_HTTP_CLOSE); | |
814 | |
815 break; | |
816 } | |
817 | |
818 return NGX_OK; | |
819 } |