LCOV - code coverage report
Current view: top level - source/common/quic - envoy_quic_server_session.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 77 162 47.5 %
Date: 2024-01-05 06:35:25 Functions: 14 24 58.3 %

          Line data    Source code
       1             : #include "source/common/quic/envoy_quic_server_session.h"
       2             : 
       3             : #include <iterator>
       4             : #include <memory>
       5             : #include <type_traits>
       6             : 
       7             : #include "source/common/common/assert.h"
       8             : #include "source/common/quic/envoy_quic_proof_source.h"
       9             : #include "source/common/quic/envoy_quic_server_stream.h"
      10             : 
      11             : #include "quic_filter_manager_connection_impl.h"
      12             : 
      13             : namespace Envoy {
      14             : namespace Quic {
      15             : 
      16             : EnvoyQuicServerSession::EnvoyQuicServerSession(
      17             :     const quic::QuicConfig& config, const quic::ParsedQuicVersionVector& supported_versions,
      18             :     std::unique_ptr<EnvoyQuicServerConnection> connection, quic::QuicSession::Visitor* visitor,
      19             :     quic::QuicCryptoServerStream::Helper* helper, const quic::QuicCryptoServerConfig* crypto_config,
      20             :     quic::QuicCompressedCertsCache* compressed_certs_cache, Event::Dispatcher& dispatcher,
      21             :     uint32_t send_buffer_limit, QuicStatNames& quic_stat_names, Stats::Scope& listener_scope,
      22             :     EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory,
      23             :     std::unique_ptr<StreamInfo::StreamInfo>&& stream_info, QuicConnectionStats& connection_stats)
      24             :     : quic::QuicServerSessionBase(config, supported_versions, connection.get(), visitor, helper,
      25             :                                   crypto_config, compressed_certs_cache),
      26             :       QuicFilterManagerConnectionImpl(
      27             :           *connection, connection->connection_id(), dispatcher, send_buffer_limit,
      28             :           std::make_shared<QuicSslConnectionInfo>(*this), std::move(stream_info)),
      29             :       quic_connection_(std::move(connection)), quic_stat_names_(quic_stat_names),
      30             :       listener_scope_(listener_scope), crypto_server_stream_factory_(crypto_server_stream_factory),
      31         515 :       connection_stats_(connection_stats) {}
      32             : 
      33         515 : EnvoyQuicServerSession::~EnvoyQuicServerSession() {
      34         515 :   ASSERT(!quic_connection_->connected());
      35         515 :   QuicFilterManagerConnectionImpl::network_connection_ = nullptr;
      36         515 : }
      37             : 
      38           0 : absl::string_view EnvoyQuicServerSession::requestedServerName() const {
      39           0 :   return {GetCryptoStream()->crypto_negotiated_params().sni};
      40           0 : }
      41             : 
      42             : std::unique_ptr<quic::QuicCryptoServerStreamBase>
      43             : EnvoyQuicServerSession::CreateQuicCryptoServerStream(
      44             :     const quic::QuicCryptoServerConfig* crypto_config,
      45         515 :     quic::QuicCompressedCertsCache* compressed_certs_cache) {
      46         515 :   return crypto_server_stream_factory_.createEnvoyQuicCryptoServerStream(
      47         515 :       crypto_config, compressed_certs_cache, this, stream_helper(),
      48         515 :       makeOptRefFromPtr(position_.has_value() ? &position_->filter_chain_.transportSocketFactory()
      49         515 :                                               : nullptr),
      50         515 :       dispatcher());
      51         515 : }
      52             : 
      53         232 : quic::QuicSpdyStream* EnvoyQuicServerSession::CreateIncomingStream(quic::QuicStreamId id) {
      54         232 :   if (!ShouldCreateIncomingStream(id)) {
      55           0 :     return nullptr;
      56           0 :   }
      57         232 :   if (!codec_stats_.has_value() || !http3_options_.has_value()) {
      58           0 :     ENVOY_BUG(false,
      59           0 :               fmt::format(
      60           0 :                   "Quic session {} attempts to create stream {} before HCM filter is initialized.",
      61           0 :                   this->id(), id));
      62           0 :     return nullptr;
      63           0 :   }
      64         232 :   auto stream = new EnvoyQuicServerStream(id, this, quic::BIDIRECTIONAL, codec_stats_.value(),
      65         232 :                                           http3_options_.value(), headers_with_underscores_action_);
      66         232 :   ActivateStream(absl::WrapUnique(stream));
      67         232 :   if (aboveHighWatermark()) {
      68           0 :     stream->runHighWatermarkCallbacks();
      69           0 :   }
      70         232 :   setUpRequestDecoder(*stream);
      71         232 :   return stream;
      72         232 : }
      73             : 
      74             : quic::QuicSpdyStream*
      75           0 : EnvoyQuicServerSession::CreateIncomingStream(quic::PendingStream* /*pending*/) {
      76           0 :   IS_ENVOY_BUG("Unexpected disallowed server push call");
      77           0 :   return nullptr;
      78           0 : }
      79             : 
      80           0 : quic::QuicSpdyStream* EnvoyQuicServerSession::CreateOutgoingBidirectionalStream() {
      81           0 :   IS_ENVOY_BUG("Unexpected disallowed server initiated stream");
      82           0 :   return nullptr;
      83           0 : }
      84             : 
      85           0 : quic::QuicSpdyStream* EnvoyQuicServerSession::CreateOutgoingUnidirectionalStream() {
      86           0 :   IS_ENVOY_BUG("Unexpected function call");
      87           0 :   return nullptr;
      88           0 : }
      89             : 
      90         232 : void EnvoyQuicServerSession::setUpRequestDecoder(EnvoyQuicServerStream& stream) {
      91         232 :   ASSERT(http_connection_callbacks_ != nullptr);
      92         232 :   Http::RequestDecoder& decoder = http_connection_callbacks_->newStream(stream);
      93         232 :   stream.setRequestDecoder(decoder);
      94         232 : }
      95             : 
      96             : void EnvoyQuicServerSession::OnConnectionClosed(const quic::QuicConnectionCloseFrame& frame,
      97         515 :                                                 quic::ConnectionCloseSource source) {
      98         515 :   quic::QuicServerSessionBase::OnConnectionClosed(frame, source);
      99         515 :   if (source == quic::ConnectionCloseSource::FROM_SELF) {
     100         503 :     setLocalCloseReason(frame.error_details);
     101         503 :   }
     102         515 :   onConnectionCloseEvent(frame, source, version());
     103         515 :   if (position_.has_value()) {
     104             :     // Remove this connection from the map.
     105           0 :     std::list<std::reference_wrapper<Network::Connection>>& connections =
     106           0 :         position_->connection_map_[&position_->filter_chain_];
     107           0 :     connections.erase(position_->iterator_);
     108           0 :     if (connections.empty()) {
     109             :       // Remove the whole entry if this is the last connection using this filter chain.
     110           0 :       position_->connection_map_.erase(&position_->filter_chain_);
     111           0 :     }
     112           0 :     position_.reset();
     113           0 :   }
     114         515 : }
     115             : 
     116         515 : void EnvoyQuicServerSession::Initialize() {
     117         515 :   quic::QuicServerSessionBase::Initialize();
     118         515 :   initialized_ = true;
     119         515 :   quic_connection_->setEnvoyConnection(*this, *this);
     120         515 : }
     121             : 
     122         515 : void EnvoyQuicServerSession::OnCanWrite() {
     123         515 :   uint64_t old_bytes_to_send = bytesToSend();
     124         515 :   quic::QuicServerSessionBase::OnCanWrite();
     125             :   // Do not update delay close timer according to connection level packet egress because that is
     126             :   // equivalent to TCP transport layer egress. But only do so if the session gets chance to write.
     127         515 :   const bool has_sent_any_data = bytesToSend() != old_bytes_to_send;
     128         515 :   maybeUpdateDelayCloseTimer(has_sent_any_data);
     129         515 : }
     130             : 
     131        1066 : bool EnvoyQuicServerSession::hasDataToWrite() { return HasDataToWrite(); }
     132             : 
     133           0 : const quic::QuicConnection* EnvoyQuicServerSession::quicConnection() const {
     134           0 :   return initialized_ ? connection() : nullptr;
     135           0 : }
     136             : 
     137           0 : quic::QuicConnection* EnvoyQuicServerSession::quicConnection() {
     138           0 :   return initialized_ ? connection() : nullptr;
     139           0 : }
     140             : 
     141           0 : void EnvoyQuicServerSession::OnTlsHandshakeComplete() {
     142           0 :   quic::QuicServerSessionBase::OnTlsHandshakeComplete();
     143           0 :   streamInfo().downstreamTiming().onDownstreamHandshakeComplete(dispatcher_.timeSource());
     144           0 :   raiseConnectionEvent(Network::ConnectionEvent::Connected);
     145           0 : }
     146             : 
     147             : void EnvoyQuicServerSession::MaybeSendRstStreamFrame(quic::QuicStreamId id,
     148             :                                                      quic::QuicResetStreamError error,
     149         232 :                                                      quic::QuicStreamOffset bytes_written) {
     150         232 :   QuicServerSessionBase::MaybeSendRstStreamFrame(id, error, bytes_written);
     151         232 :   quic_stat_names_.chargeQuicResetStreamErrorStats(listener_scope_, error, /*from_self*/ true,
     152         232 :                                                    /*is_upstream*/ false);
     153         232 : }
     154             : 
     155           7 : void EnvoyQuicServerSession::OnRstStream(const quic::QuicRstStreamFrame& frame) {
     156           7 :   QuicServerSessionBase::OnRstStream(frame);
     157           7 :   quic_stat_names_.chargeQuicResetStreamErrorStats(listener_scope_, frame.error(),
     158           7 :                                                    /*from_self*/ false, /*is_upstream*/ false);
     159           7 : }
     160             : 
     161             : void EnvoyQuicServerSession::setHttp3Options(
     162         515 :     const envoy::config::core::v3::Http3ProtocolOptions& http3_options) {
     163         515 :   QuicFilterManagerConnectionImpl::setHttp3Options(http3_options);
     164         515 :   if (http3_options_->has_quic_protocol_options() &&
     165         515 :       http3_options_->quic_protocol_options().has_connection_keepalive()) {
     166           0 :     const uint64_t initial_interval = PROTOBUF_GET_MS_OR_DEFAULT(
     167           0 :         http3_options_->quic_protocol_options().connection_keepalive(), initial_interval, 0);
     168           0 :     const uint64_t max_interval =
     169           0 :         PROTOBUF_GET_MS_OR_DEFAULT(http3_options_->quic_protocol_options().connection_keepalive(),
     170           0 :                                    max_interval, quic::kPingTimeoutSecs);
     171           0 :     if (max_interval == 0) {
     172           0 :       return;
     173           0 :     }
     174           0 :     if (initial_interval > 0) {
     175           0 :       connection()->set_keep_alive_ping_timeout(
     176           0 :           quic::QuicTime::Delta::FromMilliseconds(max_interval));
     177           0 :       connection()->set_initial_retransmittable_on_wire_timeout(
     178           0 :           quic::QuicTime::Delta::FromMilliseconds(initial_interval));
     179           0 :     }
     180           0 :   }
     181         515 :   set_allow_extended_connect(http3_options_->allow_extended_connect());
     182         515 : }
     183             : 
     184             : void EnvoyQuicServerSession::storeConnectionMapPosition(FilterChainToConnectionMap& connection_map,
     185             :                                                         const Network::FilterChain& filter_chain,
     186           0 :                                                         ConnectionMapIter position) {
     187           0 :   position_.emplace(connection_map, filter_chain, position);
     188           0 : }
     189             : 
     190         515 : quic::QuicSSLConfig EnvoyQuicServerSession::GetSSLConfig() const {
     191         515 :   quic::QuicSSLConfig config = quic::QuicServerSessionBase::GetSSLConfig();
     192         515 :   config.early_data_enabled = position_.has_value()
     193         515 :                                   ? dynamic_cast<const QuicServerTransportSocketFactory&>(
     194           0 :                                         position_->filter_chain_.transportSocketFactory())
     195           0 :                                         .earlyDataEnabled()
     196         515 :                                   : true;
     197         515 :   return config;
     198         515 : }
     199             : 
     200             : void EnvoyQuicServerSession::ProcessUdpPacket(const quic::QuicSocketAddress& self_address,
     201             :                                               const quic::QuicSocketAddress& peer_address,
     202        1066 :                                               const quic::QuicReceivedPacket& packet) {
     203             :   // If L4 filters causes the connection to be closed early during initialization, now
     204             :   // is the time to actually close the connection.
     205        1066 :   maybeHandleCloseDuringInitialize();
     206        1066 :   quic::QuicServerSessionBase::ProcessUdpPacket(self_address, peer_address, packet);
     207        1066 :   if (connection()->sent_server_preferred_address().IsInitialized() &&
     208        1066 :       self_address == connection()->sent_server_preferred_address()) {
     209           0 :     connection_stats_.num_packets_rx_on_preferred_address_.inc();
     210           0 :   }
     211        1066 :   maybeApplyDelayedClose();
     212        1066 : }
     213             : 
     214             : std::vector<absl::string_view>::const_iterator
     215           0 : EnvoyQuicServerSession::SelectAlpn(const std::vector<absl::string_view>& alpns) const {
     216           0 :   if (!position_.has_value()) {
     217           0 :     return quic::QuicServerSessionBase::SelectAlpn(alpns);
     218           0 :   }
     219           0 :   const std::vector<absl::string_view>& configured_alpns =
     220           0 :       dynamic_cast<const QuicServerTransportSocketFactory&>(
     221           0 :           position_->filter_chain_.transportSocketFactory())
     222           0 :           .supportedAlpnProtocols();
     223           0 :   if (configured_alpns.empty()) {
     224           0 :     return quic::QuicServerSessionBase::SelectAlpn(alpns);
     225           0 :   }
     226             : 
     227           0 :   for (absl::string_view configured_alpn : configured_alpns) {
     228           0 :     auto it = absl::c_find(alpns, configured_alpn);
     229           0 :     if (it != alpns.end()) {
     230           0 :       return it;
     231           0 :     }
     232           0 :   }
     233           0 :   return alpns.end();
     234           0 : }
     235             : 
     236             : } // namespace Quic
     237             : } // namespace Envoy

Generated by: LCOV version 1.15