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_sending_bandwidth_estimate_when_network_idle_ =
90 GetQuicRestartFlag(
91 quic_enable_sending_bandwidth_estimate_when_network_idle_v2) &&
92 version().HasIetfQuicFrames() &&
93 ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWID);
94
95 // Enable bandwidth resumption if peer sent correct connection options.
96 const bool last_bandwidth_resumption =
97 ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWRE);
98 const bool max_bandwidth_resumption =
99 ContainsQuicTag(config()->ReceivedConnectionOptions(), kBWMX);
100 bandwidth_resumption_enabled_ =
101 last_bandwidth_resumption || max_bandwidth_resumption;
102
103 // If the client has provided a bandwidth estimate from the same serving
104 // region as this server, then decide whether to use the data for bandwidth
105 // resumption.
106 if (cached_network_params != nullptr &&
107 cached_network_params->serving_region() == serving_region_) {
108 if (!version().UsesTls()) {
109 // Log the received connection parameters, regardless of how they
110 // get used for bandwidth resumption.
111 connection()->OnReceiveConnectionState(*cached_network_params);
112 }
113
114 if (bandwidth_resumption_enabled_) {
115 // Only do bandwidth resumption if estimate is recent enough.
116 const uint64_t seconds_since_estimate =
117 connection()->clock()->WallNow().ToUNIXSeconds() -
118 cached_network_params->timestamp();
119 if (seconds_since_estimate <= kNumSecondsPerHour) {
120 connection()->ResumeConnectionState(*cached_network_params,
121 max_bandwidth_resumption);
122 }
123 }
124 }
125 }
126
OnConnectionClosed(const QuicConnectionCloseFrame & frame,ConnectionCloseSource source)127 void QuicServerSessionBase::OnConnectionClosed(
128 const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
129 QuicSession::OnConnectionClosed(frame, source);
130 // In the unlikely event we get a connection close while doing an asynchronous
131 // crypto event, make sure we cancel the callback.
132 if (crypto_stream_ != nullptr) {
133 crypto_stream_->CancelOutstandingCallbacks();
134 }
135 }
136
OnBandwidthUpdateTimeout()137 void QuicServerSessionBase::OnBandwidthUpdateTimeout() {
138 if (!enable_sending_bandwidth_estimate_when_network_idle_) {
139 return;
140 }
141 QUIC_DVLOG(1) << "Bandwidth update timed out.";
142 const SendAlgorithmInterface* send_algorithm =
143 connection()->sent_packet_manager().GetSendAlgorithm();
144 if (send_algorithm != nullptr &&
145 send_algorithm->HasGoodBandwidthEstimateForResumption()) {
146 const bool success = MaybeSendAddressToken();
147 QUIC_BUG_IF(QUIC_BUG_25522, !success) << "Failed to send address token.";
148 QUIC_RESTART_FLAG_COUNT_N(
149 quic_enable_sending_bandwidth_estimate_when_network_idle_v2, 2, 3);
150 }
151 }
152
OnCongestionWindowChange(QuicTime now)153 void QuicServerSessionBase::OnCongestionWindowChange(QuicTime now) {
154 // Sending bandwidth is no longer conditioned on if session does bandwidth
155 // resumption.
156 if (GetQuicRestartFlag(
157 quic_enable_sending_bandwidth_estimate_when_network_idle_v2)) {
158 QUIC_RESTART_FLAG_COUNT_N(
159 quic_enable_sending_bandwidth_estimate_when_network_idle_v2, 3, 3);
160 return;
161 }
162 if (!bandwidth_resumption_enabled_) {
163 return;
164 }
165 // Only send updates when the application has no data to write.
166 if (HasDataToWrite()) {
167 return;
168 }
169
170 // If not enough time has passed since the last time we sent an update to the
171 // client, or not enough packets have been sent, then return early.
172 const QuicSentPacketManager& sent_packet_manager =
173 connection()->sent_packet_manager();
174 int64_t srtt_ms =
175 sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds();
176 int64_t now_ms = (now - last_scup_time_).ToMilliseconds();
177 int64_t packets_since_last_scup = 0;
178 const QuicPacketNumber largest_sent_packet =
179 connection()->sent_packet_manager().GetLargestSentPacket();
180 if (largest_sent_packet.IsInitialized()) {
181 packets_since_last_scup =
182 last_scup_packet_number_.IsInitialized()
183 ? largest_sent_packet - last_scup_packet_number_
184 : largest_sent_packet.ToUint64();
185 }
186 if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) ||
187 now_ms < kMinIntervalBetweenServerConfigUpdatesMs ||
188 packets_since_last_scup < kMinPacketsBetweenServerConfigUpdates) {
189 return;
190 }
191
192 // If the bandwidth recorder does not have a valid estimate, return early.
193 const QuicSustainedBandwidthRecorder* bandwidth_recorder =
194 sent_packet_manager.SustainedBandwidthRecorder();
195 if (bandwidth_recorder == nullptr || !bandwidth_recorder->HasEstimate()) {
196 return;
197 }
198
199 // The bandwidth recorder has recorded at least one sustained bandwidth
200 // estimate. Check that it's substantially different from the last one that
201 // we sent to the client, and if so, send the new one.
202 QuicBandwidth new_bandwidth_estimate =
203 bandwidth_recorder->BandwidthEstimate();
204
205 int64_t bandwidth_delta =
206 std::abs(new_bandwidth_estimate.ToBitsPerSecond() -
207 bandwidth_estimate_sent_to_client_.ToBitsPerSecond());
208
209 // Define "substantial" difference as a 50% increase or decrease from the
210 // last estimate.
211 bool substantial_difference =
212 bandwidth_delta >
213 0.5 * bandwidth_estimate_sent_to_client_.ToBitsPerSecond();
214 if (!substantial_difference) {
215 return;
216 }
217
218 if (version().UsesTls()) {
219 if (version().HasIetfQuicFrames() && MaybeSendAddressToken()) {
220 bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
221 }
222 } else {
223 absl::optional<CachedNetworkParameters> cached_network_params =
224 GenerateCachedNetworkParameters();
225
226 if (cached_network_params.has_value()) {
227 bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
228 QUIC_DVLOG(1) << "Server: sending new bandwidth estimate (KBytes/s): "
229 << bandwidth_estimate_sent_to_client_.ToKBytesPerSecond();
230
231 QUICHE_DCHECK_EQ(
232 BandwidthToCachedParameterBytesPerSecond(
233 bandwidth_estimate_sent_to_client_),
234 cached_network_params->bandwidth_estimate_bytes_per_second());
235
236 crypto_stream_->SendServerConfigUpdate(&cached_network_params.value());
237
238 connection()->OnSendConnectionState(*cached_network_params);
239 }
240 }
241
242 last_scup_time_ = now;
243 last_scup_packet_number_ =
244 connection()->sent_packet_manager().GetLargestSentPacket();
245 }
246
ShouldCreateIncomingStream(QuicStreamId id)247 bool QuicServerSessionBase::ShouldCreateIncomingStream(QuicStreamId id) {
248 if (!connection()->connected()) {
249 QUIC_BUG(quic_bug_10393_2)
250 << "ShouldCreateIncomingStream called when disconnected";
251 return false;
252 }
253
254 if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
255 QUIC_BUG(quic_bug_10393_3)
256 << "ShouldCreateIncomingStream called with server initiated "
257 "stream ID.";
258 return false;
259 }
260
261 if (QuicUtils::IsServerInitiatedStreamId(transport_version(), id)) {
262 QUIC_DLOG(INFO) << "Invalid incoming even stream_id:" << id;
263 connection()->CloseConnection(
264 QUIC_INVALID_STREAM_ID, "Client created even numbered stream",
265 ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
266 return false;
267 }
268 return true;
269 }
270
ShouldCreateOutgoingBidirectionalStream()271 bool QuicServerSessionBase::ShouldCreateOutgoingBidirectionalStream() {
272 if (!connection()->connected()) {
273 QUIC_BUG(quic_bug_12513_2)
274 << "ShouldCreateOutgoingBidirectionalStream called when disconnected";
275 return false;
276 }
277 if (!crypto_stream_->encryption_established()) {
278 QUIC_BUG(quic_bug_10393_4)
279 << "Encryption not established so no outgoing stream created.";
280 return false;
281 }
282
283 return CanOpenNextOutgoingBidirectionalStream();
284 }
285
ShouldCreateOutgoingUnidirectionalStream()286 bool QuicServerSessionBase::ShouldCreateOutgoingUnidirectionalStream() {
287 if (!connection()->connected()) {
288 QUIC_BUG(quic_bug_12513_3)
289 << "ShouldCreateOutgoingUnidirectionalStream called when disconnected";
290 return false;
291 }
292 if (!crypto_stream_->encryption_established()) {
293 QUIC_BUG(quic_bug_10393_5)
294 << "Encryption not established so no outgoing stream created.";
295 return false;
296 }
297
298 return CanOpenNextOutgoingUnidirectionalStream();
299 }
300
GetMutableCryptoStream()301 QuicCryptoServerStreamBase* QuicServerSessionBase::GetMutableCryptoStream() {
302 return crypto_stream_.get();
303 }
304
GetCryptoStream() const305 const QuicCryptoServerStreamBase* QuicServerSessionBase::GetCryptoStream()
306 const {
307 return crypto_stream_.get();
308 }
309
BandwidthToCachedParameterBytesPerSecond(const QuicBandwidth & bandwidth) const310 int32_t QuicServerSessionBase::BandwidthToCachedParameterBytesPerSecond(
311 const QuicBandwidth& bandwidth) const {
312 return static_cast<int32_t>(std::min<int64_t>(
313 bandwidth.ToBytesPerSecond(), std::numeric_limits<int32_t>::max()));
314 }
315
SendSettingsToCryptoStream()316 void QuicServerSessionBase::SendSettingsToCryptoStream() {
317 if (!version().UsesTls()) {
318 return;
319 }
320 std::string settings_frame = HttpEncoder::SerializeSettingsFrame(settings());
321
322 std::unique_ptr<ApplicationState> serialized_settings =
323 std::make_unique<ApplicationState>(
324 settings_frame.data(),
325 settings_frame.data() + settings_frame.length());
326 GetMutableCryptoStream()->SetServerApplicationStateForResumption(
327 std::move(serialized_settings));
328 }
329
GetSSLConfig() const330 QuicSSLConfig QuicServerSessionBase::GetSSLConfig() const {
331 QUICHE_DCHECK(crypto_config_ && crypto_config_->proof_source());
332
333 QuicSSLConfig ssl_config = QuicSpdySession::GetSSLConfig();
334
335 ssl_config.disable_ticket_support =
336 GetQuicFlag(quic_disable_server_tls_resumption);
337
338 if (!crypto_config_ || !crypto_config_->proof_source()) {
339 return ssl_config;
340 }
341
342 absl::InlinedVector<uint16_t, 8> signature_algorithms =
343 crypto_config_->proof_source()->SupportedTlsSignatureAlgorithms();
344 if (!signature_algorithms.empty()) {
345 ssl_config.signing_algorithm_prefs = std::move(signature_algorithms);
346 }
347
348 return ssl_config;
349 }
350
351 absl::optional<CachedNetworkParameters>
GenerateCachedNetworkParameters() const352 QuicServerSessionBase::GenerateCachedNetworkParameters() const {
353 const QuicSentPacketManager& sent_packet_manager =
354 connection()->sent_packet_manager();
355 const QuicSustainedBandwidthRecorder* bandwidth_recorder =
356 sent_packet_manager.SustainedBandwidthRecorder();
357
358 CachedNetworkParameters cached_network_params;
359 cached_network_params.set_timestamp(
360 connection()->clock()->WallNow().ToUNIXSeconds());
361
362 if (!sent_packet_manager.GetRttStats()->min_rtt().IsZero()) {
363 cached_network_params.set_min_rtt_ms(
364 sent_packet_manager.GetRttStats()->min_rtt().ToMilliseconds());
365 }
366
367 if (enable_sending_bandwidth_estimate_when_network_idle_) {
368 const SendAlgorithmInterface* send_algorithm =
369 sent_packet_manager.GetSendAlgorithm();
370 if (send_algorithm != nullptr &&
371 send_algorithm->HasGoodBandwidthEstimateForResumption()) {
372 cached_network_params.set_bandwidth_estimate_bytes_per_second(
373 BandwidthToCachedParameterBytesPerSecond(
374 send_algorithm->BandwidthEstimate()));
375 QUIC_CODE_COUNT(quic_send_measured_bandwidth_in_token);
376 } else {
377 const quic::CachedNetworkParameters* previous_cached_network_params =
378 crypto_stream()->PreviousCachedNetworkParams();
379 if (previous_cached_network_params != nullptr &&
380 previous_cached_network_params
381 ->bandwidth_estimate_bytes_per_second() > 0) {
382 cached_network_params.set_bandwidth_estimate_bytes_per_second(
383 previous_cached_network_params
384 ->bandwidth_estimate_bytes_per_second());
385 QUIC_CODE_COUNT(quic_send_previous_bandwidth_in_token);
386 } else {
387 QUIC_CODE_COUNT(quic_not_send_bandwidth_in_token);
388 }
389 }
390 } else {
391 // Populate bandwidth estimates if any.
392 if (bandwidth_recorder != nullptr && bandwidth_recorder->HasEstimate()) {
393 const int32_t bw_estimate_bytes_per_second =
394 BandwidthToCachedParameterBytesPerSecond(
395 bandwidth_recorder->BandwidthEstimate());
396 const int32_t max_bw_estimate_bytes_per_second =
397 BandwidthToCachedParameterBytesPerSecond(
398 bandwidth_recorder->MaxBandwidthEstimate());
399 QUIC_BUG_IF(quic_bug_12513_1, max_bw_estimate_bytes_per_second < 0)
400 << max_bw_estimate_bytes_per_second;
401 QUIC_BUG_IF(quic_bug_10393_1, bw_estimate_bytes_per_second < 0)
402 << bw_estimate_bytes_per_second;
403
404 cached_network_params.set_bandwidth_estimate_bytes_per_second(
405 bw_estimate_bytes_per_second);
406 cached_network_params.set_max_bandwidth_estimate_bytes_per_second(
407 max_bw_estimate_bytes_per_second);
408 cached_network_params.set_max_bandwidth_timestamp_seconds(
409 bandwidth_recorder->MaxBandwidthTimestamp());
410
411 cached_network_params.set_previous_connection_state(
412 bandwidth_recorder->EstimateRecordedDuringSlowStart()
413 ? CachedNetworkParameters::SLOW_START
414 : CachedNetworkParameters::CONGESTION_AVOIDANCE);
415 }
416 }
417
418 if (!serving_region_.empty()) {
419 cached_network_params.set_serving_region(serving_region_);
420 }
421
422 return cached_network_params;
423 }
424
425 } // namespace quic
426