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