blob: 661b5f3f1b3a276bb2c1ba9efea1d2775da13e50 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2013 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 "net/third_party/quiche/src/quic/core/quic_config.h"
6
7#include <algorithm>
dschinazi52127d72019-04-17 15:12:38 -07008#include <cstring>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010
11#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
12#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
dschinazi52127d72019-04-17 15:12:38 -070013#include "net/third_party/quiche/src/quic/core/quic_constants.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
15#include "net/third_party/quiche/src/quic/core/quic_utils.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
dschinazi52127d72019-04-17 15:12:38 -070022#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
dschinazi52127d72019-04-17 15:12:38 -070024#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050025
26namespace quic {
27
28// Reads the value corresponding to |name_| from |msg| into |out|. If the
29// |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
30// to |default_value|.
31QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
32 QuicTag tag,
33 QuicConfigPresence presence,
34 uint32_t default_value,
35 uint32_t* out,
vasilvvc48c8712019-03-11 13:38:16 -070036 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050037 DCHECK(error_details != nullptr);
38 QuicErrorCode error = msg.GetUint32(tag, out);
39 switch (error) {
40 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
41 if (presence == PRESENCE_REQUIRED) {
42 *error_details = "Missing " + QuicTagToString(tag);
43 break;
44 }
45 error = QUIC_NO_ERROR;
46 *out = default_value;
47 break;
48 case QUIC_NO_ERROR:
49 break;
50 default:
51 *error_details = "Bad " + QuicTagToString(tag);
52 break;
53 }
54 return error;
55}
56
57QuicConfigValue::QuicConfigValue(QuicTag tag, QuicConfigPresence presence)
58 : tag_(tag), presence_(presence) {}
59QuicConfigValue::~QuicConfigValue() {}
60
61QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
62 QuicConfigPresence presence)
63 : QuicConfigValue(tag, presence), negotiated_(false) {}
64QuicNegotiableValue::~QuicNegotiableValue() {}
65
66QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
67 QuicConfigPresence presence)
68 : QuicNegotiableValue(tag, presence),
69 max_value_(0),
70 default_value_(0),
71 negotiated_value_(0) {}
72QuicNegotiableUint32::~QuicNegotiableUint32() {}
73
74void QuicNegotiableUint32::set(uint32_t max, uint32_t default_value) {
75 DCHECK_LE(default_value, max);
76 max_value_ = max;
77 default_value_ = default_value;
78}
79
80uint32_t QuicNegotiableUint32::GetUint32() const {
81 if (negotiated()) {
82 return negotiated_value_;
83 }
84 return default_value_;
85}
86
87// Returns the maximum value negotiable.
88uint32_t QuicNegotiableUint32::GetMax() const {
89 return max_value_;
90}
91
92void QuicNegotiableUint32::ToHandshakeMessage(
93 CryptoHandshakeMessage* out) const {
94 if (negotiated()) {
95 out->SetValue(tag_, negotiated_value_);
96 } else {
97 out->SetValue(tag_, max_value_);
98 }
99}
100
101QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
102 const CryptoHandshakeMessage& peer_hello,
103 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700104 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500105 DCHECK(!negotiated());
106 DCHECK(error_details != nullptr);
107 uint32_t value;
108 QuicErrorCode error = ReadUint32(peer_hello, tag_, presence_, default_value_,
109 &value, error_details);
110 if (error != QUIC_NO_ERROR) {
111 return error;
112 }
113 return ReceiveValue(value, hello_type, error_details);
114}
115
116QuicErrorCode QuicNegotiableUint32::ReceiveValue(uint32_t value,
117 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700118 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 if (hello_type == SERVER && value > max_value_) {
120 *error_details = "Invalid value received for " + QuicTagToString(tag_);
121 return QUIC_INVALID_NEGOTIATED_VALUE;
122 }
123
124 set_negotiated(true);
125 negotiated_value_ = std::min(value, max_value_);
126 return QUIC_NO_ERROR;
127}
128
129QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
130 : QuicConfigValue(tag, presence),
131 has_send_value_(false),
132 has_receive_value_(false) {}
133QuicFixedUint32::~QuicFixedUint32() {}
134
135bool QuicFixedUint32::HasSendValue() const {
136 return has_send_value_;
137}
138
139uint32_t QuicFixedUint32::GetSendValue() const {
140 QUIC_BUG_IF(!has_send_value_)
141 << "No send value to get for tag:" << QuicTagToString(tag_);
142 return send_value_;
143}
144
145void QuicFixedUint32::SetSendValue(uint32_t value) {
146 has_send_value_ = true;
147 send_value_ = value;
148}
149
150bool QuicFixedUint32::HasReceivedValue() const {
151 return has_receive_value_;
152}
153
154uint32_t QuicFixedUint32::GetReceivedValue() const {
155 QUIC_BUG_IF(!has_receive_value_)
156 << "No receive value to get for tag:" << QuicTagToString(tag_);
157 return receive_value_;
158}
159
160void QuicFixedUint32::SetReceivedValue(uint32_t value) {
161 has_receive_value_ = true;
162 receive_value_ = value;
163}
164
165void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
166 if (has_send_value_) {
167 out->SetValue(tag_, send_value_);
168 }
169}
170
171QuicErrorCode QuicFixedUint32::ProcessPeerHello(
172 const CryptoHandshakeMessage& peer_hello,
dschinazi17d42422019-06-18 16:35:07 -0700173 HelloType /*hello_type*/,
vasilvvc48c8712019-03-11 13:38:16 -0700174 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500175 DCHECK(error_details != nullptr);
176 QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
177 switch (error) {
178 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
179 if (presence_ == PRESENCE_OPTIONAL) {
180 return QUIC_NO_ERROR;
181 }
182 *error_details = "Missing " + QuicTagToString(tag_);
183 break;
184 case QUIC_NO_ERROR:
185 has_receive_value_ = true;
186 break;
187 default:
188 *error_details = "Bad " + QuicTagToString(tag_);
189 break;
190 }
191 return error;
192}
193
194QuicFixedUint128::QuicFixedUint128(QuicTag tag, QuicConfigPresence presence)
195 : QuicConfigValue(tag, presence),
196 has_send_value_(false),
197 has_receive_value_(false) {}
198QuicFixedUint128::~QuicFixedUint128() {}
199
200bool QuicFixedUint128::HasSendValue() const {
201 return has_send_value_;
202}
203
204QuicUint128 QuicFixedUint128::GetSendValue() const {
205 QUIC_BUG_IF(!has_send_value_)
206 << "No send value to get for tag:" << QuicTagToString(tag_);
207 return send_value_;
208}
209
210void QuicFixedUint128::SetSendValue(QuicUint128 value) {
211 has_send_value_ = true;
212 send_value_ = value;
213}
214
215bool QuicFixedUint128::HasReceivedValue() const {
216 return has_receive_value_;
217}
218
219QuicUint128 QuicFixedUint128::GetReceivedValue() const {
220 QUIC_BUG_IF(!has_receive_value_)
221 << "No receive value to get for tag:" << QuicTagToString(tag_);
222 return receive_value_;
223}
224
225void QuicFixedUint128::SetReceivedValue(QuicUint128 value) {
226 has_receive_value_ = true;
227 receive_value_ = value;
228}
229
230void QuicFixedUint128::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
231 if (has_send_value_) {
232 out->SetValue(tag_, send_value_);
233 }
234}
235
236QuicErrorCode QuicFixedUint128::ProcessPeerHello(
237 const CryptoHandshakeMessage& peer_hello,
dschinazi17d42422019-06-18 16:35:07 -0700238 HelloType /*hello_type*/,
vasilvvc48c8712019-03-11 13:38:16 -0700239 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 DCHECK(error_details != nullptr);
241 QuicErrorCode error = peer_hello.GetUint128(tag_, &receive_value_);
242 switch (error) {
243 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
244 if (presence_ == PRESENCE_OPTIONAL) {
245 return QUIC_NO_ERROR;
246 }
247 *error_details = "Missing " + QuicTagToString(tag_);
248 break;
249 case QUIC_NO_ERROR:
250 has_receive_value_ = true;
251 break;
252 default:
253 *error_details = "Bad " + QuicTagToString(tag_);
254 break;
255 }
256 return error;
257}
258
259QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
260 QuicConfigPresence presence)
261 : QuicConfigValue(name, presence),
262 has_send_values_(false),
263 has_receive_values_(false) {}
264
265QuicFixedTagVector::QuicFixedTagVector(const QuicFixedTagVector& other) =
266 default;
267
268QuicFixedTagVector::~QuicFixedTagVector() {}
269
270bool QuicFixedTagVector::HasSendValues() const {
271 return has_send_values_;
272}
273
274QuicTagVector QuicFixedTagVector::GetSendValues() const {
275 QUIC_BUG_IF(!has_send_values_)
276 << "No send values to get for tag:" << QuicTagToString(tag_);
277 return send_values_;
278}
279
280void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
281 has_send_values_ = true;
282 send_values_ = values;
283}
284
285bool QuicFixedTagVector::HasReceivedValues() const {
286 return has_receive_values_;
287}
288
289QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
290 QUIC_BUG_IF(!has_receive_values_)
291 << "No receive value to get for tag:" << QuicTagToString(tag_);
292 return receive_values_;
293}
294
295void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
296 has_receive_values_ = true;
297 receive_values_ = values;
298}
299
300void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
301 if (has_send_values_) {
302 out->SetVector(tag_, send_values_);
303 }
304}
305
306QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
307 const CryptoHandshakeMessage& peer_hello,
dschinazi17d42422019-06-18 16:35:07 -0700308 HelloType /*hello_type*/,
vasilvvc48c8712019-03-11 13:38:16 -0700309 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310 DCHECK(error_details != nullptr);
311 QuicTagVector values;
312 QuicErrorCode error = peer_hello.GetTaglist(tag_, &values);
313 switch (error) {
314 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
315 if (presence_ == PRESENCE_OPTIONAL) {
316 return QUIC_NO_ERROR;
317 }
318 *error_details = "Missing " + QuicTagToString(tag_);
319 break;
320 case QUIC_NO_ERROR:
321 QUIC_DVLOG(1) << "Received Connection Option tags from receiver.";
322 has_receive_values_ = true;
323 receive_values_.insert(receive_values_.end(), values.begin(),
324 values.end());
325 break;
326 default:
327 *error_details = "Bad " + QuicTagToString(tag_);
328 break;
329 }
330 return error;
331}
332
333QuicFixedSocketAddress::QuicFixedSocketAddress(QuicTag tag,
334 QuicConfigPresence presence)
335 : QuicConfigValue(tag, presence),
336 has_send_value_(false),
337 has_receive_value_(false) {}
338
339QuicFixedSocketAddress::~QuicFixedSocketAddress() {}
340
341bool QuicFixedSocketAddress::HasSendValue() const {
342 return has_send_value_;
343}
344
345const QuicSocketAddress& QuicFixedSocketAddress::GetSendValue() const {
346 QUIC_BUG_IF(!has_send_value_)
347 << "No send value to get for tag:" << QuicTagToString(tag_);
348 return send_value_;
349}
350
351void QuicFixedSocketAddress::SetSendValue(const QuicSocketAddress& value) {
352 has_send_value_ = true;
353 send_value_ = value;
354}
355
356bool QuicFixedSocketAddress::HasReceivedValue() const {
357 return has_receive_value_;
358}
359
360const QuicSocketAddress& QuicFixedSocketAddress::GetReceivedValue() const {
361 QUIC_BUG_IF(!has_receive_value_)
362 << "No receive value to get for tag:" << QuicTagToString(tag_);
363 return receive_value_;
364}
365
366void QuicFixedSocketAddress::SetReceivedValue(const QuicSocketAddress& value) {
367 has_receive_value_ = true;
368 receive_value_ = value;
369}
370
371void QuicFixedSocketAddress::ToHandshakeMessage(
372 CryptoHandshakeMessage* out) const {
373 if (has_send_value_) {
374 QuicSocketAddressCoder address_coder(send_value_);
375 out->SetStringPiece(tag_, address_coder.Encode());
376 }
377}
378
379QuicErrorCode QuicFixedSocketAddress::ProcessPeerHello(
380 const CryptoHandshakeMessage& peer_hello,
dschinazi17d42422019-06-18 16:35:07 -0700381 HelloType /*hello_type*/,
vasilvvc48c8712019-03-11 13:38:16 -0700382 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500383 QuicStringPiece address;
384 if (!peer_hello.GetStringPiece(tag_, &address)) {
385 if (presence_ == PRESENCE_REQUIRED) {
386 *error_details = "Missing " + QuicTagToString(tag_);
387 return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
388 }
389 } else {
390 QuicSocketAddressCoder address_coder;
391 if (address_coder.Decode(address.data(), address.length())) {
392 SetReceivedValue(
393 QuicSocketAddress(address_coder.ip(), address_coder.port()));
394 }
395 }
396 return QUIC_NO_ERROR;
397}
398
399QuicConfig::QuicConfig()
400 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
401 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
402 max_undecryptable_packets_(0),
403 connection_options_(kCOPT, PRESENCE_OPTIONAL),
404 client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
405 idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
406 silent_close_(kSCLS, PRESENCE_OPTIONAL),
fkastenholzd3a1de92019-05-15 07:00:07 -0700407 max_incoming_bidirectional_streams_(kMIBS, PRESENCE_REQUIRED),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500408 bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
409 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
410 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
411 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
412 connection_migration_disabled_(kNCMR, PRESENCE_OPTIONAL),
413 alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
414 support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
fkastenholzd3a1de92019-05-15 07:00:07 -0700415 stateless_reset_token_(kSRST, PRESENCE_OPTIONAL),
fkastenholz4c7303c2019-07-29 08:17:07 -0700416 max_incoming_unidirectional_streams_(kMIUS, PRESENCE_OPTIONAL),
417 max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500418 SetDefaults();
419}
420
421QuicConfig::QuicConfig(const QuicConfig& other) = default;
422
423QuicConfig::~QuicConfig() {}
424
425bool QuicConfig::SetInitialReceivedConnectionOptions(
426 const QuicTagVector& tags) {
427 if (HasReceivedConnectionOptions()) {
428 // If we have already received connection options (via handshake or due to
429 // a previous call), don't re-initialize.
430 return false;
431 }
432 connection_options_.SetReceivedValues(tags);
433 return true;
434}
435
436void QuicConfig::SetConnectionOptionsToSend(
437 const QuicTagVector& connection_options) {
438 connection_options_.SetSendValues(connection_options);
439}
440
441bool QuicConfig::HasReceivedConnectionOptions() const {
442 return connection_options_.HasReceivedValues();
443}
444
445QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
446 return connection_options_.GetReceivedValues();
447}
448
449bool QuicConfig::HasSendConnectionOptions() const {
450 return connection_options_.HasSendValues();
451}
452
453QuicTagVector QuicConfig::SendConnectionOptions() const {
454 return connection_options_.GetSendValues();
455}
456
457bool QuicConfig::HasClientSentConnectionOption(QuicTag tag,
458 Perspective perspective) const {
459 if (perspective == Perspective::IS_SERVER) {
460 if (HasReceivedConnectionOptions() &&
461 ContainsQuicTag(ReceivedConnectionOptions(), tag)) {
462 return true;
463 }
464 } else if (HasSendConnectionOptions() &&
465 ContainsQuicTag(SendConnectionOptions(), tag)) {
466 return true;
467 }
468 return false;
469}
470
471void QuicConfig::SetClientConnectionOptions(
472 const QuicTagVector& client_connection_options) {
473 client_connection_options_.SetSendValues(client_connection_options);
474}
475
476bool QuicConfig::HasClientRequestedIndependentOption(
477 QuicTag tag,
478 Perspective perspective) const {
479 if (perspective == Perspective::IS_SERVER) {
480 return (HasReceivedConnectionOptions() &&
481 ContainsQuicTag(ReceivedConnectionOptions(), tag));
482 }
483
484 return (client_connection_options_.HasSendValues() &&
485 ContainsQuicTag(client_connection_options_.GetSendValues(), tag));
486}
487
488void QuicConfig::SetIdleNetworkTimeout(
489 QuicTime::Delta max_idle_network_timeout,
490 QuicTime::Delta default_idle_network_timeout) {
491 idle_network_timeout_seconds_.set(
492 static_cast<uint32_t>(max_idle_network_timeout.ToSeconds()),
493 static_cast<uint32_t>(default_idle_network_timeout.ToSeconds()));
494}
495
496QuicTime::Delta QuicConfig::IdleNetworkTimeout() const {
497 return QuicTime::Delta::FromSeconds(
498 idle_network_timeout_seconds_.GetUint32());
499}
500
501// TODO(ianswett) Use this for silent close on mobile, or delete.
502QUIC_UNUSED void QuicConfig::SetSilentClose(bool silent_close) {
503 silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0);
504}
505
506bool QuicConfig::SilentClose() const {
507 return silent_close_.GetUint32() > 0;
508}
509
fkastenholzd3a1de92019-05-15 07:00:07 -0700510void QuicConfig::SetMaxIncomingBidirectionalStreamsToSend(
511 uint32_t max_streams) {
512 max_incoming_bidirectional_streams_.SetSendValue(max_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500513}
514
fkastenholzd3a1de92019-05-15 07:00:07 -0700515uint32_t QuicConfig::GetMaxIncomingBidirectionalStreamsToSend() {
516 return max_incoming_bidirectional_streams_.GetSendValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500517}
518
fkastenholzd3a1de92019-05-15 07:00:07 -0700519bool QuicConfig::HasReceivedMaxIncomingBidirectionalStreams() {
520 return max_incoming_bidirectional_streams_.HasReceivedValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500521}
522
fkastenholzd3a1de92019-05-15 07:00:07 -0700523uint32_t QuicConfig::ReceivedMaxIncomingBidirectionalStreams() {
524 return max_incoming_bidirectional_streams_.GetReceivedValue();
525}
526
527void QuicConfig::SetMaxIncomingUnidirectionalStreamsToSend(
528 uint32_t max_streams) {
529 max_incoming_unidirectional_streams_.SetSendValue(max_streams);
530}
531
532uint32_t QuicConfig::GetMaxIncomingUnidirectionalStreamsToSend() {
533 return max_incoming_unidirectional_streams_.GetSendValue();
534}
535
536bool QuicConfig::HasReceivedMaxIncomingUnidirectionalStreams() {
537 return max_incoming_unidirectional_streams_.HasReceivedValue();
538}
539
540uint32_t QuicConfig::ReceivedMaxIncomingUnidirectionalStreams() {
541 return max_incoming_unidirectional_streams_.GetReceivedValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542}
543
fkastenholz4c7303c2019-07-29 08:17:07 -0700544void QuicConfig::SetMaxAckDelayToSendMs(uint32_t max_ack_delay_ms) {
545 return max_ack_delay_ms_.SetSendValue(max_ack_delay_ms);
546}
547
548uint32_t QuicConfig::GetMaxAckDelayToToSendMs() const {
549 return max_ack_delay_ms_.GetSendValue();
550}
551
552bool QuicConfig::HasReceivedMaxAckDelayMs() const {
553 return max_ack_delay_ms_.HasReceivedValue();
554}
555
556uint32_t QuicConfig::ReceivedMaxAckDelayMs() const {
557 return max_ack_delay_ms_.GetReceivedValue();
558}
559
QUICHE teama6ef0a62019-03-07 20:34:33 -0500560bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
561 return bytes_for_connection_id_.HasSendValue();
562}
563
564void QuicConfig::SetBytesForConnectionIdToSend(uint32_t bytes) {
565 bytes_for_connection_id_.SetSendValue(bytes);
566}
567
568bool QuicConfig::HasReceivedBytesForConnectionId() const {
569 return bytes_for_connection_id_.HasReceivedValue();
570}
571
572uint32_t QuicConfig::ReceivedBytesForConnectionId() const {
573 return bytes_for_connection_id_.GetReceivedValue();
574}
575
576void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32_t rtt) {
577 initial_round_trip_time_us_.SetSendValue(rtt);
578}
579
580bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
581 return initial_round_trip_time_us_.HasReceivedValue();
582}
583
584uint32_t QuicConfig::ReceivedInitialRoundTripTimeUs() const {
585 return initial_round_trip_time_us_.GetReceivedValue();
586}
587
588bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
589 return initial_round_trip_time_us_.HasSendValue();
590}
591
592uint32_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
593 return initial_round_trip_time_us_.GetSendValue();
594}
595
596void QuicConfig::SetInitialStreamFlowControlWindowToSend(
597 uint32_t window_bytes) {
598 if (window_bytes < kMinimumFlowControlSendWindow) {
599 QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
dschinazic7036122019-04-30 12:46:34 -0700600 << ") cannot be set lower than minimum ("
QUICHE teama6ef0a62019-03-07 20:34:33 -0500601 << kMinimumFlowControlSendWindow << ").";
602 window_bytes = kMinimumFlowControlSendWindow;
603 }
604 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
605}
606
607uint32_t QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
608 return initial_stream_flow_control_window_bytes_.GetSendValue();
609}
610
611bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
612 return initial_stream_flow_control_window_bytes_.HasReceivedValue();
613}
614
615uint32_t QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
616 return initial_stream_flow_control_window_bytes_.GetReceivedValue();
617}
618
619void QuicConfig::SetInitialSessionFlowControlWindowToSend(
620 uint32_t window_bytes) {
621 if (window_bytes < kMinimumFlowControlSendWindow) {
622 QUIC_BUG << "Initial session flow control receive window (" << window_bytes
623 << ") cannot be set lower than default ("
624 << kMinimumFlowControlSendWindow << ").";
625 window_bytes = kMinimumFlowControlSendWindow;
626 }
627 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
628}
629
630uint32_t QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
631 return initial_session_flow_control_window_bytes_.GetSendValue();
632}
633
634bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
635 return initial_session_flow_control_window_bytes_.HasReceivedValue();
636}
637
638uint32_t QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
639 return initial_session_flow_control_window_bytes_.GetReceivedValue();
640}
641
642void QuicConfig::SetDisableConnectionMigration() {
643 connection_migration_disabled_.SetSendValue(1);
644}
645
646bool QuicConfig::DisableConnectionMigration() const {
647 return connection_migration_disabled_.HasReceivedValue();
648}
649
650void QuicConfig::SetAlternateServerAddressToSend(
651 const QuicSocketAddress& alternate_server_address) {
652 alternate_server_address_.SetSendValue(alternate_server_address);
653}
654
655bool QuicConfig::HasReceivedAlternateServerAddress() const {
656 return alternate_server_address_.HasReceivedValue();
657}
658
659const QuicSocketAddress& QuicConfig::ReceivedAlternateServerAddress() const {
660 return alternate_server_address_.GetReceivedValue();
661}
662
663void QuicConfig::SetSupportMaxHeaderListSize() {
664 support_max_header_list_size_.SetSendValue(1);
665}
666
667bool QuicConfig::SupportMaxHeaderListSize() const {
668 return support_max_header_list_size_.HasReceivedValue();
669}
670
671void QuicConfig::SetStatelessResetTokenToSend(
672 QuicUint128 stateless_reset_token) {
673 stateless_reset_token_.SetSendValue(stateless_reset_token);
674}
675
676bool QuicConfig::HasReceivedStatelessResetToken() const {
677 return stateless_reset_token_.HasReceivedValue();
678}
679
680QuicUint128 QuicConfig::ReceivedStatelessResetToken() const {
681 return stateless_reset_token_.GetReceivedValue();
682}
683
684bool QuicConfig::negotiated() const {
685 // TODO(ianswett): Add the negotiated parameters once and iterate over all
686 // of them in negotiated, ToHandshakeMessage, and ProcessPeerHello.
687 return idle_network_timeout_seconds_.negotiated();
688}
689
690void QuicConfig::SetCreateSessionTagIndicators(QuicTagVector tags) {
691 create_session_tag_indicators_ = std::move(tags);
692}
693
694const QuicTagVector& QuicConfig::create_session_tag_indicators() const {
695 return create_session_tag_indicators_;
696}
697
698void QuicConfig::SetDefaults() {
699 idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
700 kDefaultIdleTimeoutSecs);
701 silent_close_.set(1, 0);
fkastenholzd3a1de92019-05-15 07:00:07 -0700702 SetMaxIncomingBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
703 SetMaxIncomingUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500704 max_time_before_crypto_handshake_ =
705 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
706 max_idle_time_before_crypto_handshake_ =
707 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs);
708 max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets;
709
710 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
711 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
fkastenholz4c7303c2019-07-29 08:17:07 -0700712 SetMaxAckDelayToSendMs(kDefaultDelayedAckTimeMs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 SetSupportMaxHeaderListSize();
714}
715
fkastenholzd3a1de92019-05-15 07:00:07 -0700716void QuicConfig::ToHandshakeMessage(
717 CryptoHandshakeMessage* out,
718 QuicTransportVersion transport_version) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500719 idle_network_timeout_seconds_.ToHandshakeMessage(out);
720 silent_close_.ToHandshakeMessage(out);
fkastenholzd3a1de92019-05-15 07:00:07 -0700721 // Do not need a version check here, max...bi... will encode
722 // as "MIDS" -- the max initial dynamic streams tag -- if
fkastenholz305e1732019-06-18 05:01:22 -0700723 // doing some version other than IETF QUIC.
fkastenholzd3a1de92019-05-15 07:00:07 -0700724 max_incoming_bidirectional_streams_.ToHandshakeMessage(out);
fkastenholz305e1732019-06-18 05:01:22 -0700725 if (VersionHasIetfQuicFrames(transport_version)) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700726 max_incoming_unidirectional_streams_.ToHandshakeMessage(out);
727 }
fkastenholz4c7303c2019-07-29 08:17:07 -0700728 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
729 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 1, 4);
730 max_ack_delay_ms_.ToHandshakeMessage(out);
731 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500732 bytes_for_connection_id_.ToHandshakeMessage(out);
733 initial_round_trip_time_us_.ToHandshakeMessage(out);
734 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
735 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
736 connection_migration_disabled_.ToHandshakeMessage(out);
737 connection_options_.ToHandshakeMessage(out);
738 alternate_server_address_.ToHandshakeMessage(out);
739 support_max_header_list_size_.ToHandshakeMessage(out);
740 stateless_reset_token_.ToHandshakeMessage(out);
741}
742
743QuicErrorCode QuicConfig::ProcessPeerHello(
744 const CryptoHandshakeMessage& peer_hello,
745 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700746 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500747 DCHECK(error_details != nullptr);
748
749 QuicErrorCode error = QUIC_NO_ERROR;
750 if (error == QUIC_NO_ERROR) {
751 error = idle_network_timeout_seconds_.ProcessPeerHello(
752 peer_hello, hello_type, error_details);
753 }
754 if (error == QUIC_NO_ERROR) {
755 error =
756 silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
757 }
758 if (error == QUIC_NO_ERROR) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700759 error = max_incoming_bidirectional_streams_.ProcessPeerHello(
760 peer_hello, hello_type, error_details);
761 }
762 if (error == QUIC_NO_ERROR) {
763 error = max_incoming_unidirectional_streams_.ProcessPeerHello(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500764 peer_hello, hello_type, error_details);
765 }
766 if (error == QUIC_NO_ERROR) {
767 error = bytes_for_connection_id_.ProcessPeerHello(peer_hello, hello_type,
768 error_details);
769 }
770 if (error == QUIC_NO_ERROR) {
771 error = initial_round_trip_time_us_.ProcessPeerHello(peer_hello, hello_type,
772 error_details);
773 }
774 if (error == QUIC_NO_ERROR) {
775 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
776 peer_hello, hello_type, error_details);
777 }
778 if (error == QUIC_NO_ERROR) {
779 error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
780 peer_hello, hello_type, error_details);
781 }
782 if (error == QUIC_NO_ERROR) {
783 error = connection_migration_disabled_.ProcessPeerHello(
784 peer_hello, hello_type, error_details);
785 }
786 if (error == QUIC_NO_ERROR) {
787 error = connection_options_.ProcessPeerHello(peer_hello, hello_type,
788 error_details);
789 }
790 if (error == QUIC_NO_ERROR) {
791 error = alternate_server_address_.ProcessPeerHello(peer_hello, hello_type,
792 error_details);
793 }
794 if (error == QUIC_NO_ERROR) {
795 error = support_max_header_list_size_.ProcessPeerHello(
796 peer_hello, hello_type, error_details);
797 }
798 if (error == QUIC_NO_ERROR) {
799 error = stateless_reset_token_.ProcessPeerHello(peer_hello, hello_type,
800 error_details);
801 }
fkastenholz4c7303c2019-07-29 08:17:07 -0700802
803 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time) &&
804 error == QUIC_NO_ERROR) {
805 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 2, 4);
806 error = max_ack_delay_ms_.ProcessPeerHello(peer_hello, hello_type,
807 error_details);
808 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500809 return error;
810}
811
812bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
dschinazi6cf4d2a2019-04-30 16:20:23 -0700813 params->idle_timeout_milliseconds.set_value(
814 idle_network_timeout_seconds_.GetUint32() * kNumMillisPerSecond);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500815
dschinazi52127d72019-04-17 15:12:38 -0700816 if (stateless_reset_token_.HasSendValue()) {
817 QuicUint128 stateless_reset_token = stateless_reset_token_.GetSendValue();
818 params->stateless_reset_token.assign(
819 reinterpret_cast<const char*>(&stateless_reset_token),
820 reinterpret_cast<const char*>(&stateless_reset_token) +
821 sizeof(stateless_reset_token));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500822 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500823
dschinazi52127d72019-04-17 15:12:38 -0700824 params->max_packet_size.set_value(kMaxIncomingPacketSize);
825 params->initial_max_data.set_value(
826 initial_session_flow_control_window_bytes_.GetSendValue());
827 params->initial_max_stream_data_bidi_local.set_value(
828 initial_stream_flow_control_window_bytes_.GetSendValue());
829 params->initial_max_stream_data_bidi_remote.set_value(
830 initial_stream_flow_control_window_bytes_.GetSendValue());
831 params->initial_max_stream_data_uni.set_value(
832 initial_stream_flow_control_window_bytes_.GetSendValue());
833 params->initial_max_streams_bidi.set_value(
fkastenholzd3a1de92019-05-15 07:00:07 -0700834 max_incoming_bidirectional_streams_.GetSendValue());
dschinazi52127d72019-04-17 15:12:38 -0700835 params->initial_max_streams_uni.set_value(
fkastenholzd3a1de92019-05-15 07:00:07 -0700836 max_incoming_unidirectional_streams_.GetSendValue());
fkastenholz4c7303c2019-07-29 08:17:07 -0700837 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
838 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 3, 4);
839 params->max_ack_delay.set_value(kDefaultDelayedAckTimeMs);
840 }
dschinazi52127d72019-04-17 15:12:38 -0700841 params->disable_migration =
842 connection_migration_disabled_.HasSendValue() &&
843 connection_migration_disabled_.GetSendValue() != 0;
844
845 if (alternate_server_address_.HasSendValue()) {
846 TransportParameters::PreferredAddress preferred_address;
847 QuicSocketAddress socket_address = alternate_server_address_.GetSendValue();
848 if (socket_address.host().IsIPv6()) {
849 preferred_address.ipv6_socket_address = socket_address;
850 } else {
851 preferred_address.ipv4_socket_address = socket_address;
852 }
853 params->preferred_address =
854 QuicMakeUnique<TransportParameters::PreferredAddress>(
855 preferred_address);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500856 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500857
858 if (!params->google_quic_params) {
859 params->google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
860 }
861 silent_close_.ToHandshakeMessage(params->google_quic_params.get());
862 initial_round_trip_time_us_.ToHandshakeMessage(
863 params->google_quic_params.get());
864 connection_options_.ToHandshakeMessage(params->google_quic_params.get());
dschinazi52127d72019-04-17 15:12:38 -0700865
QUICHE teama6ef0a62019-03-07 20:34:33 -0500866 return true;
867}
868
869QuicErrorCode QuicConfig::ProcessTransportParameters(
870 const TransportParameters& params,
871 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700872 std::string* error_details) {
dschinazi6cf4d2a2019-04-30 16:20:23 -0700873 // Intentionally round down to probe too often rather than not often enough.
874 uint64_t idle_timeout_seconds =
875 params.idle_timeout_milliseconds.value() / kNumMillisPerSecond;
dschinazi7bf7c3c2019-05-01 21:19:47 -0700876 // An idle timeout of zero indicates it is disabled (in other words, it is
877 // set to infinity). When the idle timeout is very high, we set it to our
878 // preferred maximum and still probe that often.
879 if (idle_timeout_seconds > kMaximumIdleTimeoutSecs ||
880 idle_timeout_seconds == 0) {
dschinazi52127d72019-04-17 15:12:38 -0700881 idle_timeout_seconds = kMaximumIdleTimeoutSecs;
882 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500883 QuicErrorCode error = idle_network_timeout_seconds_.ReceiveValue(
dschinazi52127d72019-04-17 15:12:38 -0700884 idle_timeout_seconds, hello_type, error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500885 if (error != QUIC_NO_ERROR) {
dschinazid1967a22019-04-03 16:11:32 -0700886 DCHECK(!error_details->empty());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500887 return error;
888 }
dschinazi52127d72019-04-17 15:12:38 -0700889
890 if (!params.stateless_reset_token.empty()) {
891 QuicUint128 stateless_reset_token;
892 if (params.stateless_reset_token.size() != sizeof(stateless_reset_token)) {
893 QUIC_BUG << "Bad stateless reset token length "
894 << params.stateless_reset_token.size();
895 *error_details = "Bad stateless reset token length";
896 return QUIC_INTERNAL_ERROR;
897 }
898 memcpy(&stateless_reset_token, params.stateless_reset_token.data(),
899 params.stateless_reset_token.size());
900 stateless_reset_token_.SetReceivedValue(stateless_reset_token);
901 }
902
903 if (params.max_packet_size.value() < kMaxOutgoingPacketSize) {
904 // TODO(dschinazi) act on this.
905 QUIC_DLOG(ERROR) << "Ignoring peer's requested max packet size of "
906 << params.max_packet_size.value();
907 }
908
909 initial_session_flow_control_window_bytes_.SetReceivedValue(
910 std::min<uint64_t>(params.initial_max_data.value(),
911 std::numeric_limits<uint32_t>::max()));
fkastenholzd3a1de92019-05-15 07:00:07 -0700912 max_incoming_bidirectional_streams_.SetReceivedValue(
dschinazi52127d72019-04-17 15:12:38 -0700913 std::min<uint64_t>(params.initial_max_streams_bidi.value(),
914 std::numeric_limits<uint32_t>::max()));
fkastenholzd3a1de92019-05-15 07:00:07 -0700915 max_incoming_unidirectional_streams_.SetReceivedValue(
916 std::min<uint64_t>(params.initial_max_streams_uni.value(),
917 std::numeric_limits<uint32_t>::max()));
dschinazi52127d72019-04-17 15:12:38 -0700918
919 initial_stream_flow_control_window_bytes_.SetReceivedValue(
920 std::min<uint64_t>(params.initial_max_stream_data_bidi_local.value(),
921 std::numeric_limits<uint32_t>::max()));
fkastenholz4c7303c2019-07-29 08:17:07 -0700922 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
923 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 4, 4);
924 max_ack_delay_ms_.SetReceivedValue(std::min<uint32_t>(
925 params.max_ack_delay.value(), std::numeric_limits<uint32_t>::max()));
926 }
dschinazi52127d72019-04-17 15:12:38 -0700927 connection_migration_disabled_.SetReceivedValue(
928 params.disable_migration ? 1u : 0u);
929
930 if (params.preferred_address != nullptr) {
931 if (params.preferred_address->ipv6_socket_address.port() != 0) {
932 alternate_server_address_.SetReceivedValue(
933 params.preferred_address->ipv6_socket_address);
934 } else if (params.preferred_address->ipv4_socket_address.port() != 0) {
935 alternate_server_address_.SetReceivedValue(
936 params.preferred_address->ipv4_socket_address);
937 }
938 }
939
QUICHE teama6ef0a62019-03-07 20:34:33 -0500940 const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
dschinazid1967a22019-04-03 16:11:32 -0700941 if (peer_params != nullptr) {
942 error =
943 silent_close_.ProcessPeerHello(*peer_params, hello_type, error_details);
944 if (error != QUIC_NO_ERROR) {
945 DCHECK(!error_details->empty());
946 return error;
947 }
948 error = initial_round_trip_time_us_.ProcessPeerHello(
949 *peer_params, hello_type, error_details);
950 if (error != QUIC_NO_ERROR) {
951 DCHECK(!error_details->empty());
952 return error;
953 }
954 error = connection_options_.ProcessPeerHello(*peer_params, hello_type,
955 error_details);
956 if (error != QUIC_NO_ERROR) {
957 DCHECK(!error_details->empty());
958 return error;
959 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500960 }
961
QUICHE teama6ef0a62019-03-07 20:34:33 -0500962 return QUIC_NO_ERROR;
963}
964
965} // namespace quic