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
|