Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 79b960a

Browse filesBrowse files
committed
quic: update http3 impl details
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode/Opus 4.6 PR-URL: #62387 Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
1 parent 57186e5 commit 79b960a
Copy full SHA for 79b960a

1 file changed

+111-26Lines changed: 111 additions & 26 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/quic/http3.cc‎

Copy file name to clipboardExpand all lines: src/quic/http3.cc
+111-26Lines changed: 111 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -319,14 +319,20 @@ class Http3ApplicationImpl final : public Session::Application {
319319

320320
void CollectSessionTicketAppData(
321321
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.
324330
}
325331

326332
SessionTicket::AppData::Status ExtractSessionTicketAppData(
327333
const SessionTicket::AppData& app_data,
328334
SessionTicket::AppData::Source::Flag flag) override {
329-
// There's currently nothing stored here but we might do so later.
335+
// See CollectSessionTicketAppData above.
330336
return flag == SessionTicket::AppData::Source::Flag::STATUS_RENEW
331337
? SessionTicket::AppData::Status::TICKET_USE_RENEW
332338
: SessionTicket::AppData::Status::TICKET_USE;
@@ -448,10 +454,42 @@ class Http3ApplicationImpl final : public Session::Application {
448454
return false;
449455
}
450456

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+
451483
StreamPriority GetStreamPriority(const Stream& stream) override {
452484
nghttp3_pri pri;
453485
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).
455493
switch (pri.urgency) {
456494
case NGHTTP3_URGENCY_HIGH:
457495
return StreamPriority::HIGH;
@@ -673,22 +711,23 @@ class Http3ApplicationImpl final : public Session::Application {
673711
stream->ReceiveStreamReset(0, QuicError::ForApplication(app_error_code));
674712
}
675713

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);
692731
}
693732

694733
void OnReceiveSettings(const nghttp3_settings* settings) {
@@ -747,9 +786,55 @@ class Http3ApplicationImpl final : public Session::Application {
747786
uint32_t* pflags,
748787
void* conn_user_data,
749788
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;
751835
}
752836

837+
753838
static int on_acked_stream_data(nghttp3_conn* conn,
754839
int64_t stream_id,
755840
uint64_t datalen,
@@ -934,7 +1019,7 @@ class Http3ApplicationImpl final : public Session::Application {
9341019

9351020
static int on_shutdown(nghttp3_conn* conn, int64_t id, void* conn_user_data) {
9361021
NGHTTP3_CALLBACK_SCOPE(app);
937-
app.OnShutdown();
1022+
app.OnShutdown(id);
9381023
return NGTCP2_SUCCESS;
9391024
}
9401025

@@ -950,14 +1035,14 @@ class Http3ApplicationImpl final : public Session::Application {
9501035
const uint8_t* origin,
9511036
size_t originlen,
9521037
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.
9551041
return NGTCP2_SUCCESS;
9561042
}
9571043

9581044
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.
9611046
return NGTCP2_SUCCESS;
9621047
}
9631048

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.