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"
15 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
21 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
22 : QuicNegotiableValue(tag, presence),
27 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
28 DCHECK_LE(default_value, max);
30 default_value_ = default_value;
33 uint32 QuicNegotiableUint32::GetUint32() const {
35 return negotiated_value_;
37 return default_value_;
40 void QuicNegotiableUint32::ToHandshakeMessage(
41 CryptoHandshakeMessage* out) const {
43 out->SetValue(tag_, negotiated_value_);
45 out->SetValue(tag_, max_value_);
49 QuicErrorCode QuicNegotiableUint32::ReadUint32(
50 const CryptoHandshakeMessage& msg,
52 string* error_details) const {
53 DCHECK(error_details != NULL);
54 QuicErrorCode error = msg.GetUint32(tag_, out);
56 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
57 if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
58 *error_details = "Missing " + QuicUtils::TagToString(tag_);
61 error = QUIC_NO_ERROR;
62 *out = default_value_;
67 *error_details = "Bad " + QuicUtils::TagToString(tag_);
73 QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
74 const CryptoHandshakeMessage& client_hello,
75 string* error_details) {
77 DCHECK(error_details != NULL);
79 QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
80 if (error != QUIC_NO_ERROR) {
85 negotiated_value_ = std::min(value, max_value_);
90 QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
91 const CryptoHandshakeMessage& server_hello,
92 string* error_details) {
94 DCHECK(error_details != NULL);
96 QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
97 if (error != QUIC_NO_ERROR) {
101 if (value > max_value_) {
102 *error_details = "Invalid value received for " +
103 QuicUtils::TagToString(tag_);
104 return QUIC_INVALID_NEGOTIATED_VALUE;
108 negotiated_value_ = value;
109 return QUIC_NO_ERROR;
112 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
113 : QuicNegotiableValue(tag, presence) {
116 QuicNegotiableTag::~QuicNegotiableTag() {}
118 void QuicNegotiableTag::set(const QuicTagVector& possible,
119 QuicTag default_value) {
120 DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
122 possible_values_ = possible;
123 default_value_ = default_value;
126 QuicTag QuicNegotiableTag::GetTag() const {
128 return negotiated_tag_;
130 return default_value_;
133 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
135 // Because of the way we serialize and parse handshake messages we can
136 // serialize this as value and still parse it as a vector.
137 out->SetValue(tag_, negotiated_tag_);
139 out->SetVector(tag_, possible_values_);
143 QuicErrorCode QuicNegotiableTag::ReadVector(
144 const CryptoHandshakeMessage& msg,
147 string* error_details) const {
148 DCHECK(error_details != NULL);
149 QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
151 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
152 if (presence_ == PRESENCE_REQUIRED) {
153 *error_details = "Missing " + QuicUtils::TagToString(tag_);
156 error = QUIC_NO_ERROR;
158 *out = &default_value_;
163 *error_details = "Bad " + QuicUtils::TagToString(tag_);
169 QuicErrorCode QuicNegotiableTag::ProcessClientHello(
170 const CryptoHandshakeMessage& client_hello,
171 string* error_details) {
172 DCHECK(!negotiated_);
173 DCHECK(error_details != NULL);
174 const QuicTag* received_tags;
175 size_t received_tags_length;
176 QuicErrorCode error = ReadVector(client_hello, &received_tags,
177 &received_tags_length, error_details);
178 if (error != QUIC_NO_ERROR) {
182 QuicTag negotiated_tag;
183 if (!QuicUtils::FindMutualTag(possible_values_,
185 received_tags_length,
186 QuicUtils::LOCAL_PRIORITY,
189 *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
190 return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
194 negotiated_tag_ = negotiated_tag;
195 return QUIC_NO_ERROR;
198 QuicErrorCode QuicNegotiableTag::ProcessServerHello(
199 const CryptoHandshakeMessage& server_hello,
200 string* error_details) {
201 DCHECK(!negotiated_);
202 DCHECK(error_details != NULL);
203 const QuicTag* received_tags;
204 size_t received_tags_length;
205 QuicErrorCode error = ReadVector(server_hello, &received_tags,
206 &received_tags_length, error_details);
207 if (error != QUIC_NO_ERROR) {
211 if (received_tags_length != 1 ||
212 std::find(possible_values_.begin(), possible_values_.end(),
213 *received_tags) == possible_values_.end()) {
214 *error_details = "Invalid " + QuicUtils::TagToString(tag_);
215 return QUIC_INVALID_NEGOTIATED_VALUE;
219 negotiated_tag_ = *received_tags;
220 return QUIC_NO_ERROR;
223 QuicConfig::QuicConfig() :
224 congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED),
225 idle_connection_state_lifetime_seconds_(
226 kICSL, QuicNegotiableValue::PRESENCE_REQUIRED),
227 keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL),
228 max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED),
229 max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
230 server_initial_congestion_window_(
231 kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
232 server_max_packet_size_(kSMSS, QuicNegotiableValue::PRESENCE_OPTIONAL),
233 initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
234 // All optional non-zero parameters should be initialized here.
235 server_initial_congestion_window_.set(kMaxInitialWindow,
236 kDefaultInitialWindow);
237 server_max_packet_size_.set(kMaxPacketSize, kDefaultMaxPacketSize);
240 QuicConfig::~QuicConfig() {}
242 void QuicConfig::set_congestion_control(
243 const QuicTagVector& congestion_control,
244 QuicTag default_congestion_control) {
245 congestion_control_.set(congestion_control, default_congestion_control);
248 QuicTag QuicConfig::congestion_control() const {
249 return congestion_control_.GetTag();
252 void QuicConfig::set_idle_connection_state_lifetime(
253 QuicTime::Delta max_idle_connection_state_lifetime,
254 QuicTime::Delta default_idle_conection_state_lifetime) {
255 idle_connection_state_lifetime_seconds_.set(
256 max_idle_connection_state_lifetime.ToSeconds(),
257 default_idle_conection_state_lifetime.ToSeconds());
260 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
261 return QuicTime::Delta::FromSeconds(
262 idle_connection_state_lifetime_seconds_.GetUint32());
265 QuicTime::Delta QuicConfig::keepalive_timeout() const {
266 return QuicTime::Delta::FromSeconds(
267 keepalive_timeout_seconds_.GetUint32());
270 void QuicConfig::set_max_streams_per_connection(size_t max_streams,
271 size_t default_streams) {
272 max_streams_per_connection_.set(max_streams, default_streams);
275 uint32 QuicConfig::max_streams_per_connection() const {
276 return max_streams_per_connection_.GetUint32();
279 void QuicConfig::set_max_time_before_crypto_handshake(
280 QuicTime::Delta max_time_before_crypto_handshake) {
281 max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
284 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
285 return max_time_before_crypto_handshake_;
288 void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window,
289 size_t default_initial_window) {
290 server_initial_congestion_window_.set(max_initial_window,
291 default_initial_window);
294 uint32 QuicConfig::server_initial_congestion_window() const {
295 return server_initial_congestion_window_.GetUint32();
298 void QuicConfig::set_server_max_packet_size(size_t max_bytes,
299 size_t default_bytes) {
300 server_max_packet_size_.set(max_bytes, default_bytes);
303 uint32 QuicConfig::server_max_packet_size() const {
304 return server_max_packet_size_.GetUint32();
307 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
308 size_t default_rtt) {
309 initial_round_trip_time_us_.set(max_rtt, default_rtt);
312 uint32 QuicConfig::initial_round_trip_time_us() const {
313 return initial_round_trip_time_us_.GetUint32();
316 bool QuicConfig::negotiated() {
317 // TODO(ianswett): Add the negotiated parameters once and iterate over all
318 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
319 // ProcessServerHello.
320 return congestion_control_.negotiated() &&
321 idle_connection_state_lifetime_seconds_.negotiated() &&
322 keepalive_timeout_seconds_.negotiated() &&
323 max_streams_per_connection_.negotiated() &&
324 server_initial_congestion_window_.negotiated() &&
325 server_max_packet_size_.negotiated() &&
326 initial_round_trip_time_us_.negotiated();
329 void QuicConfig::SetDefaults() {
330 congestion_control_.set(QuicTagVector(1, kQBIC), kQBIC);
331 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
332 kDefaultInitialTimeoutSecs);
333 // kKATO is optional. Return 0 if not negotiated.
334 keepalive_timeout_seconds_.set(0, 0);
335 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
336 kDefaultMaxStreamsPerConnection);
337 max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
338 kDefaultMaxTimeForCryptoHandshakeSecs);
339 server_initial_congestion_window_.set(kMaxInitialWindow,
340 kDefaultInitialWindow);
341 server_max_packet_size_.set(kMaxPacketSize, kDefaultMaxPacketSize);
344 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
345 congestion_control_.ToHandshakeMessage(out);
346 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
347 keepalive_timeout_seconds_.ToHandshakeMessage(out);
348 max_streams_per_connection_.ToHandshakeMessage(out);
349 server_initial_congestion_window_.ToHandshakeMessage(out);
350 server_max_packet_size_.ToHandshakeMessage(out);
351 // TODO(ianswett): Don't transmit parameters which are optional and not set.
352 initial_round_trip_time_us_.ToHandshakeMessage(out);
355 QuicErrorCode QuicConfig::ProcessClientHello(
356 const CryptoHandshakeMessage& client_hello,
357 string* error_details) {
358 DCHECK(error_details != NULL);
360 QuicErrorCode error = QUIC_NO_ERROR;
361 if (error == QUIC_NO_ERROR) {
362 error = congestion_control_.ProcessClientHello(client_hello, error_details);
364 if (error == QUIC_NO_ERROR) {
365 error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
366 client_hello, error_details);
368 if (error == QUIC_NO_ERROR) {
369 error = keepalive_timeout_seconds_.ProcessClientHello(
370 client_hello, error_details);
372 if (error == QUIC_NO_ERROR) {
373 error = max_streams_per_connection_.ProcessClientHello(
374 client_hello, error_details);
376 if (error == QUIC_NO_ERROR) {
377 error = server_initial_congestion_window_.ProcessClientHello(
378 client_hello, error_details);
380 if (error == QUIC_NO_ERROR) {
381 error = server_max_packet_size_.ProcessClientHello(
382 client_hello, error_details);
384 if (error == QUIC_NO_ERROR) {
385 error = initial_round_trip_time_us_.ProcessClientHello(
386 client_hello, error_details);
391 QuicErrorCode QuicConfig::ProcessServerHello(
392 const CryptoHandshakeMessage& server_hello,
393 string* error_details) {
394 DCHECK(error_details != NULL);
396 QuicErrorCode error = QUIC_NO_ERROR;
397 if (error == QUIC_NO_ERROR) {
398 error = congestion_control_.ProcessServerHello(server_hello, error_details);
400 if (error == QUIC_NO_ERROR) {
401 error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
402 server_hello, error_details);
404 if (error == QUIC_NO_ERROR) {
405 error = keepalive_timeout_seconds_.ProcessServerHello(
406 server_hello, error_details);
408 if (error == QUIC_NO_ERROR) {
409 error = max_streams_per_connection_.ProcessServerHello(
410 server_hello, error_details);
412 if (error == QUIC_NO_ERROR) {
413 error = server_initial_congestion_window_.ProcessServerHello(
414 server_hello, error_details);
416 if (error == QUIC_NO_ERROR) {
417 error = server_max_packet_size_.ProcessServerHello(
418 server_hello, error_details);
420 if (error == QUIC_NO_ERROR) {
421 error = initial_round_trip_time_us_.ProcessServerHello(
422 server_hello, error_details);