| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -319,14 +319,20 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 319 | 319 | ||
| 320 | 320 | void CollectSessionTicketAppData( | |
| 321 | 321 | SessionTicket::AppData* app_data) const override { | |
| 322 | - // TODO(@jasnell): There's currently nothing to store but there may be | ||
| 323 | - // later. | ||
| 322 | + // TODO(@jasnell): When HTTP/3 settings become dynamic or | ||
| 323 | + // configurable per-connection, store them here so they can be | ||
| 324 | + // validated on 0-RTT resumption. Candidates include: | ||
| 325 | + // max_field_section_size, qpack_max_dtable_capacity, | ||
| 326 | + // qpack_encoder_max_dtable_capacity, qpack_blocked_streams, | ||
| 327 | + // enable_connect_protocol, and enable_datagrams. On extraction, | ||
| 328 | + // compare stored values against current settings and return | ||
| 329 | + // TICKET_IGNORE_RENEW if incompatible. | ||
| 324 | 330 | } | |
| 325 | 331 | ||
| 326 | 332 | SessionTicket::AppData::Status ExtractSessionTicketAppData( | |
| 327 | 333 | const SessionTicket::AppData& app_data, | |
| 328 | 334 | SessionTicket::AppData::Source::Flag flag) override { | |
| 329 | - // There's currently nothing stored here but we might do so later. | ||
| 335 | + // See CollectSessionTicketAppData above. | ||
| 330 | 336 | return flag == SessionTicket::AppData::Source::Flag::STATUS_RENEW | |
| 331 | 337 | ? SessionTicket::AppData::Status::TICKET_USE_RENEW | |
| 332 | 338 | : SessionTicket::AppData::Status::TICKET_USE; | |
@@ -448,10 +454,42 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 448 | 454 | return false; | |
| 449 | 455 | } | |
| 450 | 456 | ||
| 457 | + void SetStreamPriority(const Stream& stream, | ||
| 458 | + StreamPriority priority, | ||
| 459 | + StreamPriorityFlags flags) override { | ||
| 460 | + nghttp3_pri pri; | ||
| 461 | + pri.inc = (flags == StreamPriorityFlags::NON_INCREMENTAL) ? 0 : 1; | ||
| 462 | + switch (priority) { | ||
| 463 | + case StreamPriority::HIGH: | ||
| 464 | + pri.urgency = NGHTTP3_URGENCY_HIGH; | ||
| 465 | + break; | ||
| 466 | + case StreamPriority::LOW: | ||
| 467 | + pri.urgency = NGHTTP3_URGENCY_LOW; | ||
| 468 | + break; | ||
| 469 | + default: | ||
| 470 | + pri.urgency = NGHTTP3_DEFAULT_URGENCY; | ||
| 471 | + break; | ||
| 472 | + } | ||
| 473 | + if (session().is_server()) { | ||
| 474 | + nghttp3_conn_set_server_stream_priority( | ||
| 475 | + *this, stream.id(), &pri); | ||
| 476 | + } | ||
| 477 | + // Client-side priority is set at request submission time via | ||
| 478 | + // nghttp3_conn_submit_request and is not typically changed | ||
| 479 | + // after the fact. The client API takes a serialized RFC 9218 | ||
| 480 | + // field value rather than an nghttp3_pri struct. | ||
| 481 | + } | ||
| 482 | + | ||
| 451 | 483 | StreamPriority GetStreamPriority(const Stream& stream) override { | |
| 452 | 484 | nghttp3_pri pri; | |
| 453 | 485 | if (nghttp3_conn_get_stream_priority(*this, &pri, stream.id()) == 0) { | |
| 454 | - // TODO(@jasnell): Support the incremental flag | ||
| 486 | + // TODO(@jasnell): The nghttp3_pri.inc (incremental) flag is | ||
| 487 | + // not yet exposed. When priority-based stream scheduling is | ||
| 488 | + // implemented, GetStreamPriority should return both urgency | ||
| 489 | + // and the incremental flag (making get/set symmetrical). | ||
| 490 | + // The inc flag determines whether the server should interleave | ||
| 491 | + // data from this stream with others of the same urgency | ||
| 492 | + // (inc=1) or complete it first (inc=0). | ||
| 455 | 493 | switch (pri.urgency) { | |
| 456 | 494 | case NGHTTP3_URGENCY_HIGH: | |
| 457 | 495 | return StreamPriority::HIGH; | |
@@ -673,22 +711,23 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 673 | 711 | stream->ReceiveStreamReset(0, QuicError::ForApplication(app_error_code)); | |
| 674 | 712 | } | |
| 675 | 713 | ||
| 676 | - void OnShutdown() { | ||
| 677 | - // This callback is invoked when we receive a request to gracefully shutdown | ||
| 678 | - // the http3 connection. For client, the id is the stream id of a client | ||
| 679 | - // initiated stream. For server, the id is the stream id of a server | ||
| 680 | - // initiated stream. Once received, the other side is guaranteed not to | ||
| 681 | - // process any more data. | ||
| 682 | - | ||
| 683 | - // On the client side, if id is equal to NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID, | ||
| 684 | - // or on the server if the id is equal to NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID, | ||
| 685 | - // then this is a request to begin a graceful shutdown. | ||
| 686 | - | ||
| 687 | - // This can be called multiple times but the id can only stay the same or | ||
| 688 | - // *decrease*. | ||
| 689 | - | ||
| 690 | - // TODO(@jasnell): Need to determine exactly how to handle. | ||
| 691 | - Debug(&session(), "HTTP/3 application received shutdown notice"); | ||
| 714 | + void OnShutdown(int64_t id) { | ||
| 715 | + // The peer has sent a GOAWAY frame initiating a graceful shutdown. | ||
| 716 | + // For a client, id is the stream ID beyond which the server will | ||
| 717 | + // not process requests. For a server, id is a push ID (server | ||
| 718 | + // push is not implemented). Streams/pushes with IDs >= id will | ||
| 719 | + // not be processed by the peer. | ||
| 720 | + // | ||
| 721 | + // When id equals NGHTTP3_SHUTDOWN_NOTICE_STREAM_ID (client) or | ||
| 722 | + // NGHTTP3_SHUTDOWN_NOTICE_PUSH_ID (server), this is a notice of | ||
| 723 | + // intent to shut down rather than an immediate refusal. | ||
| 724 | + // | ||
| 725 | + // This can be called multiple times with a decreasing id as the | ||
| 726 | + // peer progressively reduces the set of streams it will process. | ||
| 727 | + Debug(&session(), | ||
| 728 | + "HTTP/3 received GOAWAY (id=%" PRIi64 ")", | ||
| 729 | + id); | ||
| 730 | + session().Close(Session::CloseMethod::GRACEFUL); | ||
| 692 | 731 | } | |
| 693 | 732 | ||
| 694 | 733 | void OnReceiveSettings(const nghttp3_settings* settings) { | |
@@ -747,9 +786,55 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 747 | 786 | uint32_t* pflags, | |
| 748 | 787 | void* conn_user_data, | |
| 749 | 788 | void* stream_user_data) { | |
| 750 | - return NGTCP2_SUCCESS; | ||
| 789 | + auto ptr = From(conn, conn_user_data); | ||
| 790 | + CHECK_NOT_NULL(ptr); | ||
| 791 | + auto& app = *ptr; | ||
| 792 | + NgHttp3CallbackScope scope(app.env()); | ||
| 793 | + | ||
| 794 | + auto stream = app.session().FindStream(stream_id); | ||
| 795 | + if (!stream) return NGHTTP3_ERR_CALLBACK_FAILURE; | ||
| 796 | + | ||
| 797 | + if (stream->is_eos()) { | ||
| 798 | + *pflags |= NGHTTP3_DATA_FLAG_EOF; | ||
| 799 | + return 0; | ||
| 800 | + } | ||
| 801 | + | ||
| 802 | + size_t max_count = std::min(veccnt, | ||
| 803 | + static_cast<size_t>(kMaxVectorCount)); | ||
| 804 | + nghttp3_ssize result = 0; | ||
| 805 | + | ||
| 806 | + auto next = [&](int status, | ||
| 807 | + const ngtcp2_vec* data, | ||
| 808 | + size_t count, | ||
| 809 | + bob::Done done) { | ||
| 810 | + switch (status) { | ||
| 811 | + case bob::Status::STATUS_BLOCK: | ||
| 812 | + case bob::Status::STATUS_WAIT: | ||
| 813 | + result = NGHTTP3_ERR_WOULDBLOCK; | ||
| 814 | + return; | ||
| 815 | + case bob::Status::STATUS_EOS: | ||
| 816 | + *pflags |= NGHTTP3_DATA_FLAG_EOF; | ||
| 817 | + break; | ||
| 818 | + } | ||
| 819 | + count = std::min(count, max_count); | ||
| 820 | + for (size_t n = 0; n < count; n++) { | ||
| 821 | + vec[n].base = data[n].base; | ||
| 822 | + vec[n].len = data[n].len; | ||
| 823 | + } | ||
| 824 | + result = static_cast<nghttp3_ssize>(count); | ||
| 825 | + }; | ||
| 826 | + | ||
| 827 | + ngtcp2_vec data[kMaxVectorCount]; | ||
| 828 | + stream->Pull(std::move(next), | ||
| 829 | + bob::Options::OPTIONS_SYNC, | ||
| 830 | + data, | ||
| 831 | + max_count, | ||
| 832 | + max_count); | ||
| 833 | + | ||
| 834 | + return result; | ||
| 751 | 835 | } | |
| 752 | 836 | ||
| 837 | + | ||
| 753 | 838 | static int on_acked_stream_data(nghttp3_conn* conn, | |
| 754 | 839 | int64_t stream_id, | |
| 755 | 840 | uint64_t datalen, | |
@@ -934,7 +1019,7 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 934 | 1019 | ||
| 935 | 1020 | static int on_shutdown(nghttp3_conn* conn, int64_t id, void* conn_user_data) { | |
| 936 | 1021 | NGHTTP3_CALLBACK_SCOPE(app); | |
| 937 | - app.OnShutdown(); | ||
| 1022 | + app.OnShutdown(id); | ||
| 938 | 1023 | return NGTCP2_SUCCESS; | |
| 939 | 1024 | } | |
| 940 | 1025 | ||
@@ -950,14 +1035,14 @@ class Http3ApplicationImpl final : public Session::Application { | |||
| 950 | 1035 | const uint8_t* origin, | |
| 951 | 1036 | size_t originlen, | |
| 952 | 1037 | void* conn_user_data) { | |
| 953 | - // TODO(@jasnell): Handle the origin callback. This is called | ||
| 954 | - // when a single origin in an ORIGIN frame is received. | ||
| 1038 | + // ORIGIN frames (RFC 8336) are used for connection coalescing | ||
| 1039 | + // across multiple origins. Not yet implemented u2014 requires | ||
| 1040 | + // connection pooling and multi-origin reuse support. | ||
| 955 | 1041 | return NGTCP2_SUCCESS; | |
| 956 | 1042 | } | |
| 957 | 1043 | ||
| 958 | 1044 | static int on_end_origin(nghttp3_conn* conn, void* conn_user_data) { | |
| 959 | - // TODO(@jasnell): Handle the end of origin callback. This is called | ||
| 960 | - // when the end of an ORIGIN frame is received. | ||
| 1045 | + // See on_receive_origin above. | ||
| 961 | 1046 | return NGTCP2_SUCCESS; | |
| 962 | 1047 | } | |
| 963 | 1048 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments