xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/http/quic_server_session_base.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/http/quic_server_session_base.h"
6 
7 #include <string>
8 
9 #include "quiche/quic/core/proto/cached_network_parameters_proto.h"
10 #include "quiche/quic/core/quic_connection.h"
11 #include "quiche/quic/core/quic_stream.h"
12 #include "quiche/quic/core/quic_tag.h"
13 #include "quiche/quic/core/quic_time.h"
14 #include "quiche/quic/core/quic_types.h"
15 #include "quiche/quic/core/quic_utils.h"
16 #include "quiche/quic/platform/api/quic_bug_tracker.h"
17 #include "quiche/quic/platform/api/quic_flag_utils.h"
18 #include "quiche/quic/platform/api/quic_flags.h"
19 #include "quiche/quic/platform/api/quic_logging.h"
20 #include "quiche/common/platform/api/quiche_logging.h"
21 
22 namespace quic {
23 
QuicServerSessionBase(const QuicConfig & config,const ParsedQuicVersionVector & supported_versions,QuicConnection * connection,Visitor * visitor,QuicCryptoServerStreamBase::Helper * helper,const QuicCryptoServerConfig * crypto_config,QuicCompressedCertsCache * compressed_certs_cache)24 QuicServerSessionBase::QuicServerSessionBase(
25     const QuicConfig& config, const ParsedQuicVersionVector& supported_versions,
26     QuicConnection* connection, Visitor* visitor,
27     QuicCryptoServerStreamBase::Helper* helper,
28     const QuicCryptoServerConfig* crypto_config,
29     QuicCompressedCertsCache* compressed_certs_cache)
30     : QuicSpdySession(connection, visitor, config, supported_versions),
31       crypto_config_(crypto_config),
32       compressed_certs_cache_(compressed_certs_cache),
33       helper_(helper),
34       bandwidth_resumption_enabled_(false),
35       bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()),
36       last_scup_time_(QuicTime::Zero()) {}
37 
~QuicServerSessionBase()38 QuicServerSessionBase::~QuicServerSessionBase() {}
39 
Initialize()40 void QuicServerSessionBase::Initialize() {
41   crypto_stream_ =
42       CreateQuicCryptoServerStream(crypto_config_, compressed_certs_cache_);
43   QuicSpdySession::Initialize();
44   SendSettingsToCryptoStream();
45 }
46 
OnConfigNegotiated()47 void QuicServerSessionBase::OnConfigNegotiated() {
48   QuicSpdySession::OnConfigNegotiated();
49 
50   const CachedNetworkParameters* cached_network_params =
51       crypto_stream_->PreviousCachedNetworkParams();
52 
53   // Set the initial rtt from cached_network_params.min_rtt_ms, which comes from
54   // a validated address token. This will override the initial rtt that may have
55   // been set by the transport parameters.
56   if (version().UsesTls() && cached_network_params != nullptr) {
57     if (cached_network_params->serving_region() == serving_region_) {
58       QUIC_CODE_COUNT(quic_server_received_network_params_at_same_region);
59       if (config()->HasReceivedConnectionOptions() &&
60           ContainsQuicTag(config()->ReceivedConnectionOptions(), kTRTT)) {
61         QUIC_DLOG(INFO)
62             << "Server: Setting initial rtt to "
63             << cached_network_params->min_rtt_ms()
64             << "ms which is received from a validated address token";
65         connection()->sent_packet_manager().SetInitialRtt(
66             QuicTime::Delta::FromMilliseconds(
67                 cached_network_params->min_rtt_ms()),
68             /*trusted=*/true);
69       }
70     } else {
71       QUIC_CODE_COUNT(quic_server_received_network_params_at_different_region);
72     }
73   }
74 
75   if (!config()->HasReceivedConnectionOptions()) {
76     return;
77   }
78 
79   if (GetQuicReloadableFlag(quic_enable_disable_resumption) &&
80       version().UsesTls() &&
81       ContainsQuicTag(config()->ReceivedConnectionOptions(), kNRES) &&
82       crypto_stream_->ResumptionAttempted()) {
83     QUIC_RELOADABLE_FLAG_COUNT(quic_enable_disable_resumption);
84     const bool disabled = crypto_stream_->DisableResumption();
85     QUIC_BUG_IF(quic_failed_to_disable_resumption, !disabled)
86         << "Failed to disable resumption";
87   }
88 
89   // Enable bandwidth resumption if peer sent correct connection options.
90   const bool last_bandwidth_resumption =
91       ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE);
92   const bool max_bandwidth_resumption =
93       ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWMX);
94   bandwidth_resumption_enabled_ =
95       last_bandwidth_resumption || max_bandwidth_resumption;
96 
97   // If the client has provided a bandwidth estimate from the same serving
98   // region as this server, then decide whether to use the data for bandwidth
99   // resumption.
100   if (cached_network_params != nullptr &&
101       cached_network_params->serving_region() == serving_region_) {
102     if (!version().UsesTls()) {
103       // Log the received connection parameters, regardless of how they
104       // get used for bandwidth resumption.
105       connection()->OnReceiveConnectionState(*cached_network_params);
106     }
107 
108     if (bandwidth_resumption_enabled_) {
109       // Only do bandwidth resumption if estimate is recent enough.
110       const uint64_t seconds_since_estimate =
111           connection()->clock()->WallNow().ToUNIXSeconds() -
112           cached_network_params->timestamp();
113       if (seconds_since_estimate <= kNumSecondsPerHour) {
114         connection()->ResumeConnectionState(*cached_network_params,
115                                             max_bandwidth_resumption);
116       }
117     }
118   }
119 }
120 
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)121 void QuicServerSessionBase::OnConnectionClosed(
122     const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
123   QuicSession::OnConnectionClosed(frame, source);
124   // In the unlikely event we get a connection close while doing an asynchronous
125   // crypto event, make sure we cancel the callback.
126   if (crypto_stream_ != nullptr) {
127     crypto_stream_->CancelOutstandingCallbacks();
128   }
129 }
130 
OnCongestionWindowChange(QuicTime now)131 void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
132   if (!bandwidth_resumption_enabled_) {
133     return;
134   }
135   // Only send updates when the application has no data to write.
136   if (HasDataToWrite()) {
137     return;
138   }
139 
140   // If not enough time has passed since the last time we sent an update to the
141   // client, or not enough packets have been sent, then return early.
142   const QuicSentPacketManager& sent_packet_manager =
143       connection()->sent_packet_manager();
144   int64_t srtt_ms =
145       sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds();
146   int64_t now_ms = (now - last_scup_time_).ToMilliseconds();
147   int64_t packets_since_last_scup = 0;
148   const QuicPacketNumber largest_sent_packet =
149       connection()->sent_packet_manager().GetLargestSentPacket();
150   if (largest_sent_packet.IsInitialized()) {
151     packets_since_last_scup =
152         last_scup_packet_number_.IsInitialized()
153             ? largest_sent_packet - last_scup_packet_number_
154             : largest_sent_packet.ToUint64();
155   }
156   if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) ||
157       now_ms < kMinIntervalBetweenServerConfigUpdatesMs ||
158       packets_since_last_scup < kMinPacketsBetweenServerConfigUpdates) {
159     return;
160   }
161 
162   // If the bandwidth recorder does not have a valid estimate, return early.
163   const QuicSustainedBandwidthRecorder* bandwidth_recorder =
164       sent_packet_manager.SustainedBandwidthRecorder();
165   if (bandwidth_recorder == nullptr || !bandwidth_recorder->HasEstimate()) {
166     return;
167   }
168 
169   // The bandwidth recorder has recorded at least one sustained bandwidth
170   // estimate. Check that it's substantially different from the last one that
171   // we sent to the client, and if so, send the new one.
172   QuicBandwidth new_bandwidth_estimate =
173       bandwidth_recorder->BandwidthEstimate();
174 
175   int64_t bandwidth_delta =
176       std::abs(new_bandwidth_estimate.ToBitsPerSecond() -
177                bandwidth_estimate_sent_to_client_.ToBitsPerSecond());
178 
179   // Define "substantial" difference as a 50% increase or decrease from the
180   // last estimate.
181   bool substantial_difference =
182       bandwidth_delta >
183       0.5 * bandwidth_estimate_sent_to_client_.ToBitsPerSecond();
184   if (!substantial_difference) {
185     return;
186   }
187 
188   if (version().UsesTls()) {
189     if (version().HasIetfQuicFrames() && MaybeSendAddressToken()) {
190       bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
191     }
192   } else {
193     std::optional<CachedNetworkParameters> cached_network_params =
194         GenerateCachedNetworkParameters();
195 
196     if (cached_network_params.has_value()) {
197       bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
198       QUIC_DVLOG(1) << "Server: sending new bandwidth estimate (KBytes/s): "
199                     << bandwidth_estimate_sent_to_client_.ToKBytesPerSecond();
200 
201       QUICHE_DCHECK_EQ(
202           BandwidthToCachedParameterBytesPerSecond(
203               bandwidth_estimate_sent_to_client_),
204           cached_network_params->bandwidth_estimate_bytes_per_second());
205 
206       crypto_stream_->SendServerConfigUpdate(&*cached_network_params);
207 
208       connection()->OnSendConnectionState(*cached_network_params);
209     }
210   }
211 
212   last_scup_time_ = now;
213   last_scup_packet_number_ =
214       connection()->sent_packet_manager().GetLargestSentPacket();
215 }
216 
ShouldCreateIncomingStream(QuicStreamId id)217 bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) {
218   if (!connection()->connected()) {
219     QUIC_BUG(quic_bug_10393_2)
220         << "ShouldCreateIncomingStream called when disconnected";
221     return false;
222   }
223 
224   if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
225     QUIC_BUG(quic_bug_10393_3)
226         << "ShouldCreateIncomingStream called with server initiated "
227            "stream ID.";
228     return false;
229   }
230 
231   return true;
232 }
233 
ShouldCreateOutgoingBidirectionalStream()234 bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
235   if (!connection()->connected()) {
236     QUIC_BUG(quic_bug_12513_2)
237         << "ShouldCreateOutgoingBidirectionalStream called when disconnected";
238     return false;
239   }
240   if (!crypto_stream_->encryption_established()) {
241     QUIC_BUG(quic_bug_10393_4)
242         << "Encryption not established so no outgoing stream created.";
243     return false;
244   }
245 
246   return CanOpenNextOutgoingBidirectionalStream();
247 }
248 
ShouldCreateOutgoingUnidirectionalStream()249 bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() {
250   if (!connection()->connected()) {
251     QUIC_BUG(quic_bug_12513_3)
252         << "ShouldCreateOutgoingUnidirectionalStream called when disconnected";
253     return false;
254   }
255   if (!crypto_stream_->encryption_established()) {
256     QUIC_BUG(quic_bug_10393_5)
257         << "Encryption not established so no outgoing stream created.";
258     return false;
259   }
260 
261   return CanOpenNextOutgoingUnidirectionalStream();
262 }
263 
GetMutableCryptoStream()264 QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() {
265   return crypto_stream_.get();
266 }
267 
GetCryptoStream() const268 const QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream()
269     const {
270   return crypto_stream_.get();
271 }
272 
BandwidthToCachedParameterBytesPerSecond(const QuicBandwidth & bandwidth) const273 int32_t QuicServerSessionBase::BandwidthToCachedParameterBytesPerSecond(
274     const QuicBandwidth& bandwidth) const {
275   return static_cast<int32_t>(std::min<int64_t>(
276       bandwidth.ToBytesPerSecond(), std::numeric_limits<int32_t>::max()));
277 }
278 
SendSettingsToCryptoStream()279 void QuicServerSessionBase::SendSettingsToCryptoStream() {
280   if (!version().UsesTls()) {
281     return;
282   }
283   std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings());
284 
285   std::unique_ptr<ApplicationState> serialized_settings =
286       std::make_unique<ApplicationState>(
287           settings_frame.data(),
288           settings_frame.data() + settings_frame.length());
289   GetMutableCryptoStream()->SetServerApplicationStateForResumption(
290       std::move(serialized_settings));
291 }
292 
GetSSLConfig() const293 QuicSSLConfig QuicServerSessionBase::GetSSLConfig() const {
294   QUICHE_DCHECK(crypto_config_ && crypto_config_->proof_source());
295 
296   QuicSSLConfig ssl_config = QuicSpdySession::GetSSLConfig();
297 
298   ssl_config.disable_ticket_support =
299       GetQuicFlag(quic_disable_server_tls_resumption);
300 
301   if (!crypto_config_ || !crypto_config_->proof_source()) {
302     return ssl_config;
303   }
304 
305   absl::InlinedVector<uint16_t, 8> signature_algorithms =
306       crypto_config_->proof_source()->SupportedTlsSignatureAlgorithms();
307   if (!signature_algorithms.empty()) {
308     ssl_config.signing_algorithm_prefs = std::move(signature_algorithms);
309   }
310 
311   return ssl_config;
312 }
313 
314 std::optional<CachedNetworkParameters>
GenerateCachedNetworkParameters() const315 QuicServerSessionBase::GenerateCachedNetworkParameters() const {
316   const QuicSentPacketManager& sent_packet_manager =
317       connection()->sent_packet_manager();
318   const QuicSustainedBandwidthRecorder* bandwidth_recorder =
319       sent_packet_manager.SustainedBandwidthRecorder();
320 
321   CachedNetworkParameters cached_network_params;
322   cached_network_params.set_timestamp(
323       connection()->clock()->WallNow().ToUNIXSeconds());
324 
325   if (!sent_packet_manager.GetRttStats()->min_rtt().IsZero()) {
326     cached_network_params.set_min_rtt_ms(
327         sent_packet_manager.GetRttStats()->min_rtt().ToMilliseconds());
328   }
329 
330   // Populate bandwidth estimates if any.
331   if (bandwidth_recorder != nullptr && bandwidth_recorder->HasEstimate()) {
332     const int32_t bw_estimate_bytes_per_second =
333         BandwidthToCachedParameterBytesPerSecond(
334             bandwidth_recorder->BandwidthEstimate());
335     const int32_t max_bw_estimate_bytes_per_second =
336         BandwidthToCachedParameterBytesPerSecond(
337             bandwidth_recorder->MaxBandwidthEstimate());
338     QUIC_BUG_IF(quic_bug_12513_1, max_bw_estimate_bytes_per_second < 0)
339         << max_bw_estimate_bytes_per_second;
340     QUIC_BUG_IF(quic_bug_10393_1, bw_estimate_bytes_per_second < 0)
341         << bw_estimate_bytes_per_second;
342 
343     cached_network_params.set_bandwidth_estimate_bytes_per_second(
344         bw_estimate_bytes_per_second);
345     cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
346         max_bw_estimate_bytes_per_second);
347     cached_network_params.set_max_bandwidth_timestamp_seconds(
348         bandwidth_recorder->MaxBandwidthTimestamp());
349 
350     cached_network_params.set_previous_connection_state(
351         bandwidth_recorder->EstimateRecordedDuringSlowStart()
352             ? CachedNetworkParameters::SLOW_START
353             : CachedNetworkParameters::CONGESTION_AVOIDANCE);
354   }
355 
356   if (!serving_region_.empty()) {
357     cached_network_params.set_serving_region(serving_region_);
358   }
359 
360   return cached_network_params;
361 }
362 
363 }  // namespace quic
364