@@ -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