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 }