comparison src/event/quic/ngx_event_quic_streams.c @ 8906:41caf5410110 quic

QUIC: reject streams which we could not create. The reasons why a stream may not be created by server currently include hitting worker_connections limit and memory allocation error. Previously in these cases the entire QUIC connection was closed and all its streams were shut down. Now the new stream is rejected and existing streams continue working. To reject an HTTP/3 request stream, RESET_STREAM and STOP_SENDING with H3_REQUEST_REJECTED error code are sent to client. HTTP/3 uni streams and Stream streams are not rejected.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 11 Nov 2021 19:07:00 +0300
parents 832723a49026
children e8cbbfabe547
comparison
equal deleted inserted replaced
8905:832723a49026 8906:41caf5410110
13 #define NGX_QUIC_STREAM_GONE (void *) -1 13 #define NGX_QUIC_STREAM_GONE (void *) -1
14 14
15 15
16 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c, 16 static ngx_quic_stream_t *ngx_quic_create_client_stream(ngx_connection_t *c,
17 uint64_t id); 17 uint64_t id);
18 static ngx_int_t ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id);
18 static ngx_int_t ngx_quic_init_stream(ngx_quic_stream_t *qs); 19 static ngx_int_t ngx_quic_init_stream(ngx_quic_stream_t *qs);
19 static void ngx_quic_init_streams_handler(ngx_connection_t *c); 20 static void ngx_quic_init_streams_handler(ngx_connection_t *c);
20 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c, 21 static ngx_quic_stream_t *ngx_quic_create_stream(ngx_connection_t *c,
21 uint64_t id); 22 uint64_t id);
22 static void ngx_quic_empty_handler(ngx_event_t *ev); 23 static void ngx_quic_empty_handler(ngx_event_t *ev);
375 */ 376 */
376 377
377 for ( /* void */ ; min_id < id; min_id += 0x04) { 378 for ( /* void */ ; min_id < id; min_id += 0x04) {
378 379
379 qs = ngx_quic_create_stream(c, min_id); 380 qs = ngx_quic_create_stream(c, min_id);
381
380 if (qs == NULL) { 382 if (qs == NULL) {
381 return NULL; 383 if (ngx_quic_reject_stream(c, min_id) != NGX_OK) {
384 return NULL;
385 }
386
387 continue;
382 } 388 }
383 389
384 if (ngx_quic_init_stream(qs) != NGX_OK) { 390 if (ngx_quic_init_stream(qs) != NGX_OK) {
385 return NULL; 391 return NULL;
386 } 392 }
388 if (qc->shutdown || qc->closing) { 394 if (qc->shutdown || qc->closing) {
389 return NGX_QUIC_STREAM_GONE; 395 return NGX_QUIC_STREAM_GONE;
390 } 396 }
391 } 397 }
392 398
393 return ngx_quic_create_stream(c, id); 399 qs = ngx_quic_create_stream(c, id);
400
401 if (qs == NULL) {
402 if (ngx_quic_reject_stream(c, id) != NGX_OK) {
403 return NULL;
404 }
405
406 return NGX_QUIC_STREAM_GONE;
407 }
408
409 return qs;
410 }
411
412
413 static ngx_int_t
414 ngx_quic_reject_stream(ngx_connection_t *c, uint64_t id)
415 {
416 uint64_t code;
417 ngx_quic_frame_t *frame;
418 ngx_quic_connection_t *qc;
419
420 qc = ngx_quic_get_connection(c);
421
422 code = (id & NGX_QUIC_STREAM_UNIDIRECTIONAL)
423 ? qc->conf->stream_reject_code_uni
424 : qc->conf->stream_reject_code_bidi;
425
426 if (code == 0) {
427 return NGX_DECLINED;
428 }
429
430 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
431 "quic stream id:0x%xL reject err:0x%xL", id, code);
432
433 frame = ngx_quic_alloc_frame(c);
434 if (frame == NULL) {
435 return NGX_ERROR;
436 }
437
438 frame->level = ssl_encryption_application;
439 frame->type = NGX_QUIC_FT_RESET_STREAM;
440 frame->u.reset_stream.id = id;
441 frame->u.reset_stream.error_code = code;
442 frame->u.reset_stream.final_size = 0;
443
444 ngx_quic_queue_frame(qc, frame);
445
446 frame = ngx_quic_alloc_frame(c);
447 if (frame == NULL) {
448 return NGX_ERROR;
449 }
450
451 frame->level = ssl_encryption_application;
452 frame->type = NGX_QUIC_FT_STOP_SENDING;
453 frame->u.stop_sending.id = id;
454 frame->u.stop_sending.error_code = code;
455
456 ngx_quic_queue_frame(qc, frame);
457
458 return NGX_OK;
394 } 459 }
395 460
396 461
397 static ngx_int_t 462 static ngx_int_t
398 ngx_quic_init_stream(ngx_quic_stream_t *qs) 463 ngx_quic_init_stream(ngx_quic_stream_t *qs)
864 (void) ngx_quic_update_flow(c, qs->recv_last); 929 (void) ngx_quic_update_flow(c, qs->recv_last);
865 930
866 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0 931 if ((qs->id & NGX_QUIC_STREAM_SERVER_INITIATED) == 0
867 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0) 932 || (qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0)
868 { 933 {
869 if (!c->read->pending_eof && !c->read->error) { 934 if (!c->read->pending_eof && !c->read->error
935 && qc->conf->stream_close_code)
936 {
870 frame = ngx_quic_alloc_frame(pc); 937 frame = ngx_quic_alloc_frame(pc);
871 if (frame == NULL) { 938 if (frame == NULL) {
872 goto done; 939 goto done;
873 } 940 }
874 941
875 frame->level = ssl_encryption_application; 942 frame->level = ssl_encryption_application;
876 frame->type = NGX_QUIC_FT_STOP_SENDING; 943 frame->type = NGX_QUIC_FT_STOP_SENDING;
877 frame->u.stop_sending.id = qs->id; 944 frame->u.stop_sending.id = qs->id;
878 frame->u.stop_sending.error_code = 0x100; /* HTTP/3 no error */ 945 frame->u.stop_sending.error_code = qc->conf->stream_close_code;
879 946
880 ngx_quic_queue_frame(qc, frame); 947 ngx_quic_queue_frame(qc, frame);
881 } 948 }
882 } 949 }
883 950