@@ -295,221 +295,6 @@ void Session::Application::ReceiveStreamReset(Stream* stream,
295295 stream->ReceiveStreamReset (final_size, std::move (error));
296296}
297297
298- // ============================================================================
299- // The DefaultApplication is the default implementation of Session::Application
300- // that is used for all unrecognized ALPN identifiers.
301- class DefaultApplication final : public Session::Application {
302- public:
303- // Marked NOLINT because the cpp linter gets confused about this using
304- // statement not being sorted with the using v8 statements at the top
305- // of the namespace.
306- DefaultApplication (Session* session, const Options& options)
307- : Session::Application(session, options), options_(options) {}
308-
309- const Options& options () const override { return options_; }
310-
311- Session::Application::Type type () const override {
312- return Session::Application::Type::DEFAULT ;
313- }
314-
315- error_code GetNoErrorCode () const override { return 0 ; }
316-
317- // Raw QUIC has no application-defined "general failure" code, so
318- // fall back to the QUIC transport-level INTERNAL_ERROR (0x1) used
319- // by ngtcp2 for unspecified failures.
320- error_code GetInternalErrorCode () const override {
321- return NGTCP2_INTERNAL_ERROR ;
322- }
323-
324- void EarlyDataRejected () override {
325- // Destroy all open streams — ngtcp2 has already discarded their
326- // internal state when it rejected the early data. Use the
327- // application's internal error code since this is an error
328- // condition (code 0 would be treated as a clean close).
329- session ().DestroyAllStreams (
330- QuicError::ForApplication (GetInternalErrorCode ()));
331- if (!session ().is_destroyed ()) {
332- session ().EmitEarlyDataRejected ();
333- }
334- }
335-
336- void CollectSessionTicketAppData (
337- SessionTicket::AppData* app_data) const override {
338- const auto & atd = session ().config ().options .app_ticket_data ;
339- if (!atd.has_value () || atd->length () == 0 ) {
340- // No app data configured — write just the type byte (base behaviour).
341- Session::Application::CollectSessionTicketAppData (app_data);
342- return ;
343- }
344- // Layout: [type byte][opaque app data].
345- uv_buf_t bytes = *atd;
346- std::vector<uint8_t > buf;
347- buf.reserve (1 + bytes.len );
348- buf.push_back (static_cast <uint8_t >(type ())); // Type::DEFAULT
349- const auto * p = reinterpret_cast <const uint8_t *>(bytes.base );
350- buf.insert (buf.end (), p, p + bytes.len );
351- app_data->Set (
352- uv_buf_init (reinterpret_cast <char *>(buf.data ()), buf.size ()));
353- }
354-
355- bool ApplySessionTicketData (const PendingTicketAppData& data) override {
356- return std::holds_alternative<DefaultTicketData>(data);
357- }
358-
359- bool ReceiveStreamOpen (stream_id id) override {
360- auto stream = session ().CreateStream (id);
361- if (!stream || session ().is_destroyed ()) [[unlikely]] {
362- return !session ().is_destroyed ();
363- }
364- return true ;
365- }
366-
367- bool ReceiveStreamData (stream_id id,
368- const uint8_t * data,
369- size_t datalen,
370- const Stream::ReceiveDataFlags& flags,
371- void * stream_user_data) override {
372- BaseObjectPtr<Stream> stream;
373- if (stream_user_data == nullptr ) {
374- // This is the first time we're seeing this stream. Implicitly create it.
375- stream = session ().CreateStream (id);
376- if (!stream || session ().is_destroyed ()) [[unlikely]] {
377- // We couldn't create the stream, or the session was destroyed
378- // during the onstream callback (via MakeCallback re-entrancy).
379- return false ;
380- }
381- } else {
382- stream = BaseObjectPtr<Stream>(Stream::From (stream_user_data));
383- if (!stream) {
384- Debug (&session (),
385- " Default application failed to get existing stream "
386- " from user data" );
387- return false ;
388- }
389- }
390-
391- CHECK (stream);
392-
393- // Now we can actually receive the data! Woo!
394- stream->ReceiveData (data, datalen, flags);
395- return true ;
396- }
397-
398- int GetStreamData (StreamData* stream_data) override {
399- // Reset the state of stream_data before proceeding...
400- stream_data->id = -1 ;
401- stream_data->count = 0 ;
402- stream_data->fin = 0 ;
403- stream_data->stream .reset ();
404- Debug (&session (), " Default application getting stream data" );
405- DCHECK_NOT_NULL (stream_data);
406- // If the queue is empty, there aren't any streams with data yet
407-
408- // If the connection-level flow control window is exhausted,
409- // there is no point in pulling stream data.
410- if (!session ().max_data_left ()) return 0 ;
411- if (stream_queue_.IsEmpty ()) return 0 ;
412-
413- Stream* stream = stream_queue_.PopFront ();
414- CHECK_NOT_NULL (stream);
415- stream_data->stream .reset (stream);
416- stream_data->id = stream->id ();
417- auto next =
418- [&](int status, const ngtcp2_vec* data, size_t count, bob::Done done) {
419- switch (status) {
420- case bob::Status::STATUS_BLOCK :
421- // Fall through
422- case bob::Status::STATUS_WAIT :
423- return ;
424- case bob::Status::STATUS_EOS :
425- stream_data->fin = 1 ;
426- }
427-
428- // It is possible that the data pointers returned are not actually
429- // the data pointers in the stream_data. If that's the case, we need
430- // to copy over the pointers.
431- count = std::min (count, kMaxVectorCount );
432- ngtcp2_vec* dest = *stream_data;
433- if (dest != data) {
434- for (size_t n = 0 ; n < count; n++) {
435- dest[n] = data[n];
436- }
437- }
438-
439- stream_data->count = count;
440-
441- if (count > 0 ) {
442- stream->Schedule (&stream_queue_);
443- }
444-
445- // Not calling done here because we defer committing
446- // the data until after we're sure it's written.
447- };
448-
449- if (!stream->is_eos ()) [[likely]] {
450- int ret = stream->Pull (std::move (next),
451- bob::Options::OPTIONS_SYNC ,
452- stream_data->data ,
453- arraysize (stream_data->data ),
454- kMaxVectorCount );
455- if (ret == bob::Status::STATUS_EOS ) {
456- stream_data->fin = 1 ;
457- }
458- } else {
459- stream_data->fin = 1 ;
460- }
461-
462- return 0 ;
463- }
464-
465- void ResumeStream (stream_id id) override { ScheduleStream (id); }
466-
467- void BlockStream (stream_id id) override {
468- if (auto stream = session ().FindStream (id)) [[likely]] {
469- // Remove the stream from the send queue. It will be re-scheduled
470- // via ExtendMaxStreamData when the peer grants more flow control.
471- // Without this, SendPendingData would repeatedly pop and retry
472- // the same blocked stream in an infinite loop.
473- stream->Unschedule ();
474- stream->EmitBlocked ();
475- }
476- }
477-
478- void ExtendMaxStreamData (Stream* stream, uint64_t max_data) override {
479- // The peer granted more flow control for this stream. Re-schedule
480- // it so SendPendingData will resume writing.
481- DCHECK_NOT_NULL (stream);
482- stream->Schedule (&stream_queue_);
483- }
484-
485- bool StreamCommit (StreamData* stream_data, size_t datalen) override {
486- DCHECK_NOT_NULL (stream_data);
487- CHECK (stream_data->stream );
488- stream_data->stream ->Commit (datalen, stream_data->fin );
489- return true ;
490- }
491-
492- SET_SELF_SIZE (DefaultApplication)
493- SET_MEMORY_INFO_NAME (DefaultApplication)
494- SET_NO_MEMORY_INFO ()
495-
496- private:
497- void ScheduleStream (stream_id id) {
498- if (auto stream = session ().FindStream (id)) [[likely]] {
499- stream->Schedule (&stream_queue_);
500- }
501- }
502-
503- Options options_;
504-
505- Stream::Queue stream_queue_;
506- };
507-
508- std::unique_ptr<Session::Application> CreateDefaultApplication (
509- Session* session, const Session::Application_Options& options) {
510- return std::make_unique<DefaultApplication>(session, options);
511- }
512-
513298} // namespace quic
514299} // namespace node
515300
0 commit comments