11#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
22
33#include " application.h"
4+ #include < async_wrap-inl.h>
5+ #include < debug_utils-inl.h>
46#include < node_bob.h>
57#include < node_sockaddr-inl.h>
68#include < uv.h>
79#include < v8.h>
810#include " defs.h"
911#include " endpoint.h"
12+ #include " http3.h"
1013#include " packet.h"
1114#include " session.h"
1215
@@ -21,24 +24,48 @@ using v8::Value;
2124
2225namespace quic {
2326
24- struct Session ::Application::StreamData final {
25- // The actual number of vectors in the struct, up to kMaxVectorCount.
26- size_t count = 0 ;
27- size_t remaining = 0 ;
28- // The stream identifier. If this is a negative value then no stream is
29- // identified.
30- int64_t id = -1 ;
31- int fin = 0 ;
32- ngtcp2_vec data[kMaxVectorCount ]{};
33- ngtcp2_vec* buf = data;
34- BaseObjectPtr<Stream> stream;
35- };
36-
27+ // ============================================================================
28+ // Session::Application_Options
3729const Session::Application_Options Session::Application_Options::kDefault = {};
3830
31+ Session::Application_Options::operator const nghttp3_settings () const {
32+ // In theory, Application_Options might contain options for more than just
33+ // HTTP/3. Here we extract only the properties that are relevant to HTTP/3.
34+ return nghttp3_settings{
35+ max_field_section_size,
36+ static_cast <size_t >(qpack_max_dtable_capacity),
37+ static_cast <size_t >(qpack_encoder_max_dtable_capacity),
38+ static_cast <size_t >(qpack_blocked_streams),
39+ enable_connect_protocol,
40+ enable_datagrams,
41+ };
42+ }
43+
44+ std::string Session::Application_Options::ToString () const {
45+ DebugIndentScope indent;
46+ auto prefix = indent.Prefix ();
47+ std::string res (" {" );
48+ res += prefix + " max header pairs: " + std::to_string (max_header_pairs);
49+ res += prefix + " max header length: " + std::to_string (max_header_length);
50+ res += prefix +
51+ " max field section size: " + std::to_string (max_field_section_size);
52+ res += prefix + " qpack max dtable capacity: " +
53+ std::to_string (qpack_max_dtable_capacity);
54+ res += prefix + " qpack encoder max dtable capacity: " +
55+ std::to_string (qpack_encoder_max_dtable_capacity);
56+ res += prefix +
57+ " qpack blocked streams: " + std::to_string (qpack_blocked_streams);
58+ res += prefix + " enable connect protocol: " +
59+ (enable_connect_protocol ? std::string (" yes" ) : std::string (" no" ));
60+ res += prefix + " enable datagrams: " +
61+ (enable_datagrams ? std::string (" yes" ) : std::string (" no" ));
62+ res += indent.Close ();
63+ return res;
64+ }
65+
3966Maybe<Session::Application_Options> Session::Application_Options::From (
4067 Environment* env, Local<Value> value) {
41- if (value.IsEmpty ()) {
68+ if (value.IsEmpty () || (!value-> IsUndefined () && !value-> IsObject ()) ) {
4269 THROW_ERR_INVALID_ARG_TYPE (env, " options must be an object" );
4370 return Nothing<Application_Options>();
4471 }
@@ -49,11 +76,6 @@ Maybe<Session::Application_Options> Session::Application_Options::From(
4976 return Just<Application_Options>(options);
5077 }
5178
52- if (!value->IsObject ()) {
53- THROW_ERR_INVALID_ARG_TYPE (env, " options must be an object" );
54- return Nothing<Application_Options>();
55- }
56-
5779 auto params = value.As <Object>();
5880
5981#define SET (name ) \
@@ -63,7 +85,8 @@ Maybe<Session::Application_Options> Session::Application_Options::From(
6385
6486 if (!SET (max_header_pairs) || !SET (max_header_length) ||
6587 !SET (max_field_section_size) || !SET (qpack_max_dtable_capacity) ||
66- !SET (qpack_encoder_max_dtable_capacity) || !SET (qpack_blocked_streams)) {
88+ !SET (qpack_encoder_max_dtable_capacity) || !SET (qpack_blocked_streams) ||
89+ !SET (enable_connect_protocol) || !SET (enable_datagrams)) {
6790 return Nothing<Application_Options>();
6891 }
6992
@@ -78,16 +101,22 @@ Session::Application::Application(Session* session, const Options& options)
78101bool Session::Application::Start () {
79102 // By default there is nothing to do. Specific implementations may
80103 // override to perform more actions.
104+ Debug (session_, " Session application started" );
81105 return true ;
82106}
83107
84108void Session::Application::AcknowledgeStreamData (Stream* stream,
85109 size_t datalen) {
110+ Debug (session_,
111+ " Application acknowledging stream %" PRIi64 " data: %zu" ,
112+ stream->id (),
113+ datalen);
86114 DCHECK_NOT_NULL (stream);
87115 stream->Acknowledge (datalen);
88116}
89117
90118void Session::Application::BlockStream (int64_t id) {
119+ Debug (session_, " Application blocking stream %" PRIi64, id);
91120 auto stream = session ().FindStream (id);
92121 if (stream) stream->EmitBlocked ();
93122}
@@ -96,6 +125,7 @@ bool Session::Application::CanAddHeader(size_t current_count,
96125 size_t current_headers_length,
97126 size_t this_header_length) {
98127 // By default headers are not supported.
128+ Debug (session_, " Application cannot add header" );
99129 return false ;
100130}
101131
@@ -104,33 +134,39 @@ bool Session::Application::SendHeaders(const Stream& stream,
104134 const v8::Local<v8::Array>& headers,
105135 HeadersFlags flags) {
106136 // By default do nothing.
137+ Debug (session_, " Application cannot send headers" );
107138 return false ;
108139}
109140
110141void Session::Application::ResumeStream (int64_t id) {
142+ Debug (session_, " Application resuming stream %" PRIi64, id);
111143 // By default do nothing.
112144}
113145
114146void Session::Application::ExtendMaxStreams (EndpointLabel label,
115147 Direction direction,
116148 uint64_t max_streams) {
149+ Debug (session_, " Application extending max streams" );
117150 // By default do nothing.
118151}
119152
120153void Session::Application::ExtendMaxStreamData (Stream* stream,
121154 uint64_t max_data) {
155+ Debug (session_, " Application extending max stream data" );
122156 // By default do nothing.
123157}
124158
125159void Session::Application::CollectSessionTicketAppData (
126160 SessionTicket::AppData* app_data) const {
161+ Debug (session_, " Application collecting session ticket app data" );
127162 // By default do nothing.
128163}
129164
130165SessionTicket::AppData::Status
131166Session::Application::ExtractSessionTicketAppData (
132167 const SessionTicket::AppData& app_data,
133168 SessionTicket::AppData::Source::Flag flag) {
169+ Debug (session_, " Application extracting session ticket app data" );
134170 // By default we do not have any application data to retrieve.
135171 return flag == SessionTicket::AppData::Source::Flag::STATUS_RENEW
136172 ? SessionTicket::AppData::Status::TICKET_USE_RENEW
@@ -140,14 +176,16 @@ Session::Application::ExtractSessionTicketAppData(
140176void Session::Application::SetStreamPriority (const Stream& stream,
141177 StreamPriority priority,
142178 StreamPriorityFlags flags) {
179+ Debug (
180+ session_, " Application setting stream %" PRIi64 " priority" , stream.id ());
143181 // By default do nothing.
144182}
145183
146184StreamPriority Session::Application::GetStreamPriority (const Stream& stream) {
147185 return StreamPriority::DEFAULT;
148186}
149187
150- BaseObjectPtr< Packet> Session::Application::CreateStreamDataPacket () {
188+ Packet* Session::Application::CreateStreamDataPacket () {
151189 return Packet::Create (env (),
152190 session_->endpoint_ .get (),
153191 session_->remote_address_ ,
@@ -156,24 +194,37 @@ BaseObjectPtr<Packet> Session::Application::CreateStreamDataPacket() {
156194}
157195
158196void Session::Application::StreamClose (Stream* stream, QuicError error) {
197+ Debug (session_,
198+ " Application closing stream %" PRIi64 " with error %s" ,
199+ stream->id (),
200+ error);
159201 stream->Destroy (error);
160202}
161203
162204void Session::Application::StreamStopSending (Stream* stream, QuicError error) {
205+ Debug (session_,
206+ " Application stopping sending on stream %" PRIi64 " with error %s" ,
207+ stream->id (),
208+ error);
163209 DCHECK_NOT_NULL (stream);
164210 stream->ReceiveStopSending (error);
165211}
166212
167213void Session::Application::StreamReset (Stream* stream,
168214 uint64_t final_size,
169215 QuicError error) {
216+ Debug (session_,
217+ " Application resetting stream %" PRIi64 " with error %s" ,
218+ stream->id (),
219+ error);
170220 stream->ReceiveStreamReset (final_size, error);
171221}
172222
173223void Session::Application::SendPendingData () {
224+ Debug (session_, " Application sending pending data" );
174225 PathStorage path;
175226
176- BaseObjectPtr< Packet> packet;
227+ Packet* packet = nullptr ;
177228 uint8_t * pos = nullptr ;
178229 int err = 0 ;
179230
@@ -182,6 +233,7 @@ void Session::Application::SendPendingData() {
182233 size_t packetSendCount = 0 ;
183234
184235 const auto updateTimer = [&] {
236+ Debug (session_, " Application updating the session timer" );
185237 ngtcp2_conn_update_pkt_tx_time (*session_, uv_hrtime ());
186238 session_->UpdateTimer ();
187239 };
@@ -209,9 +261,9 @@ void Session::Application::SendPendingData() {
209261 return session_->Close (Session::CloseMethod::SILENT);
210262 }
211263
212- if (! packet) {
264+ if (packet == nullptr ) {
213265 packet = CreateStreamDataPacket ();
214- if (! packet) {
266+ if (packet == nullptr ) {
215267 session_->last_error_ = QuicError::ForNgtcp2Error (NGTCP2_ERR_INTERNAL);
216268 return session_->Close (Session::CloseMethod::SILENT);
217269 }
@@ -319,12 +371,14 @@ class DefaultApplication final : public Session::Application {
319371 const uint8_t * data,
320372 size_t datalen,
321373 Stream::ReceiveDataFlags flags) override {
374+ Debug (&session (), " Default application receiving stream data" );
322375 DCHECK_NOT_NULL (stream);
323376 if (!stream->is_destroyed ()) stream->ReceiveData (data, datalen, flags);
324377 return true ;
325378 }
326379
327380 int GetStreamData (StreamData* stream_data) override {
381+ Debug (&session (), " Default application getting stream data" );
328382 DCHECK_NOT_NULL (stream_data);
329383 // If the queue is empty, there aren't any streams with data yet
330384 if (stream_queue_.IsEmpty ()) return 0 ;
@@ -380,7 +434,10 @@ class DefaultApplication final : public Session::Application {
380434 return 0 ;
381435 }
382436
383- void ResumeStream (int64_t id) override { ScheduleStream (id); }
437+ void ResumeStream (int64_t id) override {
438+ Debug (&session (), " Default application resuming stream %" PRIi64, id);
439+ ScheduleStream (id);
440+ }
384441
385442 bool ShouldSetFin (const StreamData& stream_data) override {
386443 auto const is_empty = [](auto vec, size_t cnt) {
@@ -394,6 +451,7 @@ class DefaultApplication final : public Session::Application {
394451 }
395452
396453 bool StreamCommit (StreamData* stream_data, size_t datalen) override {
454+ Debug (&session (), " Default application committing stream data" );
397455 DCHECK_NOT_NULL (stream_data);
398456 const auto consume = [](ngtcp2_vec** pvec, size_t * pcnt, size_t len) {
399457 ngtcp2_vec* v = *pvec;
@@ -425,13 +483,15 @@ class DefaultApplication final : public Session::Application {
425483
426484 private:
427485 void ScheduleStream (int64_t id) {
486+ Debug (&session (), " Default application scheduling stream %" PRIi64, id);
428487 auto stream = session ().FindStream (id);
429488 if (stream && !stream->is_destroyed ()) {
430489 stream->Schedule (&stream_queue_);
431490 }
432491 }
433492
434493 void UnscheduleStream (int64_t id) {
494+ Debug (&session (), " Default application unscheduling stream %" PRIi64, id);
435495 auto stream = session ().FindStream (id);
436496 if (stream && !stream->is_destroyed ()) stream->Unschedule ();
437497 }
@@ -440,13 +500,15 @@ class DefaultApplication final : public Session::Application {
440500};
441501
442502std::unique_ptr<Session::Application> Session::select_application () {
443- // if (config.options.crypto_options.alpn == NGHTTP3_ALPN_H3)
444- // return std::make_unique<Http3>(session,
445- // config.options.application_options);
446-
447503 // In the future, we may end up supporting additional QUIC protocols. As they
448504 // are added, extend the cases here to create and return them.
449505
506+ if (config_.options .tls_options .alpn == NGHTTP3_ALPN_H3) {
507+ Debug (this , " Selecting HTTP/3 application" );
508+ return createHttp3Application (this , config_.options .application_options );
509+ }
510+
511+ Debug (this , " Selecting default application" );
450512 return std::make_unique<DefaultApplication>(
451513 this , config_.options .application_options );
452514}
0 commit comments