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"
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_flags.h"
13 #include "net/quic/quic_sent_packet_manager.h"
14 #include "net/quic/quic_utils.h"
21 // Reads the value corresponding to |name_| from |msg| into |out|. If the
22 // |name_| is absent in |msg| and |presence| is set to OPTIONAL |out| is set
23 // to |default_value|.
24 QuicErrorCode
ReadUint32(const CryptoHandshakeMessage
& msg
,
26 QuicConfigPresence presence
,
29 string
* error_details
) {
30 DCHECK(error_details
!= NULL
);
31 QuicErrorCode error
= msg
.GetUint32(tag
, out
);
33 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
34 if (presence
== PRESENCE_REQUIRED
) {
35 *error_details
= "Missing " + QuicUtils::TagToString(tag
);
38 error
= QUIC_NO_ERROR
;
44 *error_details
= "Bad " + QuicUtils::TagToString(tag
);
51 QuicConfigValue::QuicConfigValue(QuicTag tag
,
52 QuicConfigPresence presence
)
56 QuicConfigValue::~QuicConfigValue() {}
58 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag
,
59 QuicConfigPresence presence
)
60 : QuicConfigValue(tag
, presence
),
63 QuicNegotiableValue::~QuicNegotiableValue() {}
65 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag
,
66 QuicConfigPresence presence
)
67 : QuicNegotiableValue(tag
, presence
),
71 QuicNegotiableUint32::~QuicNegotiableUint32() {}
73 void QuicNegotiableUint32::set(uint32 max
, uint32 default_value
) {
74 DCHECK_LE(default_value
, max
);
76 default_value_
= default_value
;
79 uint32
QuicNegotiableUint32::GetUint32() const {
81 return negotiated_value_
;
83 return default_value_
;
86 void QuicNegotiableUint32::ToHandshakeMessage(
87 CryptoHandshakeMessage
* out
) const {
89 out
->SetValue(tag_
, negotiated_value_
);
91 out
->SetValue(tag_
, max_value_
);
95 QuicErrorCode
QuicNegotiableUint32::ProcessPeerHello(
96 const CryptoHandshakeMessage
& peer_hello
,
98 string
* error_details
) {
100 DCHECK(error_details
!= NULL
);
102 QuicErrorCode error
= ReadUint32(peer_hello
,
108 if (error
!= QUIC_NO_ERROR
) {
111 if (hello_type
== SERVER
&& value
> max_value_
) {
113 "Invalid value received for " + QuicUtils::TagToString(tag_
);
114 return QUIC_INVALID_NEGOTIATED_VALUE
;
118 negotiated_value_
= min(value
, max_value_
);
119 return QUIC_NO_ERROR
;
122 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag
, QuicConfigPresence presence
)
123 : QuicNegotiableValue(tag
, presence
),
128 QuicNegotiableTag::~QuicNegotiableTag() {}
130 void QuicNegotiableTag::set(const QuicTagVector
& possible
,
131 QuicTag default_value
) {
132 DCHECK(ContainsQuicTag(possible
, default_value
));
133 possible_values_
= possible
;
134 default_value_
= default_value
;
137 QuicTag
QuicNegotiableTag::GetTag() const {
139 return negotiated_tag_
;
141 return default_value_
;
144 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
146 // Because of the way we serialize and parse handshake messages we can
147 // serialize this as value and still parse it as a vector.
148 out
->SetValue(tag_
, negotiated_tag_
);
150 out
->SetVector(tag_
, possible_values_
);
154 QuicErrorCode
QuicNegotiableTag::ReadVector(
155 const CryptoHandshakeMessage
& msg
,
158 string
* error_details
) const {
159 DCHECK(error_details
!= NULL
);
160 QuicErrorCode error
= msg
.GetTaglist(tag_
, out
, out_length
);
162 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
163 if (presence_
== PRESENCE_REQUIRED
) {
164 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
167 error
= QUIC_NO_ERROR
;
169 *out
= &default_value_
;
174 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
180 QuicErrorCode
QuicNegotiableTag::ProcessPeerHello(
181 const CryptoHandshakeMessage
& peer_hello
,
182 HelloType hello_type
,
183 string
* error_details
) {
184 DCHECK(!negotiated_
);
185 DCHECK(error_details
!= NULL
);
186 const QuicTag
* received_tags
;
187 size_t received_tags_length
;
188 QuicErrorCode error
= ReadVector(peer_hello
, &received_tags
,
189 &received_tags_length
, error_details
);
190 if (error
!= QUIC_NO_ERROR
) {
194 if (hello_type
== SERVER
) {
195 if (received_tags_length
!= 1 ||
196 !ContainsQuicTag(possible_values_
, *received_tags
)) {
197 *error_details
= "Invalid " + QuicUtils::TagToString(tag_
);
198 return QUIC_INVALID_NEGOTIATED_VALUE
;
200 negotiated_tag_
= *received_tags
;
202 QuicTag negotiated_tag
;
203 if (!QuicUtils::FindMutualTag(possible_values_
,
205 received_tags_length
,
206 QuicUtils::LOCAL_PRIORITY
,
209 *error_details
= "Unsupported " + QuicUtils::TagToString(tag_
);
210 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP
;
212 negotiated_tag_
= negotiated_tag
;
216 return QUIC_NO_ERROR
;
219 QuicFixedUint32::QuicFixedUint32(QuicTag tag
, QuicConfigPresence presence
)
220 : QuicConfigValue(tag
, presence
),
221 has_send_value_(false),
222 has_receive_value_(false) {
224 QuicFixedUint32::~QuicFixedUint32() {}
226 bool QuicFixedUint32::HasSendValue() const {
227 return has_send_value_
;
230 uint32
QuicFixedUint32::GetSendValue() const {
231 LOG_IF(DFATAL
, !has_send_value_
)
232 << "No send value to get for tag:" << QuicUtils::TagToString(tag_
);
236 void QuicFixedUint32::SetSendValue(uint32 value
) {
237 has_send_value_
= true;
241 bool QuicFixedUint32::HasReceivedValue() const {
242 return has_receive_value_
;
245 uint32
QuicFixedUint32::GetReceivedValue() const {
246 LOG_IF(DFATAL
, !has_receive_value_
)
247 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
248 return receive_value_
;
251 void QuicFixedUint32::SetReceivedValue(uint32 value
) {
252 has_receive_value_
= true;
253 receive_value_
= value
;
256 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
257 if (has_send_value_
) {
258 out
->SetValue(tag_
, send_value_
);
262 QuicErrorCode
QuicFixedUint32::ProcessPeerHello(
263 const CryptoHandshakeMessage
& peer_hello
,
264 HelloType hello_type
,
265 string
* error_details
) {
266 DCHECK(error_details
!= NULL
);
267 QuicErrorCode error
= peer_hello
.GetUint32(tag_
, &receive_value_
);
269 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
270 if (presence_
== PRESENCE_OPTIONAL
) {
271 return QUIC_NO_ERROR
;
273 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
276 has_receive_value_
= true;
279 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
285 QuicFixedTag::QuicFixedTag(QuicTag name
,
286 QuicConfigPresence presence
)
287 : QuicConfigValue(name
, presence
),
288 has_send_value_(false),
289 has_receive_value_(false) {
292 QuicFixedTag::~QuicFixedTag() {}
294 bool QuicFixedTag::HasSendValue() const {
295 return has_send_value_
;
298 uint32
QuicFixedTag::GetSendValue() const {
299 LOG_IF(DFATAL
, !has_send_value_
)
300 << "No send value to get for tag:" << QuicUtils::TagToString(tag_
);
304 void QuicFixedTag::SetSendValue(uint32 value
) {
305 has_send_value_
= true;
309 bool QuicFixedTag::HasReceivedValue() const {
310 return has_receive_value_
;
313 uint32
QuicFixedTag::GetReceivedValue() const {
314 LOG_IF(DFATAL
, !has_receive_value_
)
315 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
316 return receive_value_
;
319 void QuicFixedTag::SetReceivedValue(uint32 value
) {
320 has_receive_value_
= true;
321 receive_value_
= value
;
324 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
325 if (has_send_value_
) {
326 out
->SetValue(tag_
, send_value_
);
330 QuicErrorCode
QuicFixedTag::ProcessPeerHello(
331 const CryptoHandshakeMessage
& peer_hello
,
332 HelloType hello_type
,
333 string
* error_details
) {
334 DCHECK(error_details
!= NULL
);
335 QuicErrorCode error
= peer_hello
.GetUint32(tag_
, &receive_value_
);
337 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
338 if (presence_
== PRESENCE_OPTIONAL
) {
339 return QUIC_NO_ERROR
;
341 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
344 has_receive_value_
= true;
347 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
353 QuicFixedTagVector::QuicFixedTagVector(QuicTag name
,
354 QuicConfigPresence presence
)
355 : QuicConfigValue(name
, presence
),
356 has_send_values_(false),
357 has_receive_values_(false) {
360 QuicFixedTagVector::~QuicFixedTagVector() {}
362 bool QuicFixedTagVector::HasSendValues() const {
363 return has_send_values_
;
366 QuicTagVector
QuicFixedTagVector::GetSendValues() const {
367 LOG_IF(DFATAL
, !has_send_values_
)
368 << "No send values to get for tag:" << QuicUtils::TagToString(tag_
);
372 void QuicFixedTagVector::SetSendValues(const QuicTagVector
& values
) {
373 has_send_values_
= true;
374 send_values_
= values
;
377 bool QuicFixedTagVector::HasReceivedValues() const {
378 return has_receive_values_
;
381 QuicTagVector
QuicFixedTagVector::GetReceivedValues() const {
382 LOG_IF(DFATAL
, !has_receive_values_
)
383 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_
);
384 return receive_values_
;
387 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector
& values
) {
388 has_receive_values_
= true;
389 receive_values_
= values
;
392 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
393 if (has_send_values_
) {
394 out
->SetVector(tag_
, send_values_
);
398 QuicErrorCode
QuicFixedTagVector::ProcessPeerHello(
399 const CryptoHandshakeMessage
& peer_hello
,
400 HelloType hello_type
,
401 string
* error_details
) {
402 DCHECK(error_details
!= NULL
);
403 const QuicTag
* received_tags
;
404 size_t received_tags_length
;
405 QuicErrorCode error
=
406 peer_hello
.GetTaglist(tag_
, &received_tags
, &received_tags_length
);
408 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
:
409 if (presence_
== PRESENCE_OPTIONAL
) {
410 return QUIC_NO_ERROR
;
412 *error_details
= "Missing " + QuicUtils::TagToString(tag_
);
415 DVLOG(1) << "Received Connection Option tags from receiver.";
416 has_receive_values_
= true;
417 for (size_t i
= 0; i
< received_tags_length
; ++i
) {
418 receive_values_
.push_back(received_tags
[i
]);
422 *error_details
= "Bad " + QuicUtils::TagToString(tag_
);
428 QuicConfig::QuicConfig()
429 : congestion_feedback_(kCGST
, PRESENCE_REQUIRED
),
430 connection_options_(kCOPT
, PRESENCE_OPTIONAL
),
431 loss_detection_(kLOSS
, PRESENCE_OPTIONAL
),
432 idle_connection_state_lifetime_seconds_(kICSL
, PRESENCE_REQUIRED
),
433 keepalive_timeout_seconds_(kKATO
, PRESENCE_OPTIONAL
),
434 max_streams_per_connection_(kMSPC
, PRESENCE_REQUIRED
),
435 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
436 initial_congestion_window_(kSWND
, PRESENCE_OPTIONAL
),
437 initial_round_trip_time_us_(kIRTT
, PRESENCE_OPTIONAL
),
438 // TODO(rjshade): Make this PRESENCE_REQUIRED when QUIC_VERSION_16 is
440 initial_flow_control_window_bytes_(kIFCW
, PRESENCE_OPTIONAL
),
441 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
443 initial_stream_flow_control_window_bytes_(kSFCW
, PRESENCE_OPTIONAL
),
444 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
446 initial_session_flow_control_window_bytes_(kCFCW
, PRESENCE_OPTIONAL
),
447 socket_receive_buffer_(kSRBF
, PRESENCE_OPTIONAL
) {
450 QuicConfig::~QuicConfig() {}
452 void QuicConfig::set_congestion_feedback(
453 const QuicTagVector
& congestion_feedback
,
454 QuicTag default_congestion_feedback
) {
455 congestion_feedback_
.set(congestion_feedback
, default_congestion_feedback
);
458 QuicTag
QuicConfig::congestion_feedback() const {
459 return congestion_feedback_
.GetTag();
462 void QuicConfig::SetConnectionOptionsToSend(
463 const QuicTagVector
& connection_options
) {
464 connection_options_
.SetSendValues(connection_options
);
467 bool QuicConfig::HasReceivedConnectionOptions() const {
468 return connection_options_
.HasReceivedValues();
471 QuicTagVector
QuicConfig::ReceivedConnectionOptions() const {
472 return connection_options_
.GetReceivedValues();
475 bool QuicConfig::HasSendConnectionOptions() const {
476 return connection_options_
.HasSendValues();
479 QuicTagVector
QuicConfig::SendConnectionOptions() const {
480 return connection_options_
.GetSendValues();
483 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection
) {
484 loss_detection_
.SetSendValue(loss_detection
);
487 bool QuicConfig::HasReceivedLossDetection() const {
488 return loss_detection_
.HasReceivedValue();
491 QuicTag
QuicConfig::ReceivedLossDetection() const {
492 return loss_detection_
.GetReceivedValue();
495 void QuicConfig::set_idle_connection_state_lifetime(
496 QuicTime::Delta max_idle_connection_state_lifetime
,
497 QuicTime::Delta default_idle_conection_state_lifetime
) {
498 idle_connection_state_lifetime_seconds_
.set(
499 max_idle_connection_state_lifetime
.ToSeconds(),
500 default_idle_conection_state_lifetime
.ToSeconds());
503 QuicTime::Delta
QuicConfig::idle_connection_state_lifetime() const {
504 return QuicTime::Delta::FromSeconds(
505 idle_connection_state_lifetime_seconds_
.GetUint32());
508 QuicTime::Delta
QuicConfig::keepalive_timeout() const {
509 return QuicTime::Delta::FromSeconds(
510 keepalive_timeout_seconds_
.GetUint32());
513 void QuicConfig::set_max_streams_per_connection(size_t max_streams
,
514 size_t default_streams
) {
515 max_streams_per_connection_
.set(max_streams
, default_streams
);
518 uint32
QuicConfig::max_streams_per_connection() const {
519 return max_streams_per_connection_
.GetUint32();
522 void QuicConfig::set_max_time_before_crypto_handshake(
523 QuicTime::Delta max_time_before_crypto_handshake
) {
524 max_time_before_crypto_handshake_
= max_time_before_crypto_handshake
;
527 QuicTime::Delta
QuicConfig::max_time_before_crypto_handshake() const {
528 return max_time_before_crypto_handshake_
;
531 void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window
) {
532 initial_congestion_window_
.SetSendValue(initial_window
);
535 bool QuicConfig::HasReceivedInitialCongestionWindow() const {
536 return initial_congestion_window_
.HasReceivedValue();
539 uint32
QuicConfig::ReceivedInitialCongestionWindow() const {
540 return initial_congestion_window_
.GetReceivedValue();
543 void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt
) {
544 initial_round_trip_time_us_
.SetSendValue(rtt
);
547 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
548 return initial_round_trip_time_us_
.HasReceivedValue();
551 uint32
QuicConfig::ReceivedInitialRoundTripTimeUs() const {
552 return initial_round_trip_time_us_
.GetReceivedValue();
555 bool QuicConfig::HasInitialRoundTripTimeUsToSend() const {
556 return initial_round_trip_time_us_
.HasSendValue();
559 uint32
QuicConfig::GetInitialRoundTripTimeUsToSend() const {
560 return initial_round_trip_time_us_
.GetSendValue();
563 void QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes
) {
564 if (window_bytes
< kDefaultFlowControlSendWindow
) {
565 LOG(DFATAL
) << "Initial flow control receive window (" << window_bytes
566 << ") cannot be set lower than default ("
567 << kDefaultFlowControlSendWindow
<< ").";
568 window_bytes
= kDefaultFlowControlSendWindow
;
570 initial_flow_control_window_bytes_
.SetSendValue(window_bytes
);
573 uint32
QuicConfig::GetInitialFlowControlWindowToSend() const {
574 return initial_flow_control_window_bytes_
.GetSendValue();
577 bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
578 return initial_flow_control_window_bytes_
.HasReceivedValue();
581 uint32
QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
582 return initial_flow_control_window_bytes_
.GetReceivedValue();
585 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes
) {
586 if (window_bytes
< kDefaultFlowControlSendWindow
) {
587 LOG(DFATAL
) << "Initial stream flow control receive window ("
588 << window_bytes
<< ") cannot be set lower than default ("
589 << kDefaultFlowControlSendWindow
<< ").";
590 window_bytes
= kDefaultFlowControlSendWindow
;
592 initial_stream_flow_control_window_bytes_
.SetSendValue(window_bytes
);
595 uint32
QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
596 return initial_stream_flow_control_window_bytes_
.GetSendValue();
599 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
600 return initial_stream_flow_control_window_bytes_
.HasReceivedValue();
603 uint32
QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
604 return initial_stream_flow_control_window_bytes_
.GetReceivedValue();
607 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes
) {
608 if (window_bytes
< kDefaultFlowControlSendWindow
) {
609 LOG(DFATAL
) << "Initial session flow control receive window ("
610 << window_bytes
<< ") cannot be set lower than default ("
611 << kDefaultFlowControlSendWindow
<< ").";
612 window_bytes
= kDefaultFlowControlSendWindow
;
614 initial_session_flow_control_window_bytes_
.SetSendValue(window_bytes
);
617 uint32
QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
618 return initial_session_flow_control_window_bytes_
.GetSendValue();
621 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
622 return initial_session_flow_control_window_bytes_
.HasReceivedValue();
625 uint32
QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
626 return initial_session_flow_control_window_bytes_
.GetReceivedValue();
629 void QuicConfig::SetSocketReceiveBufferToSend(uint32 tcp_receive_window
) {
630 socket_receive_buffer_
.SetSendValue(tcp_receive_window
);
633 uint32
QuicConfig::GetSocketReceiveBufferToSend() const {
634 return socket_receive_buffer_
.GetSendValue();
637 bool QuicConfig::HasReceivedSocketReceiveBuffer() const {
638 return socket_receive_buffer_
.HasReceivedValue();
641 uint32
QuicConfig::ReceivedSocketReceiveBuffer() const {
642 return socket_receive_buffer_
.GetReceivedValue();
645 bool QuicConfig::negotiated() {
646 // TODO(ianswett): Add the negotiated parameters once and iterate over all
647 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
648 // ProcessServerHello.
649 return congestion_feedback_
.negotiated() &&
650 idle_connection_state_lifetime_seconds_
.negotiated() &&
651 keepalive_timeout_seconds_
.negotiated() &&
652 max_streams_per_connection_
.negotiated();
655 void QuicConfig::SetDefaults() {
656 QuicTagVector congestion_feedback
;
657 congestion_feedback
.push_back(kQBIC
);
658 congestion_feedback_
.set(congestion_feedback
, kQBIC
);
659 idle_connection_state_lifetime_seconds_
.set(kMaximumIdleTimeoutSecs
,
660 kDefaultInitialTimeoutSecs
);
661 // kKATO is optional. Return 0 if not negotiated.
662 keepalive_timeout_seconds_
.set(0, 0);
663 set_max_streams_per_connection(kDefaultMaxStreamsPerConnection
,
664 kDefaultMaxStreamsPerConnection
);
665 max_time_before_crypto_handshake_
= QuicTime::Delta::FromSeconds(
666 kDefaultMaxTimeForCryptoHandshakeSecs
);
668 SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow
);
669 SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow
);
670 SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow
);
673 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage
* out
) const {
674 congestion_feedback_
.ToHandshakeMessage(out
);
675 idle_connection_state_lifetime_seconds_
.ToHandshakeMessage(out
);
676 keepalive_timeout_seconds_
.ToHandshakeMessage(out
);
677 max_streams_per_connection_
.ToHandshakeMessage(out
);
678 initial_congestion_window_
.ToHandshakeMessage(out
);
679 initial_round_trip_time_us_
.ToHandshakeMessage(out
);
680 loss_detection_
.ToHandshakeMessage(out
);
681 initial_flow_control_window_bytes_
.ToHandshakeMessage(out
);
682 initial_stream_flow_control_window_bytes_
.ToHandshakeMessage(out
);
683 initial_session_flow_control_window_bytes_
.ToHandshakeMessage(out
);
684 socket_receive_buffer_
.ToHandshakeMessage(out
);
685 connection_options_
.ToHandshakeMessage(out
);
688 QuicErrorCode
QuicConfig::ProcessPeerHello(
689 const CryptoHandshakeMessage
& peer_hello
,
690 HelloType hello_type
,
691 string
* error_details
) {
692 DCHECK(error_details
!= NULL
);
694 QuicErrorCode error
= QUIC_NO_ERROR
;
695 if (error
== QUIC_NO_ERROR
) {
696 error
= congestion_feedback_
.ProcessPeerHello(
697 peer_hello
, hello_type
, error_details
);
699 if (error
== QUIC_NO_ERROR
) {
700 error
= idle_connection_state_lifetime_seconds_
.ProcessPeerHello(
701 peer_hello
, hello_type
, error_details
);
703 if (error
== QUIC_NO_ERROR
) {
704 error
= keepalive_timeout_seconds_
.ProcessPeerHello(
705 peer_hello
, hello_type
, error_details
);
707 if (error
== QUIC_NO_ERROR
) {
708 error
= max_streams_per_connection_
.ProcessPeerHello(
709 peer_hello
, hello_type
, error_details
);
711 if (error
== QUIC_NO_ERROR
) {
712 error
= initial_congestion_window_
.ProcessPeerHello(
713 peer_hello
, hello_type
, error_details
);
715 if (error
== QUIC_NO_ERROR
) {
716 error
= initial_round_trip_time_us_
.ProcessPeerHello(
717 peer_hello
, hello_type
, error_details
);
719 if (error
== QUIC_NO_ERROR
) {
720 error
= initial_flow_control_window_bytes_
.ProcessPeerHello(
721 peer_hello
, hello_type
, error_details
);
723 if (error
== QUIC_NO_ERROR
) {
724 error
= initial_stream_flow_control_window_bytes_
.ProcessPeerHello(
725 peer_hello
, hello_type
, error_details
);
727 if (error
== QUIC_NO_ERROR
) {
728 error
= initial_session_flow_control_window_bytes_
.ProcessPeerHello(
729 peer_hello
, hello_type
, error_details
);
731 if (error
== QUIC_NO_ERROR
) {
732 error
= socket_receive_buffer_
.ProcessPeerHello(
733 peer_hello
, hello_type
, error_details
);
735 if (error
== QUIC_NO_ERROR
) {
736 error
= loss_detection_
.ProcessPeerHello(
737 peer_hello
, hello_type
, error_details
);
739 if (error
== QUIC_NO_ERROR
) {
740 error
= connection_options_
.ProcessPeerHello(
741 peer_hello
, hello_type
, error_details
);