blob: 22aef80fb03d37f96ede9a324582643eb15836bf [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),
fkastenholz4dc4ba32019-07-30 09:55:25 -0700417 max_ack_delay_ms_(kMAD, PRESENCE_OPTIONAL),
418 ack_delay_exponent_(kADE, PRESENCE_OPTIONAL) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 SetDefaults();
420}
421
422QuicConfig::QuicConfig(const QuicConfig& other) = default;
423
424QuicConfig::~QuicConfig() {}
425
426bool QuicConfig::SetInitialReceivedConnectionOptions(
427 const QuicTagVector& tags) {
428 if (HasReceivedConnectionOptions()) {
429 // If we have already received connection options (via handshake or due to
430 // a previous call), don't re-initialize.
431 return false;
432 }
433 connection_options_.SetReceivedValues(tags);
434 return true;
435}
436
437void QuicConfig::SetConnectionOptionsToSend(
438 const QuicTagVector& connection_options) {
439 connection_options_.SetSendValues(connection_options);
440}
441
442bool QuicConfig::HasReceivedConnectionOptions() const {
443 return connection_options_.HasReceivedValues();
444}
445
446QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
447 return connection_options_.GetReceivedValues();
448}
449
450bool QuicConfig::HasSendConnectionOptions() const {
451 return connection_options_.HasSendValues();
452}
453
454QuicTagVector QuicConfig::SendConnectionOptions() const {
455 return connection_options_.GetSendValues();
456}
457
458bool QuicConfig::HasClientSentConnectionOption(QuicTag tag,
459 Perspective perspective) const {
460 if (perspective == Perspective::IS_SERVER) {
461 if (HasReceivedConnectionOptions() &&
462 ContainsQuicTag(ReceivedConnectionOptions(), tag)) {
463 return true;
464 }
465 } else if (HasSendConnectionOptions() &&
466 ContainsQuicTag(SendConnectionOptions(), tag)) {
467 return true;
468 }
469 return false;
470}
471
472void QuicConfig::SetClientConnectionOptions(
473 const QuicTagVector& client_connection_options) {
474 client_connection_options_.SetSendValues(client_connection_options);
475}
476
477bool QuicConfig::HasClientRequestedIndependentOption(
478 QuicTag tag,
479 Perspective perspective) const {
480 if (perspective == Perspective::IS_SERVER) {
481 return (HasReceivedConnectionOptions() &&
482 ContainsQuicTag(ReceivedConnectionOptions(), tag));
483 }
484
485 return (client_connection_options_.HasSendValues() &&
486 ContainsQuicTag(client_connection_options_.GetSendValues(), tag));
487}
488
489void QuicConfig::SetIdleNetworkTimeout(
490 QuicTime::Delta max_idle_network_timeout,
491 QuicTime::Delta default_idle_network_timeout) {
492 idle_network_timeout_seconds_.set(
493 static_cast<uint32_t>(max_idle_network_timeout.ToSeconds()),
494 static_cast<uint32_t>(default_idle_network_timeout.ToSeconds()));
495}
496
497QuicTime::Delta QuicConfig::IdleNetworkTimeout() const {
498 return QuicTime::Delta::FromSeconds(
499 idle_network_timeout_seconds_.GetUint32());
500}
501
502// TODO(ianswett) Use this for silent close on mobile, or delete.
503QUIC_UNUSED void QuicConfig::SetSilentClose(bool silent_close) {
504 silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0);
505}
506
507bool QuicConfig::SilentClose() const {
508 return silent_close_.GetUint32() > 0;
509}
510
fkastenholzd3a1de92019-05-15 07:00:07 -0700511void QuicConfig::SetMaxIncomingBidirectionalStreamsToSend(
512 uint32_t max_streams) {
513 max_incoming_bidirectional_streams_.SetSendValue(max_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500514}
515
fkastenholzd3a1de92019-05-15 07:00:07 -0700516uint32_t QuicConfig::GetMaxIncomingBidirectionalStreamsToSend() {
517 return max_incoming_bidirectional_streams_.GetSendValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518}
519
fkastenholzd3a1de92019-05-15 07:00:07 -0700520bool QuicConfig::HasReceivedMaxIncomingBidirectionalStreams() {
521 return max_incoming_bidirectional_streams_.HasReceivedValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500522}
523
fkastenholzd3a1de92019-05-15 07:00:07 -0700524uint32_t QuicConfig::ReceivedMaxIncomingBidirectionalStreams() {
525 return max_incoming_bidirectional_streams_.GetReceivedValue();
526}
527
528void QuicConfig::SetMaxIncomingUnidirectionalStreamsToSend(
529 uint32_t max_streams) {
530 max_incoming_unidirectional_streams_.SetSendValue(max_streams);
531}
532
533uint32_t QuicConfig::GetMaxIncomingUnidirectionalStreamsToSend() {
534 return max_incoming_unidirectional_streams_.GetSendValue();
535}
536
537bool QuicConfig::HasReceivedMaxIncomingUnidirectionalStreams() {
538 return max_incoming_unidirectional_streams_.HasReceivedValue();
539}
540
541uint32_t QuicConfig::ReceivedMaxIncomingUnidirectionalStreams() {
542 return max_incoming_unidirectional_streams_.GetReceivedValue();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500543}
544
fkastenholz4c7303c2019-07-29 08:17:07 -0700545void QuicConfig::SetMaxAckDelayToSendMs(uint32_t max_ack_delay_ms) {
546 return max_ack_delay_ms_.SetSendValue(max_ack_delay_ms);
547}
548
549uint32_t QuicConfig::GetMaxAckDelayToToSendMs() const {
550 return max_ack_delay_ms_.GetSendValue();
551}
552
553bool QuicConfig::HasReceivedMaxAckDelayMs() const {
554 return max_ack_delay_ms_.HasReceivedValue();
555}
556
557uint32_t QuicConfig::ReceivedMaxAckDelayMs() const {
558 return max_ack_delay_ms_.GetReceivedValue();
559}
560
fkastenholz4dc4ba32019-07-30 09:55:25 -0700561void QuicConfig::SetAckDelayExponentToSend(uint32_t exponent) {
562 ack_delay_exponent_.SetSendValue(exponent);
563}
564
565uint32_t QuicConfig::GetAckDelayExponentToSend() {
566 return ack_delay_exponent_.GetSendValue();
567}
568
569bool QuicConfig::HasReceivedAckDelayExponent() const {
570 return ack_delay_exponent_.HasReceivedValue();
571}
572
573uint32_t QuicConfig::ReceivedAckDelayExponent() const {
574 return ack_delay_exponent_.GetReceivedValue();
575}
576
QUICHE teama6ef0a62019-03-07 20:34:33 -0500577bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
578 return bytes_for_connection_id_.HasSendValue();
579}
580
581void QuicConfig::SetBytesForConnectionIdToSend(uint32_t bytes) {
582 bytes_for_connection_id_.SetSendValue(bytes);
583}
584
585bool QuicConfig::HasReceivedBytesForConnectionId() const {
586 return bytes_for_connection_id_.HasReceivedValue();
587}
588
589uint32_t QuicConfig::ReceivedBytesForConnectionId() const {
590 return bytes_for_connection_id_.GetReceivedValue();
591}
592
593void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32_t rtt) {
594 initial_round_trip_time_us_.SetSendValue(rtt);
595}
596
597bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
598 return initial_round_trip_time_us_.HasReceivedValue();
599}
600
601uint32_t QuicConfig::ReceivedInitialRoundTripTimeUs() const {
602 return initial_round_trip_time_us_.GetReceivedValue();
603}
604
605bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
606 return initial_round_trip_time_us_.HasSendValue();
607}
608
609uint32_t QuicConfig::GetInitialRoundTripTimeUsToSend() const {
610 return initial_round_trip_time_us_.GetSendValue();
611}
612
613void QuicConfig::SetInitialStreamFlowControlWindowToSend(
614 uint32_t window_bytes) {
615 if (window_bytes < kMinimumFlowControlSendWindow) {
616 QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
dschinazic7036122019-04-30 12:46:34 -0700617 << ") cannot be set lower than minimum ("
QUICHE teama6ef0a62019-03-07 20:34:33 -0500618 << kMinimumFlowControlSendWindow << ").";
619 window_bytes = kMinimumFlowControlSendWindow;
620 }
621 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
622}
623
624uint32_t QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
625 return initial_stream_flow_control_window_bytes_.GetSendValue();
626}
627
628bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
629 return initial_stream_flow_control_window_bytes_.HasReceivedValue();
630}
631
632uint32_t QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
633 return initial_stream_flow_control_window_bytes_.GetReceivedValue();
634}
635
636void QuicConfig::SetInitialSessionFlowControlWindowToSend(
637 uint32_t window_bytes) {
638 if (window_bytes < kMinimumFlowControlSendWindow) {
639 QUIC_BUG << "Initial session flow control receive window (" << window_bytes
640 << ") cannot be set lower than default ("
641 << kMinimumFlowControlSendWindow << ").";
642 window_bytes = kMinimumFlowControlSendWindow;
643 }
644 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
645}
646
647uint32_t QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
648 return initial_session_flow_control_window_bytes_.GetSendValue();
649}
650
651bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
652 return initial_session_flow_control_window_bytes_.HasReceivedValue();
653}
654
655uint32_t QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
656 return initial_session_flow_control_window_bytes_.GetReceivedValue();
657}
658
659void QuicConfig::SetDisableConnectionMigration() {
660 connection_migration_disabled_.SetSendValue(1);
661}
662
663bool QuicConfig::DisableConnectionMigration() const {
664 return connection_migration_disabled_.HasReceivedValue();
665}
666
667void QuicConfig::SetAlternateServerAddressToSend(
668 const QuicSocketAddress& alternate_server_address) {
669 alternate_server_address_.SetSendValue(alternate_server_address);
670}
671
672bool QuicConfig::HasReceivedAlternateServerAddress() const {
673 return alternate_server_address_.HasReceivedValue();
674}
675
676const QuicSocketAddress& QuicConfig::ReceivedAlternateServerAddress() const {
677 return alternate_server_address_.GetReceivedValue();
678}
679
680void QuicConfig::SetSupportMaxHeaderListSize() {
681 support_max_header_list_size_.SetSendValue(1);
682}
683
684bool QuicConfig::SupportMaxHeaderListSize() const {
685 return support_max_header_list_size_.HasReceivedValue();
686}
687
688void QuicConfig::SetStatelessResetTokenToSend(
689 QuicUint128 stateless_reset_token) {
690 stateless_reset_token_.SetSendValue(stateless_reset_token);
691}
692
693bool QuicConfig::HasReceivedStatelessResetToken() const {
694 return stateless_reset_token_.HasReceivedValue();
695}
696
697QuicUint128 QuicConfig::ReceivedStatelessResetToken() const {
698 return stateless_reset_token_.GetReceivedValue();
699}
700
701bool QuicConfig::negotiated() const {
702 // TODO(ianswett): Add the negotiated parameters once and iterate over all
703 // of them in negotiated, ToHandshakeMessage, and ProcessPeerHello.
704 return idle_network_timeout_seconds_.negotiated();
705}
706
707void QuicConfig::SetCreateSessionTagIndicators(QuicTagVector tags) {
708 create_session_tag_indicators_ = std::move(tags);
709}
710
711const QuicTagVector& QuicConfig::create_session_tag_indicators() const {
712 return create_session_tag_indicators_;
713}
714
715void QuicConfig::SetDefaults() {
716 idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
717 kDefaultIdleTimeoutSecs);
718 silent_close_.set(1, 0);
fkastenholzd3a1de92019-05-15 07:00:07 -0700719 SetMaxIncomingBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
720 SetMaxIncomingUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500721 max_time_before_crypto_handshake_ =
722 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
723 max_idle_time_before_crypto_handshake_ =
724 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs);
725 max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets;
726
727 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
728 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
fkastenholz4c7303c2019-07-29 08:17:07 -0700729 SetMaxAckDelayToSendMs(kDefaultDelayedAckTimeMs);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 SetSupportMaxHeaderListSize();
fkastenholz4dc4ba32019-07-30 09:55:25 -0700731 SetAckDelayExponentToSend(kDefaultAckDelayExponent);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500732}
733
fkastenholzd3a1de92019-05-15 07:00:07 -0700734void QuicConfig::ToHandshakeMessage(
735 CryptoHandshakeMessage* out,
736 QuicTransportVersion transport_version) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500737 idle_network_timeout_seconds_.ToHandshakeMessage(out);
738 silent_close_.ToHandshakeMessage(out);
fkastenholzd3a1de92019-05-15 07:00:07 -0700739 // Do not need a version check here, max...bi... will encode
740 // as "MIDS" -- the max initial dynamic streams tag -- if
fkastenholz305e1732019-06-18 05:01:22 -0700741 // doing some version other than IETF QUIC.
fkastenholzd3a1de92019-05-15 07:00:07 -0700742 max_incoming_bidirectional_streams_.ToHandshakeMessage(out);
fkastenholz305e1732019-06-18 05:01:22 -0700743 if (VersionHasIetfQuicFrames(transport_version)) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700744 max_incoming_unidirectional_streams_.ToHandshakeMessage(out);
fkastenholz4dc4ba32019-07-30 09:55:25 -0700745 ack_delay_exponent_.ToHandshakeMessage(out);
fkastenholzd3a1de92019-05-15 07:00:07 -0700746 }
fkastenholz4c7303c2019-07-29 08:17:07 -0700747 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
748 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 1, 4);
749 max_ack_delay_ms_.ToHandshakeMessage(out);
750 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500751 bytes_for_connection_id_.ToHandshakeMessage(out);
752 initial_round_trip_time_us_.ToHandshakeMessage(out);
753 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
754 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
755 connection_migration_disabled_.ToHandshakeMessage(out);
756 connection_options_.ToHandshakeMessage(out);
757 alternate_server_address_.ToHandshakeMessage(out);
758 support_max_header_list_size_.ToHandshakeMessage(out);
759 stateless_reset_token_.ToHandshakeMessage(out);
760}
761
762QuicErrorCode QuicConfig::ProcessPeerHello(
763 const CryptoHandshakeMessage& peer_hello,
764 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700765 std::string* error_details) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500766 DCHECK(error_details != nullptr);
767
768 QuicErrorCode error = QUIC_NO_ERROR;
769 if (error == QUIC_NO_ERROR) {
770 error = idle_network_timeout_seconds_.ProcessPeerHello(
771 peer_hello, hello_type, error_details);
772 }
773 if (error == QUIC_NO_ERROR) {
774 error =
775 silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
776 }
777 if (error == QUIC_NO_ERROR) {
fkastenholzd3a1de92019-05-15 07:00:07 -0700778 error = max_incoming_bidirectional_streams_.ProcessPeerHello(
779 peer_hello, hello_type, error_details);
780 }
781 if (error == QUIC_NO_ERROR) {
782 error = max_incoming_unidirectional_streams_.ProcessPeerHello(
QUICHE teama6ef0a62019-03-07 20:34:33 -0500783 peer_hello, hello_type, error_details);
784 }
785 if (error == QUIC_NO_ERROR) {
786 error = bytes_for_connection_id_.ProcessPeerHello(peer_hello, hello_type,
787 error_details);
788 }
789 if (error == QUIC_NO_ERROR) {
790 error = initial_round_trip_time_us_.ProcessPeerHello(peer_hello, hello_type,
791 error_details);
792 }
793 if (error == QUIC_NO_ERROR) {
794 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
795 peer_hello, hello_type, error_details);
796 }
797 if (error == QUIC_NO_ERROR) {
798 error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
799 peer_hello, hello_type, error_details);
800 }
801 if (error == QUIC_NO_ERROR) {
802 error = connection_migration_disabled_.ProcessPeerHello(
803 peer_hello, hello_type, error_details);
804 }
805 if (error == QUIC_NO_ERROR) {
806 error = connection_options_.ProcessPeerHello(peer_hello, hello_type,
807 error_details);
808 }
809 if (error == QUIC_NO_ERROR) {
810 error = alternate_server_address_.ProcessPeerHello(peer_hello, hello_type,
811 error_details);
812 }
813 if (error == QUIC_NO_ERROR) {
814 error = support_max_header_list_size_.ProcessPeerHello(
815 peer_hello, hello_type, error_details);
816 }
817 if (error == QUIC_NO_ERROR) {
818 error = stateless_reset_token_.ProcessPeerHello(peer_hello, hello_type,
819 error_details);
820 }
fkastenholz4c7303c2019-07-29 08:17:07 -0700821
822 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time) &&
823 error == QUIC_NO_ERROR) {
824 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 2, 4);
825 error = max_ack_delay_ms_.ProcessPeerHello(peer_hello, hello_type,
826 error_details);
827 }
fkastenholz4dc4ba32019-07-30 09:55:25 -0700828 if (error == QUIC_NO_ERROR) {
829 error = ack_delay_exponent_.ProcessPeerHello(peer_hello, hello_type,
830 error_details);
831 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500832 return error;
833}
834
835bool QuicConfig::FillTransportParameters(TransportParameters* params) const {
dschinazi6cf4d2a2019-04-30 16:20:23 -0700836 params->idle_timeout_milliseconds.set_value(
837 idle_network_timeout_seconds_.GetUint32() * kNumMillisPerSecond);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500838
dschinazi52127d72019-04-17 15:12:38 -0700839 if (stateless_reset_token_.HasSendValue()) {
840 QuicUint128 stateless_reset_token = stateless_reset_token_.GetSendValue();
841 params->stateless_reset_token.assign(
842 reinterpret_cast<const char*>(&stateless_reset_token),
843 reinterpret_cast<const char*>(&stateless_reset_token) +
844 sizeof(stateless_reset_token));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500845 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500846
dschinazi52127d72019-04-17 15:12:38 -0700847 params->max_packet_size.set_value(kMaxIncomingPacketSize);
848 params->initial_max_data.set_value(
849 initial_session_flow_control_window_bytes_.GetSendValue());
850 params->initial_max_stream_data_bidi_local.set_value(
851 initial_stream_flow_control_window_bytes_.GetSendValue());
852 params->initial_max_stream_data_bidi_remote.set_value(
853 initial_stream_flow_control_window_bytes_.GetSendValue());
854 params->initial_max_stream_data_uni.set_value(
855 initial_stream_flow_control_window_bytes_.GetSendValue());
856 params->initial_max_streams_bidi.set_value(
fkastenholzd3a1de92019-05-15 07:00:07 -0700857 max_incoming_bidirectional_streams_.GetSendValue());
dschinazi52127d72019-04-17 15:12:38 -0700858 params->initial_max_streams_uni.set_value(
fkastenholzd3a1de92019-05-15 07:00:07 -0700859 max_incoming_unidirectional_streams_.GetSendValue());
fkastenholz4c7303c2019-07-29 08:17:07 -0700860 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
861 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 3, 4);
862 params->max_ack_delay.set_value(kDefaultDelayedAckTimeMs);
863 }
fkastenholz4dc4ba32019-07-30 09:55:25 -0700864 params->ack_delay_exponent.set_value(ack_delay_exponent_.GetSendValue());
dschinazi52127d72019-04-17 15:12:38 -0700865 params->disable_migration =
866 connection_migration_disabled_.HasSendValue() &&
867 connection_migration_disabled_.GetSendValue() != 0;
868
869 if (alternate_server_address_.HasSendValue()) {
870 TransportParameters::PreferredAddress preferred_address;
871 QuicSocketAddress socket_address = alternate_server_address_.GetSendValue();
872 if (socket_address.host().IsIPv6()) {
873 preferred_address.ipv6_socket_address = socket_address;
874 } else {
875 preferred_address.ipv4_socket_address = socket_address;
876 }
877 params->preferred_address =
878 QuicMakeUnique<TransportParameters::PreferredAddress>(
879 preferred_address);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500880 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500881
882 if (!params->google_quic_params) {
883 params->google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
884 }
885 silent_close_.ToHandshakeMessage(params->google_quic_params.get());
886 initial_round_trip_time_us_.ToHandshakeMessage(
887 params->google_quic_params.get());
888 connection_options_.ToHandshakeMessage(params->google_quic_params.get());
dschinazi52127d72019-04-17 15:12:38 -0700889
QUICHE teama6ef0a62019-03-07 20:34:33 -0500890 return true;
891}
892
893QuicErrorCode QuicConfig::ProcessTransportParameters(
894 const TransportParameters& params,
895 HelloType hello_type,
vasilvvc48c8712019-03-11 13:38:16 -0700896 std::string* error_details) {
dschinazi6cf4d2a2019-04-30 16:20:23 -0700897 // Intentionally round down to probe too often rather than not often enough.
898 uint64_t idle_timeout_seconds =
899 params.idle_timeout_milliseconds.value() / kNumMillisPerSecond;
dschinazi7bf7c3c2019-05-01 21:19:47 -0700900 // An idle timeout of zero indicates it is disabled (in other words, it is
901 // set to infinity). When the idle timeout is very high, we set it to our
902 // preferred maximum and still probe that often.
903 if (idle_timeout_seconds > kMaximumIdleTimeoutSecs ||
904 idle_timeout_seconds == 0) {
dschinazi52127d72019-04-17 15:12:38 -0700905 idle_timeout_seconds = kMaximumIdleTimeoutSecs;
906 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500907 QuicErrorCode error = idle_network_timeout_seconds_.ReceiveValue(
dschinazi52127d72019-04-17 15:12:38 -0700908 idle_timeout_seconds, hello_type, error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500909 if (error != QUIC_NO_ERROR) {
dschinazid1967a22019-04-03 16:11:32 -0700910 DCHECK(!error_details->empty());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500911 return error;
912 }
dschinazi52127d72019-04-17 15:12:38 -0700913
914 if (!params.stateless_reset_token.empty()) {
915 QuicUint128 stateless_reset_token;
916 if (params.stateless_reset_token.size() != sizeof(stateless_reset_token)) {
917 QUIC_BUG << "Bad stateless reset token length "
918 << params.stateless_reset_token.size();
919 *error_details = "Bad stateless reset token length";
920 return QUIC_INTERNAL_ERROR;
921 }
922 memcpy(&stateless_reset_token, params.stateless_reset_token.data(),
923 params.stateless_reset_token.size());
924 stateless_reset_token_.SetReceivedValue(stateless_reset_token);
925 }
926
927 if (params.max_packet_size.value() < kMaxOutgoingPacketSize) {
928 // TODO(dschinazi) act on this.
929 QUIC_DLOG(ERROR) << "Ignoring peer's requested max packet size of "
930 << params.max_packet_size.value();
931 }
932
933 initial_session_flow_control_window_bytes_.SetReceivedValue(
934 std::min<uint64_t>(params.initial_max_data.value(),
935 std::numeric_limits<uint32_t>::max()));
fkastenholzd3a1de92019-05-15 07:00:07 -0700936 max_incoming_bidirectional_streams_.SetReceivedValue(
dschinazi52127d72019-04-17 15:12:38 -0700937 std::min<uint64_t>(params.initial_max_streams_bidi.value(),
938 std::numeric_limits<uint32_t>::max()));
fkastenholzd3a1de92019-05-15 07:00:07 -0700939 max_incoming_unidirectional_streams_.SetReceivedValue(
940 std::min<uint64_t>(params.initial_max_streams_uni.value(),
941 std::numeric_limits<uint32_t>::max()));
dschinazi52127d72019-04-17 15:12:38 -0700942
943 initial_stream_flow_control_window_bytes_.SetReceivedValue(
944 std::min<uint64_t>(params.initial_max_stream_data_bidi_local.value(),
945 std::numeric_limits<uint32_t>::max()));
fkastenholz4c7303c2019-07-29 08:17:07 -0700946 if (GetQuicReloadableFlag(quic_negotiate_ack_delay_time)) {
947 QUIC_RELOADABLE_FLAG_COUNT_N(quic_negotiate_ack_delay_time, 4, 4);
948 max_ack_delay_ms_.SetReceivedValue(std::min<uint32_t>(
949 params.max_ack_delay.value(), std::numeric_limits<uint32_t>::max()));
950 }
fkastenholz4dc4ba32019-07-30 09:55:25 -0700951 if (params.ack_delay_exponent.IsValid()) {
952 ack_delay_exponent_.SetReceivedValue(params.ack_delay_exponent.value());
953 }
dschinazi52127d72019-04-17 15:12:38 -0700954 connection_migration_disabled_.SetReceivedValue(
955 params.disable_migration ? 1u : 0u);
956
957 if (params.preferred_address != nullptr) {
958 if (params.preferred_address->ipv6_socket_address.port() != 0) {
959 alternate_server_address_.SetReceivedValue(
960 params.preferred_address->ipv6_socket_address);
961 } else if (params.preferred_address->ipv4_socket_address.port() != 0) {
962 alternate_server_address_.SetReceivedValue(
963 params.preferred_address->ipv4_socket_address);
964 }
965 }
966
QUICHE teama6ef0a62019-03-07 20:34:33 -0500967 const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
dschinazid1967a22019-04-03 16:11:32 -0700968 if (peer_params != nullptr) {
969 error =
970 silent_close_.ProcessPeerHello(*peer_params, hello_type, error_details);
971 if (error != QUIC_NO_ERROR) {
972 DCHECK(!error_details->empty());
973 return error;
974 }
975 error = initial_round_trip_time_us_.ProcessPeerHello(
976 *peer_params, hello_type, error_details);
977 if (error != QUIC_NO_ERROR) {
978 DCHECK(!error_details->empty());
979 return error;
980 }
981 error = connection_options_.ProcessPeerHello(*peer_params, hello_type,
982 error_details);
983 if (error != QUIC_NO_ERROR) {
984 DCHECK(!error_details->empty());
985 return error;
986 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500987 }
988
QUICHE teama6ef0a62019-03-07 20:34:33 -0500989 return QUIC_NO_ERROR;
990}
991
992} // namespace quic