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. 4 5 #include "net/quic/quic_config.h" 6 7 #include <algorithm> 8 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" 15 16 using std::min; 17 using std::string; 18 19 namespace net { 20 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, 25 QuicTag tag, 26 QuicConfigPresence presence, 27 uint32 default_value, 28 uint32* out, 29 string* error_details) { 30 DCHECK(error_details != NULL); 31 QuicErrorCode error = msg.GetUint32(tag, out); 32 switch (error) { 33 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 34 if (presence == PRESENCE_REQUIRED) { 35 *error_details = "Missing " + QuicUtils::TagToString(tag); 36 break; 37 } 38 error = QUIC_NO_ERROR; 39 *out = default_value; 40 break; 41 case QUIC_NO_ERROR: 42 break; 43 default: 44 *error_details = "Bad " + QuicUtils::TagToString(tag); 45 break; 46 } 47 return error; 48 } 49 50 51 QuicConfigValue::QuicConfigValue(QuicTag tag, 52 QuicConfigPresence presence) 53 : tag_(tag), 54 presence_(presence) { 55 } 56 QuicConfigValue::~QuicConfigValue() {} 57 58 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, 59 QuicConfigPresence presence) 60 : QuicConfigValue(tag, presence), 61 negotiated_(false) { 62 } 63 QuicNegotiableValue::~QuicNegotiableValue() {} 64 65 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, 66 QuicConfigPresence presence) 67 : QuicNegotiableValue(tag, presence), 68 max_value_(0), 69 default_value_(0) { 70 } 71 QuicNegotiableUint32::~QuicNegotiableUint32() {} 72 73 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) { 74 DCHECK_LE(default_value, max); 75 max_value_ = max; 76 default_value_ = default_value; 77 } 78 79 uint32 QuicNegotiableUint32::GetUint32() const { 80 if (negotiated_) { 81 return negotiated_value_; 82 } 83 return default_value_; 84 } 85 86 void QuicNegotiableUint32::ToHandshakeMessage( 87 CryptoHandshakeMessage* out) const { 88 if (negotiated_) { 89 out->SetValue(tag_, negotiated_value_); 90 } else { 91 out->SetValue(tag_, max_value_); 92 } 93 } 94 95 QuicErrorCode QuicNegotiableUint32::ProcessPeerHello( 96 const CryptoHandshakeMessage& peer_hello, 97 HelloType hello_type, 98 string* error_details) { 99 DCHECK(!negotiated_); 100 DCHECK(error_details != NULL); 101 uint32 value; 102 QuicErrorCode error = ReadUint32(peer_hello, 103 tag_, 104 presence_, 105 default_value_, 106 &value, 107 error_details); 108 if (error != QUIC_NO_ERROR) { 109 return error; 110 } 111 if (hello_type == SERVER && value > max_value_) { 112 *error_details = 113 "Invalid value received for " + QuicUtils::TagToString(tag_); 114 return QUIC_INVALID_NEGOTIATED_VALUE; 115 } 116 117 negotiated_ = true; 118 negotiated_value_ = min(value, max_value_); 119 return QUIC_NO_ERROR; 120 } 121 122 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence) 123 : QuicNegotiableValue(tag, presence), 124 negotiated_tag_(0), 125 default_value_(0) { 126 } 127 128 QuicNegotiableTag::~QuicNegotiableTag() {} 129 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; 135 } 136 137 QuicTag QuicNegotiableTag::GetTag() const { 138 if (negotiated_) { 139 return negotiated_tag_; 140 } 141 return default_value_; 142 } 143 144 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 145 if (negotiated_) { 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_); 149 } else { 150 out->SetVector(tag_, possible_values_); 151 } 152 } 153 154 QuicErrorCode QuicNegotiableTag::ReadVector( 155 const CryptoHandshakeMessage& msg, 156 const QuicTag** out, 157 size_t* out_length, 158 string* error_details) const { 159 DCHECK(error_details != NULL); 160 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length); 161 switch (error) { 162 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 163 if (presence_ == PRESENCE_REQUIRED) { 164 *error_details = "Missing " + QuicUtils::TagToString(tag_); 165 break; 166 } 167 error = QUIC_NO_ERROR; 168 *out_length = 1; 169 *out = &default_value_; 170 171 case QUIC_NO_ERROR: 172 break; 173 default: 174 *error_details = "Bad " + QuicUtils::TagToString(tag_); 175 break; 176 } 177 return error; 178 } 179 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) { 191 return error; 192 } 193 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; 199 } 200 negotiated_tag_ = *received_tags; 201 } else { 202 QuicTag negotiated_tag; 203 if (!QuicUtils::FindMutualTag(possible_values_, 204 received_tags, 205 received_tags_length, 206 QuicUtils::LOCAL_PRIORITY, 207 &negotiated_tag, 208 NULL)) { 209 *error_details = "Unsupported " + QuicUtils::TagToString(tag_); 210 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP; 211 } 212 negotiated_tag_ = negotiated_tag; 213 } 214 215 negotiated_ = true; 216 return QUIC_NO_ERROR; 217 } 218 219 QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence) 220 : QuicConfigValue(tag, presence), 221 has_send_value_(false), 222 has_receive_value_(false) { 223 } 224 QuicFixedUint32::~QuicFixedUint32() {} 225 226 bool QuicFixedUint32::HasSendValue() const { 227 return has_send_value_; 228 } 229 230 uint32 QuicFixedUint32::GetSendValue() const { 231 LOG_IF(DFATAL, !has_send_value_) 232 << "No send value to get for tag:" << QuicUtils::TagToString(tag_); 233 return send_value_; 234 } 235 236 void QuicFixedUint32::SetSendValue(uint32 value) { 237 has_send_value_ = true; 238 send_value_ = value; 239 } 240 241 bool QuicFixedUint32::HasReceivedValue() const { 242 return has_receive_value_; 243 } 244 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_; 249 } 250 251 void QuicFixedUint32::SetReceivedValue(uint32 value) { 252 has_receive_value_ = true; 253 receive_value_ = value; 254 } 255 256 void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 257 if (has_send_value_) { 258 out->SetValue(tag_, send_value_); 259 } 260 } 261 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_); 268 switch (error) { 269 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 270 if (presence_ == PRESENCE_OPTIONAL) { 271 return QUIC_NO_ERROR; 272 } 273 *error_details = "Missing " + QuicUtils::TagToString(tag_); 274 break; 275 case QUIC_NO_ERROR: 276 has_receive_value_ = true; 277 break; 278 default: 279 *error_details = "Bad " + QuicUtils::TagToString(tag_); 280 break; 281 } 282 return error; 283 } 284 285 QuicFixedTag::QuicFixedTag(QuicTag name, 286 QuicConfigPresence presence) 287 : QuicConfigValue(name, presence), 288 has_send_value_(false), 289 has_receive_value_(false) { 290 } 291 292 QuicFixedTag::~QuicFixedTag() {} 293 294 bool QuicFixedTag::HasSendValue() const { 295 return has_send_value_; 296 } 297 298 uint32 QuicFixedTag::GetSendValue() const { 299 LOG_IF(DFATAL, !has_send_value_) 300 << "No send value to get for tag:" << QuicUtils::TagToString(tag_); 301 return send_value_; 302 } 303 304 void QuicFixedTag::SetSendValue(uint32 value) { 305 has_send_value_ = true; 306 send_value_ = value; 307 } 308 309 bool QuicFixedTag::HasReceivedValue() const { 310 return has_receive_value_; 311 } 312 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_; 317 } 318 319 void QuicFixedTag::SetReceivedValue(uint32 value) { 320 has_receive_value_ = true; 321 receive_value_ = value; 322 } 323 324 void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 325 if (has_send_value_) { 326 out->SetValue(tag_, send_value_); 327 } 328 } 329 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_); 336 switch (error) { 337 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 338 if (presence_ == PRESENCE_OPTIONAL) { 339 return QUIC_NO_ERROR; 340 } 341 *error_details = "Missing " + QuicUtils::TagToString(tag_); 342 break; 343 case QUIC_NO_ERROR: 344 has_receive_value_ = true; 345 break; 346 default: 347 *error_details = "Bad " + QuicUtils::TagToString(tag_); 348 break; 349 } 350 return error; 351 } 352 353 QuicFixedTagVector::QuicFixedTagVector(QuicTag name, 354 QuicConfigPresence presence) 355 : QuicConfigValue(name, presence), 356 has_send_values_(false), 357 has_receive_values_(false) { 358 } 359 360 QuicFixedTagVector::~QuicFixedTagVector() {} 361 362 bool QuicFixedTagVector::HasSendValues() const { 363 return has_send_values_; 364 } 365 366 QuicTagVector QuicFixedTagVector::GetSendValues() const { 367 LOG_IF(DFATAL, !has_send_values_) 368 << "No send values to get for tag:" << QuicUtils::TagToString(tag_); 369 return send_values_; 370 } 371 372 void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) { 373 has_send_values_ = true; 374 send_values_ = values; 375 } 376 377 bool QuicFixedTagVector::HasReceivedValues() const { 378 return has_receive_values_; 379 } 380 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_; 385 } 386 387 void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) { 388 has_receive_values_ = true; 389 receive_values_ = values; 390 } 391 392 void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 393 if (has_send_values_) { 394 out->SetVector(tag_, send_values_); 395 } 396 } 397 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); 407 switch (error) { 408 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND: 409 if (presence_ == PRESENCE_OPTIONAL) { 410 return QUIC_NO_ERROR; 411 } 412 *error_details = "Missing " + QuicUtils::TagToString(tag_); 413 break; 414 case QUIC_NO_ERROR: 415 has_receive_values_ = true; 416 for (size_t i = 0; i < received_tags_length; ++i) { 417 receive_values_.push_back(received_tags[i]); 418 } 419 break; 420 default: 421 *error_details = "Bad " + QuicUtils::TagToString(tag_); 422 break; 423 } 424 return error; 425 } 426 427 QuicConfig::QuicConfig() 428 : congestion_feedback_(kCGST, PRESENCE_REQUIRED), 429 congestion_options_(kCOPT, PRESENCE_OPTIONAL), 430 loss_detection_(kLOSS, PRESENCE_OPTIONAL), 431 idle_connection_state_lifetime_seconds_(kICSL, PRESENCE_REQUIRED), 432 keepalive_timeout_seconds_(kKATO, PRESENCE_OPTIONAL), 433 max_streams_per_connection_(kMSPC, PRESENCE_REQUIRED), 434 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()), 435 initial_congestion_window_(kSWND, PRESENCE_OPTIONAL), 436 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL), 437 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring 438 // QUIC_VERSION_17. 439 initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL), 440 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring 441 // QUIC_VERSION_19. 442 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL), 443 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring 444 // QUIC_VERSION_19. 445 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL) { 446 } 447 448 QuicConfig::~QuicConfig() {} 449 450 void QuicConfig::set_congestion_feedback( 451 const QuicTagVector& congestion_feedback, 452 QuicTag default_congestion_feedback) { 453 congestion_feedback_.set(congestion_feedback, default_congestion_feedback); 454 } 455 456 QuicTag QuicConfig::congestion_feedback() const { 457 return congestion_feedback_.GetTag(); 458 } 459 460 void QuicConfig::SetCongestionOptionsToSend( 461 const QuicTagVector& congestion_options) { 462 congestion_options_.SetSendValues(congestion_options); 463 } 464 465 bool QuicConfig::HasReceivedCongestionOptions() const { 466 return congestion_options_.HasReceivedValues(); 467 } 468 469 QuicTagVector QuicConfig::ReceivedCongestionOptions() const { 470 return congestion_options_.GetReceivedValues(); 471 } 472 473 void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) { 474 loss_detection_.SetSendValue(loss_detection); 475 } 476 477 bool QuicConfig::HasReceivedLossDetection() const { 478 return loss_detection_.HasReceivedValue(); 479 } 480 481 QuicTag QuicConfig::ReceivedLossDetection() const { 482 return loss_detection_.GetReceivedValue(); 483 } 484 485 void QuicConfig::set_idle_connection_state_lifetime( 486 QuicTime::Delta max_idle_connection_state_lifetime, 487 QuicTime::Delta default_idle_conection_state_lifetime) { 488 idle_connection_state_lifetime_seconds_.set( 489 max_idle_connection_state_lifetime.ToSeconds(), 490 default_idle_conection_state_lifetime.ToSeconds()); 491 } 492 493 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const { 494 return QuicTime::Delta::FromSeconds( 495 idle_connection_state_lifetime_seconds_.GetUint32()); 496 } 497 498 QuicTime::Delta QuicConfig::keepalive_timeout() const { 499 return QuicTime::Delta::FromSeconds( 500 keepalive_timeout_seconds_.GetUint32()); 501 } 502 503 void QuicConfig::set_max_streams_per_connection(size_t max_streams, 504 size_t default_streams) { 505 max_streams_per_connection_.set(max_streams, default_streams); 506 } 507 508 uint32 QuicConfig::max_streams_per_connection() const { 509 return max_streams_per_connection_.GetUint32(); 510 } 511 512 void QuicConfig::set_max_time_before_crypto_handshake( 513 QuicTime::Delta max_time_before_crypto_handshake) { 514 max_time_before_crypto_handshake_ = max_time_before_crypto_handshake; 515 } 516 517 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const { 518 return max_time_before_crypto_handshake_; 519 } 520 521 void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) { 522 initial_congestion_window_.SetSendValue(initial_window); 523 } 524 525 bool QuicConfig::HasReceivedInitialCongestionWindow() const { 526 return initial_congestion_window_.HasReceivedValue(); 527 } 528 529 uint32 QuicConfig::ReceivedInitialCongestionWindow() const { 530 return initial_congestion_window_.GetReceivedValue(); 531 } 532 533 void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) { 534 initial_round_trip_time_us_.SetSendValue(rtt); 535 } 536 537 bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const { 538 return initial_round_trip_time_us_.HasReceivedValue(); 539 } 540 541 uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const { 542 return initial_round_trip_time_us_.GetReceivedValue(); 543 } 544 545 void QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) { 546 if (window_bytes < kDefaultFlowControlSendWindow) { 547 LOG(DFATAL) << "Initial flow control receive window (" << window_bytes 548 << ") cannot be set lower than default (" 549 << kDefaultFlowControlSendWindow << ")."; 550 window_bytes = kDefaultFlowControlSendWindow; 551 } 552 initial_flow_control_window_bytes_.SetSendValue(window_bytes); 553 } 554 555 uint32 QuicConfig::GetInitialFlowControlWindowToSend() const { 556 return initial_flow_control_window_bytes_.GetSendValue(); 557 } 558 559 bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const { 560 return initial_flow_control_window_bytes_.HasReceivedValue(); 561 } 562 563 uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const { 564 return initial_flow_control_window_bytes_.GetReceivedValue(); 565 } 566 567 void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) { 568 if (window_bytes < kDefaultFlowControlSendWindow) { 569 LOG(DFATAL) << "Initial stream flow control receive window (" 570 << window_bytes << ") cannot be set lower than default (" 571 << kDefaultFlowControlSendWindow << ")."; 572 window_bytes = kDefaultFlowControlSendWindow; 573 } 574 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes); 575 } 576 577 uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const { 578 return initial_stream_flow_control_window_bytes_.GetSendValue(); 579 } 580 581 bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const { 582 return initial_stream_flow_control_window_bytes_.HasReceivedValue(); 583 } 584 585 uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const { 586 return initial_stream_flow_control_window_bytes_.GetReceivedValue(); 587 } 588 589 void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) { 590 if (window_bytes < kDefaultFlowControlSendWindow) { 591 LOG(DFATAL) << "Initial session flow control receive window (" 592 << window_bytes << ") cannot be set lower than default (" 593 << kDefaultFlowControlSendWindow << ")."; 594 window_bytes = kDefaultFlowControlSendWindow; 595 } 596 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes); 597 } 598 599 uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const { 600 return initial_session_flow_control_window_bytes_.GetSendValue(); 601 } 602 603 bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const { 604 return initial_session_flow_control_window_bytes_.HasReceivedValue(); 605 } 606 607 uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const { 608 return initial_session_flow_control_window_bytes_.GetReceivedValue(); 609 } 610 611 bool QuicConfig::negotiated() { 612 // TODO(ianswett): Add the negotiated parameters once and iterate over all 613 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and 614 // ProcessServerHello. 615 return congestion_feedback_.negotiated() && 616 idle_connection_state_lifetime_seconds_.negotiated() && 617 keepalive_timeout_seconds_.negotiated() && 618 max_streams_per_connection_.negotiated(); 619 } 620 621 void QuicConfig::SetDefaults() { 622 QuicTagVector congestion_feedback; 623 if (FLAGS_enable_quic_pacing) { 624 congestion_feedback.push_back(kPACE); 625 } 626 congestion_feedback.push_back(kQBIC); 627 congestion_feedback_.set(congestion_feedback, kQBIC); 628 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs, 629 kDefaultInitialTimeoutSecs); 630 // kKATO is optional. Return 0 if not negotiated. 631 keepalive_timeout_seconds_.set(0, 0); 632 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection, 633 kDefaultMaxStreamsPerConnection); 634 max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds( 635 kDefaultMaxTimeForCryptoHandshakeSecs); 636 637 SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow); 638 SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow); 639 SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow); 640 } 641 642 void QuicConfig::EnablePacing(bool enable_pacing) { 643 QuicTagVector congestion_feedback; 644 if (enable_pacing) { 645 congestion_feedback.push_back(kPACE); 646 } 647 congestion_feedback.push_back(kQBIC); 648 congestion_feedback_.set(congestion_feedback, kQBIC); 649 } 650 651 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const { 652 congestion_feedback_.ToHandshakeMessage(out); 653 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out); 654 keepalive_timeout_seconds_.ToHandshakeMessage(out); 655 max_streams_per_connection_.ToHandshakeMessage(out); 656 initial_congestion_window_.ToHandshakeMessage(out); 657 initial_round_trip_time_us_.ToHandshakeMessage(out); 658 loss_detection_.ToHandshakeMessage(out); 659 initial_flow_control_window_bytes_.ToHandshakeMessage(out); 660 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out); 661 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out); 662 congestion_options_.ToHandshakeMessage(out); 663 } 664 665 QuicErrorCode QuicConfig::ProcessPeerHello( 666 const CryptoHandshakeMessage& peer_hello, 667 HelloType hello_type, 668 string* error_details) { 669 DCHECK(error_details != NULL); 670 671 QuicErrorCode error = QUIC_NO_ERROR; 672 if (error == QUIC_NO_ERROR) { 673 error = congestion_feedback_.ProcessPeerHello( 674 peer_hello, hello_type, error_details); 675 } 676 if (error == QUIC_NO_ERROR) { 677 error = idle_connection_state_lifetime_seconds_.ProcessPeerHello( 678 peer_hello, hello_type, error_details); 679 } 680 if (error == QUIC_NO_ERROR) { 681 error = keepalive_timeout_seconds_.ProcessPeerHello( 682 peer_hello, hello_type, error_details); 683 } 684 if (error == QUIC_NO_ERROR) { 685 error = max_streams_per_connection_.ProcessPeerHello( 686 peer_hello, hello_type, error_details); 687 } 688 if (error == QUIC_NO_ERROR) { 689 error = initial_congestion_window_.ProcessPeerHello( 690 peer_hello, hello_type, error_details); 691 } 692 if (error == QUIC_NO_ERROR) { 693 error = initial_round_trip_time_us_.ProcessPeerHello( 694 peer_hello, hello_type, error_details); 695 } 696 if (error == QUIC_NO_ERROR) { 697 error = initial_flow_control_window_bytes_.ProcessPeerHello( 698 peer_hello, hello_type, error_details); 699 } 700 if (error == QUIC_NO_ERROR) { 701 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello( 702 peer_hello, hello_type, error_details); 703 } 704 if (error == QUIC_NO_ERROR) { 705 error = initial_session_flow_control_window_bytes_.ProcessPeerHello( 706 peer_hello, hello_type, error_details); 707 } 708 if (error == QUIC_NO_ERROR) { 709 error = loss_detection_.ProcessPeerHello( 710 peer_hello, hello_type, error_details); 711 } 712 if (error == QUIC_NO_ERROR) { 713 error = congestion_options_.ProcessPeerHello( 714 peer_hello, hello_type, error_details); 715 } 716 return error; 717 } 718 719 } // namespace net 720