Re-land: C++ readability review
[chromium-blink-merge.git] / net / quic / quic_config.cc
blob3bdf26a36816f0ab9309f290b707457248f1208d
1 // 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.
5 #include "net/quic/quic_config.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "net/quic/crypto/crypto_handshake_message.h"
11 #include "net/quic/crypto/crypto_protocol.h"
12 #include "net/quic/quic_utils.h"
14 using std::min;
15 using std::string;
17 namespace net {
19 // Reads the value corresponding to |name_| from |msg| into |out|. If the
20 // |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
21 // to |default_value|.
22 QuicErrorCode ReadUint32(const CryptoHandshakeMessage& msg,
23 QuicTag tag,
24 QuicConfigPresence presence,
25 uint32 default_value,
26 uint32* out,
27 string* error_details) {
28 DCHECK(error_details != nullptr);
29 QuicErrorCode error = msg.GetUint32(tag, out);
30 switch (error) {
31 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
32 if (presence == PRESENCE_REQUIRED) {
33 *error_details = "Missing " + QuicUtils::TagToString(tag);
34 break;
36 error = QUIC_NO_ERROR;
37 *out = default_value;
38 break;
39 case QUIC_NO_ERROR:
40 break;
41 default:
42 *error_details = "Bad " + QuicUtils::TagToString(tag);
43 break;
45 return error;
49 QuicConfigValue::QuicConfigValue(QuicTag tag,
50 QuicConfigPresence presence)
51 : tag_(tag),
52 presence_(presence) {
54 QuicConfigValue::~QuicConfigValue() {}
56 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
57 QuicConfigPresence presence)
58 : QuicConfigValue(tag, presence),
59 negotiated_(false) {
61 QuicNegotiableValue::~QuicNegotiableValue() {}
63 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
64 QuicConfigPresence presence)
65 : QuicNegotiableValue(tag, presence),
66 max_value_(0),
67 default_value_(0),
68 negotiated_value_(0) {
70 QuicNegotiableUint32::~QuicNegotiableUint32() {}
72 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
73 DCHECK_LE(default_value, max);
74 max_value_ = max;
75 default_value_ = default_value;
78 uint32 QuicNegotiableUint32::GetUint32() const {
79 if (negotiated()) {
80 return negotiated_value_;
82 return default_value_;
85 void QuicNegotiableUint32::ToHandshakeMessage(
86 CryptoHandshakeMessage* out) const {
87 if (negotiated()) {
88 out->SetValue(tag_, negotiated_value_);
89 } else {
90 out->SetValue(tag_, max_value_);
94 QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
95 const CryptoHandshakeMessage& peer_hello,
96 HelloType hello_type,
97 string* error_details) {
98 DCHECK(!negotiated());
99 DCHECK(error_details != nullptr);
100 uint32 value;
101 QuicErrorCode error = ReadUint32(peer_hello,
102 tag_,
103 presence_,
104 default_value_,
105 &value,
106 error_details);
107 if (error != QUIC_NO_ERROR) {
108 return error;
110 if (hello_type == SERVER && value > max_value_) {
111 *error_details =
112 "Invalid value received for " + QuicUtils::TagToString(tag_);
113 return QUIC_INVALID_NEGOTIATED_VALUE;
116 set_negotiated(true);
117 negotiated_value_ = min(value, max_value_);
118 return QUIC_NO_ERROR;
121 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
122 : QuicNegotiableValue(tag, presence),
123 negotiated_tag_(0),
124 default_value_(0) {
127 QuicNegotiableTag::~QuicNegotiableTag() {}
129 void QuicNegotiableTag::set(const QuicTagVector& possible,
130 QuicTag default_value) {
131 DCHECK(ContainsQuicTag(possible, default_value));
132 possible_values_ = possible;
133 default_value_ = default_value;
136 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
137 if (negotiated()) {
138 // Because of the way we serialize and parse handshake messages we can
139 // serialize this as value and still parse it as a vector.
140 out->SetValue(tag_, negotiated_tag_);
141 } else {
142 out->SetVector(tag_, possible_values_);
146 QuicErrorCode QuicNegotiableTag::ReadVector(
147 const CryptoHandshakeMessage& msg,
148 const QuicTag** out,
149 size_t* out_length,
150 string* error_details) const {
151 DCHECK(error_details != nullptr);
152 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
153 switch (error) {
154 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
155 if (presence_ == PRESENCE_REQUIRED) {
156 *error_details = "Missing " + QuicUtils::TagToString(tag_);
157 break;
159 error = QUIC_NO_ERROR;
160 *out_length = 1;
161 *out = &default_value_;
163 case QUIC_NO_ERROR:
164 break;
165 default:
166 *error_details = "Bad " + QuicUtils::TagToString(tag_);
167 break;
169 return error;
172 QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
173 const CryptoHandshakeMessage& peer_hello,
174 HelloType hello_type,
175 string* error_details) {
176 DCHECK(!negotiated());
177 DCHECK(error_details != nullptr);
178 const QuicTag* received_tags;
179 size_t received_tags_length;
180 QuicErrorCode error = ReadVector(peer_hello, &received_tags,
181 &received_tags_length, error_details);
182 if (error != QUIC_NO_ERROR) {
183 return error;
186 if (hello_type == SERVER) {
187 if (received_tags_length != 1 ||
188 !ContainsQuicTag(possible_values_, *received_tags)) {
189 *error_details = "Invalid " + QuicUtils::TagToString(tag_);
190 return QUIC_INVALID_NEGOTIATED_VALUE;
192 negotiated_tag_ = *received_tags;
193 } else {
194 QuicTag negotiated_tag;
195 if (!QuicUtils::FindMutualTag(possible_values_,
196 received_tags,
197 received_tags_length,
198 QuicUtils::LOCAL_PRIORITY,
199 &negotiated_tag,
200 nullptr)) {
201 *error_details = "Unsupported " + QuicUtils::TagToString(tag_);
202 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
204 negotiated_tag_ = negotiated_tag;
207 set_negotiated(true);
208 return QUIC_NO_ERROR;
211 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
212 : QuicConfigValue(tag, presence),
213 has_send_value_(false),
214 has_receive_value_(false) {
216 QuicFixedUint32::~QuicFixedUint32() {}
218 bool QuicFixedUint32::HasSendValue() const {
219 return has_send_value_;
222 uint32 QuicFixedUint32::GetSendValue() const {
223 LOG_IF(DFATAL, !has_send_value_)
224 << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
225 return send_value_;
228 void QuicFixedUint32::SetSendValue(uint32 value) {
229 has_send_value_ = true;
230 send_value_ = value;
233 bool QuicFixedUint32::HasReceivedValue() const {
234 return has_receive_value_;
237 uint32 QuicFixedUint32::GetReceivedValue() const {
238 LOG_IF(DFATAL, !has_receive_value_)
239 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
240 return receive_value_;
243 void QuicFixedUint32::SetReceivedValue(uint32 value) {
244 has_receive_value_ = true;
245 receive_value_ = value;
248 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
249 if (has_send_value_) {
250 out->SetValue(tag_, send_value_);
254 QuicErrorCode QuicFixedUint32::ProcessPeerHello(
255 const CryptoHandshakeMessage& peer_hello,
256 HelloType hello_type,
257 string* error_details) {
258 DCHECK(error_details != nullptr);
259 QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
260 switch (error) {
261 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
262 if (presence_ == PRESENCE_OPTIONAL) {
263 return QUIC_NO_ERROR;
265 *error_details = "Missing " + QuicUtils::TagToString(tag_);
266 break;
267 case QUIC_NO_ERROR:
268 has_receive_value_ = true;
269 break;
270 default:
271 *error_details = "Bad " + QuicUtils::TagToString(tag_);
272 break;
274 return error;
277 QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
278 QuicConfigPresence presence)
279 : QuicConfigValue(name, presence),
280 has_send_values_(false),
281 has_receive_values_(false) {
284 QuicFixedTagVector::~QuicFixedTagVector() {}
286 bool QuicFixedTagVector::HasSendValues() const {
287 return has_send_values_;
290 QuicTagVector QuicFixedTagVector::GetSendValues() const {
291 LOG_IF(DFATAL, !has_send_values_)
292 << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
293 return send_values_;
296 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
297 has_send_values_ = true;
298 send_values_ = values;
301 bool QuicFixedTagVector::HasReceivedValues() const {
302 return has_receive_values_;
305 QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
306 LOG_IF(DFATAL, !has_receive_values_)
307 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
308 return receive_values_;
311 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
312 has_receive_values_ = true;
313 receive_values_ = values;
316 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
317 if (has_send_values_) {
318 out->SetVector(tag_, send_values_);
322 QuicErrorCode QuicFixedTagVector::ProcessPeerHello(
323 const CryptoHandshakeMessage& peer_hello,
324 HelloType hello_type,
325 string* error_details) {
326 DCHECK(error_details != nullptr);
327 const QuicTag* received_tags;
328 size_t received_tags_length;
329 QuicErrorCode error =
330 peer_hello.GetTaglist(tag_, &received_tags, &received_tags_length);
331 switch (error) {
332 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
333 if (presence_ == PRESENCE_OPTIONAL) {
334 return QUIC_NO_ERROR;
336 *error_details = "Missing " + QuicUtils::TagToString(tag_);
337 break;
338 case QUIC_NO_ERROR:
339 DVLOG(1) << "Received Connection Option tags from receiver.";
340 has_receive_values_ = true;
341 for (size_t i = 0; i < received_tags_length; ++i) {
342 receive_values_.push_back(received_tags[i]);
344 break;
345 default:
346 *error_details = "Bad " + QuicUtils::TagToString(tag_);
347 break;
349 return error;
352 QuicConfig::QuicConfig()
353 : max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
354 max_idle_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
355 max_undecryptable_packets_(0),
356 congestion_feedback_(kCGST, PRESENCE_OPTIONAL),
357 connection_options_(kCOPT, PRESENCE_OPTIONAL),
358 idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED),
359 silent_close_(kSCLS, PRESENCE_OPTIONAL),
360 max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED),
361 bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
362 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
363 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
364 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL),
365 socket_receive_buffer_(kSRBF, PRESENCE_OPTIONAL) {
366 SetDefaults();
369 QuicConfig::~QuicConfig() {}
371 void QuicConfig::SetConnectionOptionsToSend(
372 const QuicTagVector& connection_options) {
373 connection_options_.SetSendValues(connection_options);
376 bool QuicConfig::HasReceivedConnectionOptions() const {
377 return connection_options_.HasReceivedValues();
380 QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
381 return connection_options_.GetReceivedValues();
384 bool QuicConfig::HasSendConnectionOptions() const {
385 return connection_options_.HasSendValues();
388 QuicTagVector QuicConfig::SendConnectionOptions() const {
389 return connection_options_.GetSendValues();
392 void QuicConfig::SetIdleConnectionStateLifetime(
393 QuicTime::Delta max_idle_connection_state_lifetime,
394 QuicTime::Delta default_idle_conection_state_lifetime) {
395 idle_connection_state_lifetime_seconds_.set(
396 static_cast<uint32>(max_idle_connection_state_lifetime.ToSeconds()),
397 static_cast<uint32>(default_idle_conection_state_lifetime.ToSeconds()));
400 QuicTime::Delta QuicConfig::IdleConnectionStateLifetime() const {
401 return QuicTime::Delta::FromSeconds(
402 idle_connection_state_lifetime_seconds_.GetUint32());
405 // TODO(ianswett) Use this for silent close on mobile, or delete.
406 void QuicConfig::SetSilentClose(bool silent_close) {
407 silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0);
410 bool QuicConfig::SilentClose() const {
411 return silent_close_.GetUint32() > 0;
414 void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams,
415 size_t default_streams) {
416 max_streams_per_connection_.set(max_streams, default_streams);
419 uint32 QuicConfig::MaxStreamsPerConnection() const {
420 return max_streams_per_connection_.GetUint32();
423 bool QuicConfig::HasSetBytesForConnectionIdToSend() const {
424 return bytes_for_connection_id_.HasSendValue();
427 void QuicConfig::SetBytesForConnectionIdToSend(uint32 bytes) {
428 bytes_for_connection_id_.SetSendValue(bytes);
431 bool QuicConfig::HasReceivedBytesForConnectionId() const {
432 return bytes_for_connection_id_.HasReceivedValue();
435 uint32 QuicConfig::ReceivedBytesForConnectionId() const {
436 return bytes_for_connection_id_.GetReceivedValue();
439 void QuicConfig::SetInitialRoundTripTimeUsToSend(uint32 rtt) {
440 initial_round_trip_time_us_.SetSendValue(rtt);
443 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
444 return initial_round_trip_time_us_.HasReceivedValue();
447 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
448 return initial_round_trip_time_us_.GetReceivedValue();
451 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
452 return initial_round_trip_time_us_.HasSendValue();
455 uint32 QuicConfig::GetInitialRoundTripTimeUsToSend() const {
456 return initial_round_trip_time_us_.GetSendValue();
459 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
460 if (window_bytes < kMinimumFlowControlSendWindow) {
461 LOG(DFATAL) << "Initial stream flow control receive window ("
462 << window_bytes << ") cannot be set lower than default ("
463 << kMinimumFlowControlSendWindow << ").";
464 window_bytes = kMinimumFlowControlSendWindow;
466 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
469 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
470 return initial_stream_flow_control_window_bytes_.GetSendValue();
473 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
474 return initial_stream_flow_control_window_bytes_.HasReceivedValue();
477 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
478 return initial_stream_flow_control_window_bytes_.GetReceivedValue();
481 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
482 if (window_bytes < kMinimumFlowControlSendWindow) {
483 LOG(DFATAL) << "Initial session flow control receive window ("
484 << window_bytes << ") cannot be set lower than default ("
485 << kMinimumFlowControlSendWindow << ").";
486 window_bytes = kMinimumFlowControlSendWindow;
488 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
491 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
492 return initial_session_flow_control_window_bytes_.GetSendValue();
495 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
496 return initial_session_flow_control_window_bytes_.HasReceivedValue();
499 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
500 return initial_session_flow_control_window_bytes_.GetReceivedValue();
503 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window) {
504 socket_receive_buffer_.SetSendValue(tcp_receive_window);
507 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
508 return socket_receive_buffer_.HasReceivedValue();
511 uint32 QuicConfig::ReceivedSocketReceiveBuffer() const {
512 return socket_receive_buffer_.GetReceivedValue();
515 bool QuicConfig::negotiated() const {
516 // TODO(ianswett): Add the negotiated parameters once and iterate over all
517 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
518 // ProcessServerHello.
519 return idle_connection_state_lifetime_seconds_.negotiated() &&
520 max_streams_per_connection_.negotiated();
523 void QuicConfig::SetDefaults() {
524 QuicTagVector congestion_feedback;
525 // TODO(alyssar) stop sending this once QUIC_VERSION_23 is sunset.
526 // This field was required until version 22 was removed but by the time
527 // QUIC_VERSION_23 is sunset, no users of QUIC_VERSION_24 should be expecting
528 // it.
529 congestion_feedback.push_back(kQBIC);
530 congestion_feedback_.set(congestion_feedback, kQBIC);
531 idle_connection_state_lifetime_seconds_.set(kMaximumIdleTimeoutSecs,
532 kDefaultIdleTimeoutSecs);
533 silent_close_.set(1, 0);
534 SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection,
535 kDefaultMaxStreamsPerConnection);
536 max_time_before_crypto_handshake_ =
537 QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
538 max_idle_time_before_crypto_handshake_ =
539 QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs);
540 max_undecryptable_packets_ = kDefaultMaxUndecryptablePackets;
542 SetInitialStreamFlowControlWindowToSend(kMinimumFlowControlSendWindow);
543 SetInitialSessionFlowControlWindowToSend(kMinimumFlowControlSendWindow);
546 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
547 congestion_feedback_.ToHandshakeMessage(out);
548 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
549 silent_close_.ToHandshakeMessage(out);
550 max_streams_per_connection_.ToHandshakeMessage(out);
551 bytes_for_connection_id_.ToHandshakeMessage(out);
552 initial_round_trip_time_us_.ToHandshakeMessage(out);
553 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
554 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
555 socket_receive_buffer_.ToHandshakeMessage(out);
556 connection_options_.ToHandshakeMessage(out);
559 QuicErrorCode QuicConfig::ProcessPeerHello(
560 const CryptoHandshakeMessage& peer_hello,
561 HelloType hello_type,
562 string* error_details) {
563 DCHECK(error_details != nullptr);
565 QuicErrorCode error = QUIC_NO_ERROR;
566 if (error == QUIC_NO_ERROR) {
567 error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
568 peer_hello, hello_type, error_details);
570 if (error == QUIC_NO_ERROR) {
571 error =
572 silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
574 if (error == QUIC_NO_ERROR) {
575 error = max_streams_per_connection_.ProcessPeerHello(
576 peer_hello, hello_type, error_details);
578 if (error == QUIC_NO_ERROR) {
579 error = bytes_for_connection_id_.ProcessPeerHello(
580 peer_hello, hello_type, error_details);
582 if (error == QUIC_NO_ERROR) {
583 error = initial_round_trip_time_us_.ProcessPeerHello(
584 peer_hello, hello_type, error_details);
586 if (error == QUIC_NO_ERROR) {
587 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
588 peer_hello, hello_type, error_details);
590 if (error == QUIC_NO_ERROR) {
591 error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
592 peer_hello, hello_type, error_details);
594 if (error == QUIC_NO_ERROR) {
595 error = socket_receive_buffer_.ProcessPeerHello(
596 peer_hello, hello_type, error_details);
598 if (error == QUIC_NO_ERROR) {
599 error = connection_options_.ProcessPeerHello(
600 peer_hello, hello_type, error_details);
602 return error;
605 } // namespace net