comparison src/http/v3/ngx_http_v3_streams.c @ 8902:925572184d4a quic

HTTP/3: adjusted QUIC connection finalization. When an HTTP/3 function returns an error in context of a QUIC stream, it's this function's responsibility now to finalize the entire QUIC connection with the right code, if required. Previously, QUIC connection finalization could be done both outside and inside such functions. The new rule follows a similar rule for logging, leads to cleaner code, and allows to provide more details about the error. While here, a few error cases are no longer treated as fatal and QUIC connection is no longer finalized in these cases. A few other cases now lead to stream reset instead of connection finalization.
author Roman Arutyunyan <arut@nginx.com>
date Mon, 18 Oct 2021 15:22:33 +0300
parents 72b304f6207c
children 0d3bf08eaac0
comparison
equal deleted inserted replaced
8901:a951e0809044 8902:925572184d4a
281 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 281 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
282 "http3 create push stream id:%uL", push_id); 282 "http3 create push stream id:%uL", push_id);
283 283
284 sc = ngx_quic_open_stream(c, 0); 284 sc = ngx_quic_open_stream(c, 0);
285 if (sc == NULL) { 285 if (sc == NULL) {
286 return NULL; 286 goto failed;
287 } 287 }
288 288
289 p = buf; 289 p = buf;
290 p = (u_char *) ngx_http_v3_encode_varlen_int(p, NGX_HTTP_V3_STREAM_PUSH); 290 p = (u_char *) ngx_http_v3_encode_varlen_int(p, NGX_HTTP_V3_STREAM_PUSH);
291 p = (u_char *) ngx_http_v3_encode_varlen_int(p, push_id); 291 p = (u_char *) ngx_http_v3_encode_varlen_int(p, push_id);
316 316
317 return sc; 317 return sc;
318 318
319 failed: 319 failed:
320 320
321 ngx_http_v3_close_uni_stream(sc); 321 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create push stream");
322
323 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
324 "failed to create push stream");
325 if (sc) {
326 ngx_http_v3_close_uni_stream(sc);
327 }
322 328
323 return NULL; 329 return NULL;
324 } 330 }
325 331
326 332
366 } 372 }
367 } 373 }
368 374
369 sc = ngx_quic_open_stream(c, 0); 375 sc = ngx_quic_open_stream(c, 0);
370 if (sc == NULL) { 376 if (sc == NULL) {
371 return NULL; 377 goto failed;
372 } 378 }
373 379
374 sc->quic->cancelable = 1; 380 sc->quic->cancelable = 1;
375 381
376 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 382 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
403 409
404 return sc; 410 return sc;
405 411
406 failed: 412 failed:
407 413
408 ngx_http_v3_close_uni_stream(sc); 414 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to create server stream");
415
416 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_STREAM_CREATION_ERROR,
417 "failed to create server stream");
418 if (sc) {
419 ngx_http_v3_close_uni_stream(sc);
420 }
409 421
410 return NULL; 422 return NULL;
411 } 423 }
412 424
413 425
422 434
423 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send settings"); 435 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send settings");
424 436
425 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); 437 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL);
426 if (cc == NULL) { 438 if (cc == NULL) {
427 return NGX_DECLINED; 439 return NGX_ERROR;
428 } 440 }
429 441
430 h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module); 442 h3scf = ngx_http_v3_get_module_srv_conf(c, ngx_http_v3_module);
431 443
432 n = ngx_http_v3_encode_varlen_int(NULL, 444 n = ngx_http_v3_encode_varlen_int(NULL,
455 467
456 return NGX_OK; 468 return NGX_OK;
457 469
458 failed: 470 failed:
459 471
472 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send settings");
473
474 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
475 "failed to send settings");
460 ngx_http_v3_close_uni_stream(cc); 476 ngx_http_v3_close_uni_stream(cc);
461 477
462 return NGX_ERROR; 478 return NGX_ERROR;
463 } 479 }
464 480
473 489
474 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send goaway %uL", id); 490 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 send goaway %uL", id);
475 491
476 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL); 492 cc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_CONTROL);
477 if (cc == NULL) { 493 if (cc == NULL) {
478 return NGX_DECLINED; 494 return NGX_ERROR;
479 } 495 }
480 496
481 n = ngx_http_v3_encode_varlen_int(NULL, id); 497 n = ngx_http_v3_encode_varlen_int(NULL, id);
482 p = (u_char *) ngx_http_v3_encode_varlen_int(buf, NGX_HTTP_V3_FRAME_GOAWAY); 498 p = (u_char *) ngx_http_v3_encode_varlen_int(buf, NGX_HTTP_V3_FRAME_GOAWAY);
483 p = (u_char *) ngx_http_v3_encode_varlen_int(p, n); 499 p = (u_char *) ngx_http_v3_encode_varlen_int(p, n);
493 509
494 return NGX_OK; 510 return NGX_OK;
495 511
496 failed: 512 failed:
497 513
514 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send goaway");
515
516 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
517 "failed to send goaway");
498 ngx_http_v3_close_uni_stream(cc); 518 ngx_http_v3_close_uni_stream(cc);
499 519
500 return NGX_ERROR; 520 return NGX_ERROR;
501 } 521 }
502 522
508 size_t n; 528 size_t n;
509 ngx_connection_t *dc; 529 ngx_connection_t *dc;
510 ngx_http_v3_session_t *h3c; 530 ngx_http_v3_session_t *h3c;
511 531
512 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 532 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
513 "http3 client ack section %ui", stream_id); 533 "http3 send section acknowledgement %ui", stream_id);
514 534
515 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); 535 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
516 if (dc == NULL) { 536 if (dc == NULL) {
517 return NGX_ERROR; 537 return NGX_ERROR;
518 } 538 }
522 542
523 h3c = ngx_http_v3_get_session(c); 543 h3c = ngx_http_v3_get_session(c);
524 h3c->total_bytes += n; 544 h3c->total_bytes += n;
525 545
526 if (dc->send(dc, buf, n) != (ssize_t) n) { 546 if (dc->send(dc, buf, n) != (ssize_t) n) {
527 ngx_http_v3_close_uni_stream(dc); 547 goto failed;
528 return NGX_ERROR; 548 }
529 } 549
530 550 return NGX_OK;
531 return NGX_OK; 551
552 failed:
553
554 ngx_log_error(NGX_LOG_ERR, c->log, 0,
555 "failed to send section acknowledgement");
556
557 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
558 "failed to send section acknowledgement");
559 ngx_http_v3_close_uni_stream(dc);
560
561 return NGX_ERROR;
532 } 562 }
533 563
534 564
535 ngx_int_t 565 ngx_int_t
536 ngx_http_v3_send_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id) 566 ngx_http_v3_send_cancel_stream(ngx_connection_t *c, ngx_uint_t stream_id)
539 size_t n; 569 size_t n;
540 ngx_connection_t *dc; 570 ngx_connection_t *dc;
541 ngx_http_v3_session_t *h3c; 571 ngx_http_v3_session_t *h3c;
542 572
543 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 573 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
544 "http3 client cancel stream %ui", stream_id); 574 "http3 send stream cancellation %ui", stream_id);
545 575
546 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); 576 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
547 if (dc == NULL) { 577 if (dc == NULL) {
548 return NGX_ERROR; 578 return NGX_ERROR;
549 } 579 }
553 583
554 h3c = ngx_http_v3_get_session(c); 584 h3c = ngx_http_v3_get_session(c);
555 h3c->total_bytes += n; 585 h3c->total_bytes += n;
556 586
557 if (dc->send(dc, buf, n) != (ssize_t) n) { 587 if (dc->send(dc, buf, n) != (ssize_t) n) {
558 ngx_http_v3_close_uni_stream(dc); 588 goto failed;
559 return NGX_ERROR; 589 }
560 } 590
561 591 return NGX_OK;
562 return NGX_OK; 592
593 failed:
594
595 ngx_log_error(NGX_LOG_ERR, c->log, 0, "failed to send stream cancellation");
596
597 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
598 "failed to send stream cancellation");
599 ngx_http_v3_close_uni_stream(dc);
600
601 return NGX_ERROR;
563 } 602 }
564 603
565 604
566 ngx_int_t 605 ngx_int_t
567 ngx_http_v3_send_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc) 606 ngx_http_v3_send_inc_insert_count(ngx_connection_t *c, ngx_uint_t inc)
570 size_t n; 609 size_t n;
571 ngx_connection_t *dc; 610 ngx_connection_t *dc;
572 ngx_http_v3_session_t *h3c; 611 ngx_http_v3_session_t *h3c;
573 612
574 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, 613 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
575 "http3 client increment insert count %ui", inc); 614 "http3 send insert count increment %ui", inc);
576 615
577 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER); 616 dc = ngx_http_v3_get_uni_stream(c, NGX_HTTP_V3_STREAM_DECODER);
578 if (dc == NULL) { 617 if (dc == NULL) {
579 return NGX_ERROR; 618 return NGX_ERROR;
580 } 619 }
584 623
585 h3c = ngx_http_v3_get_session(c); 624 h3c = ngx_http_v3_get_session(c);
586 h3c->total_bytes += n; 625 h3c->total_bytes += n;
587 626
588 if (dc->send(dc, buf, n) != (ssize_t) n) { 627 if (dc->send(dc, buf, n) != (ssize_t) n) {
589 ngx_http_v3_close_uni_stream(dc); 628 goto failed;
590 return NGX_ERROR; 629 }
591 } 630
592 631 return NGX_OK;
593 return NGX_OK; 632
633 failed:
634
635 ngx_log_error(NGX_LOG_ERR, c->log, 0,
636 "failed to send insert count increment");
637
638 ngx_http_v3_finalize_connection(c, NGX_HTTP_V3_ERR_EXCESSIVE_LOAD,
639 "failed to send insert count increment");
640 ngx_http_v3_close_uni_stream(dc);
641
642 return NGX_ERROR;
594 } 643 }
595 644
596 645
597 ngx_int_t 646 ngx_int_t
598 ngx_http_v3_set_max_push_id(ngx_connection_t *c, uint64_t max_push_id) 647 ngx_http_v3_set_max_push_id(ngx_connection_t *c, uint64_t max_push_id)