blob: 90579d3a03f3bdcb8ffe169516943823ab8650f1 [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// 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
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01007#include <algorithm>
8
9#include "base/logging.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000010#include "net/quic/crypto/crypto_handshake_message.h"
11#include "net/quic/crypto/crypto_protocol.h"
Ben Murdoche5d81f52014-04-03 12:29:45 +010012#include "net/quic/quic_flags.h"
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000013#include "net/quic/quic_sent_packet_manager.h"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000014#include "net/quic/quic_utils.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010015
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000016using std::min;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010017using std::string;
18
19namespace net {
20
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000021// 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|.
24QuicErrorCode 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;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010048}
49
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000050
51QuicConfigValue::QuicConfigValue(QuicTag tag,
52 QuicConfigPresence presence)
53 : tag_(tag),
54 presence_(presence) {
55}
56QuicConfigValue::~QuicConfigValue() {}
57
58QuicNegotiableValue::QuicNegotiableValue(QuicTag tag,
59 QuicConfigPresence presence)
60 : QuicConfigValue(tag, presence),
61 negotiated_(false) {
62}
63QuicNegotiableValue::~QuicNegotiableValue() {}
64
65QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag,
66 QuicConfigPresence presence)
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +000067 : QuicNegotiableValue(tag, presence),
68 max_value_(0),
69 default_value_(0) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010070}
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000071QuicNegotiableUint32::~QuicNegotiableUint32() {}
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010072
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010073void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
74 DCHECK_LE(default_value, max);
75 max_value_ = max;
76 default_value_ = default_value;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010077}
78
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010079uint32 QuicNegotiableUint32::GetUint32() const {
80 if (negotiated_) {
81 return negotiated_value_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010082 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010083 return default_value_;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010084}
85
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010086void QuicNegotiableUint32::ToHandshakeMessage(
87 CryptoHandshakeMessage* out) const {
88 if (negotiated_) {
89 out->SetValue(tag_, negotiated_value_);
90 } else {
91 out->SetValue(tag_, max_value_);
92 }
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010093}
94
Ben Murdoch0529e5d2014-04-24 10:50:13 +010095QuicErrorCode QuicNegotiableUint32::ProcessPeerHello(
96 const CryptoHandshakeMessage& peer_hello,
97 HelloType hello_type,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010098 string* error_details) {
99 DCHECK(!negotiated_);
100 DCHECK(error_details != NULL);
101 uint32 value;
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100102 QuicErrorCode error = ReadUint32(peer_hello,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000103 tag_,
104 presence_,
105 default_value_,
106 &value,
107 error_details);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100108 if (error != QUIC_NO_ERROR) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100109 return error;
110 }
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100111 if (hello_type == SERVER && value > max_value_) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100112 *error_details =
113 "Invalid value received for " + QuicUtils::TagToString(tag_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100114 return QUIC_INVALID_NEGOTIATED_VALUE;
115 }
116
117 negotiated_ = true;
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100118 negotiated_value_ = min(value, max_value_);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100119 return QUIC_NO_ERROR;
120}
121
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000122QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, QuicConfigPresence presence)
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000123 : QuicNegotiableValue(tag, presence),
124 negotiated_tag_(0),
125 default_value_(0) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100126}
127
128QuicNegotiableTag::~QuicNegotiableTag() {}
129
130void QuicNegotiableTag::set(const QuicTagVector& possible,
131 QuicTag default_value) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100132 DCHECK(ContainsQuicTag(possible, default_value));
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100133 possible_values_ = possible;
134 default_value_ = default_value;
135}
136
137QuicTag QuicNegotiableTag::GetTag() const {
138 if (negotiated_) {
139 return negotiated_tag_;
140 }
141 return default_value_;
142}
143
144void 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
154QuicErrorCode 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
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100180QuicErrorCode QuicNegotiableTag::ProcessPeerHello(
181 const CryptoHandshakeMessage& peer_hello,
182 HelloType hello_type,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100183 string* error_details) {
184 DCHECK(!negotiated_);
185 DCHECK(error_details != NULL);
186 const QuicTag* received_tags;
187 size_t received_tags_length;
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100188 QuicErrorCode error = ReadVector(peer_hello, &received_tags,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100189 &received_tags_length, error_details);
190 if (error != QUIC_NO_ERROR) {
191 return error;
192 }
193
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100194 if (hello_type == SERVER) {
195 if (received_tags_length != 1 ||
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100196 !ContainsQuicTag(possible_values_, *received_tags)) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100197 *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;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100213 }
214
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100215 negotiated_ = true;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100216 return QUIC_NO_ERROR;
217}
218
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100219QuicFixedUint32::QuicFixedUint32(QuicTag tag, QuicConfigPresence presence)
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000220 : QuicConfigValue(tag, presence),
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100221 has_send_value_(false),
222 has_receive_value_(false) {
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000223}
224QuicFixedUint32::~QuicFixedUint32() {}
225
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100226bool QuicFixedUint32::HasSendValue() const {
227 return has_send_value_;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000228}
229
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100230uint32 QuicFixedUint32::GetSendValue() const {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100231 LOG_IF(DFATAL, !has_send_value_)
232 << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100233 return send_value_;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000234}
235
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100236void QuicFixedUint32::SetSendValue(uint32 value) {
237 has_send_value_ = true;
238 send_value_ = value;
239}
240
241bool QuicFixedUint32::HasReceivedValue() const {
242 return has_receive_value_;
243}
244
245uint32 QuicFixedUint32::GetReceivedValue() const {
246 LOG_IF(DFATAL, !has_receive_value_)
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100247 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100248 return receive_value_;
249}
250
251void QuicFixedUint32::SetReceivedValue(uint32 value) {
252 has_receive_value_ = true;
253 receive_value_ = value;
254}
255
256void QuicFixedUint32::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
257 if (has_send_value_) {
258 out->SetValue(tag_, send_value_);
259 }
260}
261
262QuicErrorCode 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:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100270 if (presence_ == PRESENCE_OPTIONAL) {
271 return QUIC_NO_ERROR;
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100272 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100273 *error_details = "Missing " + QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100274 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
285QuicFixedTag::QuicFixedTag(QuicTag name,
286 QuicConfigPresence presence)
287 : QuicConfigValue(name, presence),
288 has_send_value_(false),
289 has_receive_value_(false) {
290}
291
292QuicFixedTag::~QuicFixedTag() {}
293
294bool QuicFixedTag::HasSendValue() const {
295 return has_send_value_;
296}
297
298uint32 QuicFixedTag::GetSendValue() const {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100299 LOG_IF(DFATAL, !has_send_value_)
300 << "No send value to get for tag:" << QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100301 return send_value_;
302}
303
304void QuicFixedTag::SetSendValue(uint32 value) {
305 has_send_value_ = true;
306 send_value_ = value;
307}
308
309bool QuicFixedTag::HasReceivedValue() const {
310 return has_receive_value_;
311}
312
313uint32 QuicFixedTag::GetReceivedValue() const {
314 LOG_IF(DFATAL, !has_receive_value_)
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100315 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100316 return receive_value_;
317}
318
319void QuicFixedTag::SetReceivedValue(uint32 value) {
320 has_receive_value_ = true;
321 receive_value_ = value;
322}
323
324void QuicFixedTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
325 if (has_send_value_) {
326 out->SetValue(tag_, send_value_);
327 }
328}
329
330QuicErrorCode QuicFixedTag::ProcessPeerHello(
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100331 const CryptoHandshakeMessage& peer_hello,
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100332 HelloType hello_type,
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000333 string* error_details) {
334 DCHECK(error_details != NULL);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100335 QuicErrorCode error = peer_hello.GetUint32(tag_, &receive_value_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100336 switch (error) {
337 case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100338 if (presence_ == PRESENCE_OPTIONAL) {
339 return QUIC_NO_ERROR;
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100340 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100341 *error_details = "Missing " + QuicUtils::TagToString(tag_);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100342 break;
343 case QUIC_NO_ERROR:
344 has_receive_value_ = true;
345 break;
346 default:
347 *error_details = "Bad " + QuicUtils::TagToString(tag_);
348 break;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000349 }
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100350 return error;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000351}
352
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100353QuicFixedTagVector::QuicFixedTagVector(QuicTag name,
354 QuicConfigPresence presence)
355 : QuicConfigValue(name, presence),
356 has_send_values_(false),
357 has_receive_values_(false) {
358}
359
360QuicFixedTagVector::~QuicFixedTagVector() {}
361
362bool QuicFixedTagVector::HasSendValues() const {
363 return has_send_values_;
364}
365
366QuicTagVector QuicFixedTagVector::GetSendValues() const {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100367 LOG_IF(DFATAL, !has_send_values_)
368 << "No send values to get for tag:" << QuicUtils::TagToString(tag_);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100369 return send_values_;
370}
371
372void QuicFixedTagVector::SetSendValues(const QuicTagVector& values) {
373 has_send_values_ = true;
374 send_values_ = values;
375}
376
377bool QuicFixedTagVector::HasReceivedValues() const {
378 return has_receive_values_;
379}
380
381QuicTagVector QuicFixedTagVector::GetReceivedValues() const {
382 LOG_IF(DFATAL, !has_receive_values_)
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100383 << "No receive value to get for tag:" << QuicUtils::TagToString(tag_);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100384 return receive_values_;
385}
386
387void QuicFixedTagVector::SetReceivedValues(const QuicTagVector& values) {
388 has_receive_values_ = true;
389 receive_values_ = values;
390}
391
392void QuicFixedTagVector::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
393 if (has_send_values_) {
394 out->SetVector(tag_, send_values_);
395 }
396}
397
398QuicErrorCode 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:
Ben Murdoch116680a2014-07-20 18:25:52 -0700415 DVLOG(1) << "Received Connection Option tags from receiver.";
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100416 has_receive_values_ = true;
417 for (size_t i = 0; i < received_tags_length; ++i) {
418 receive_values_.push_back(received_tags[i]);
419 }
420 break;
421 default:
422 *error_details = "Bad " + QuicUtils::TagToString(tag_);
423 break;
424 }
425 return error;
426}
427
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000428QuicConfig::QuicConfig()
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100429 : congestion_feedback_(kCGST, PRESENCE_REQUIRED),
Ben Murdoch116680a2014-07-20 18:25:52 -0700430 connection_options_(kCOPT, PRESENCE_OPTIONAL),
Ben Murdoche5d81f52014-04-03 12:29:45 +0100431 loss_detection_(kLOSS, PRESENCE_OPTIONAL),
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000432 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()),
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100436 initial_congestion_window_(kSWND, PRESENCE_OPTIONAL),
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000437 initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
Torne (Richard Coles)5f1c9432014-08-12 13:47:38 +0100438 // TODO(rjshade): Make this PRESENCE_REQUIRED when QUIC_VERSION_16 is
439 // retired.
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100440 initial_flow_control_window_bytes_(kIFCW, PRESENCE_OPTIONAL),
441 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
442 // QUIC_VERSION_19.
443 initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
444 // TODO(rjshade): Make this PRESENCE_REQUIRED when retiring
445 // QUIC_VERSION_19.
446 initial_session_flow_control_window_bytes_(kCFCW, PRESENCE_OPTIONAL) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100447}
448
449QuicConfig::~QuicConfig() {}
450
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100451void QuicConfig::set_congestion_feedback(
452 const QuicTagVector& congestion_feedback,
453 QuicTag default_congestion_feedback) {
454 congestion_feedback_.set(congestion_feedback, default_congestion_feedback);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100455}
456
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100457QuicTag QuicConfig::congestion_feedback() const {
458 return congestion_feedback_.GetTag();
459}
460
Ben Murdoch116680a2014-07-20 18:25:52 -0700461void QuicConfig::SetConnectionOptionsToSend(
462 const QuicTagVector& connection_options) {
463 connection_options_.SetSendValues(connection_options);
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100464}
465
Ben Murdoch116680a2014-07-20 18:25:52 -0700466bool QuicConfig::HasReceivedConnectionOptions() const {
467 return connection_options_.HasReceivedValues();
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100468}
469
Ben Murdoch116680a2014-07-20 18:25:52 -0700470QuicTagVector QuicConfig::ReceivedConnectionOptions() const {
471 return connection_options_.GetReceivedValues();
472}
473
474bool QuicConfig::HasSendConnectionOptions() const {
475 return connection_options_.HasSendValues();
476}
477
478QuicTagVector QuicConfig::SendConnectionOptions() const {
479 return connection_options_.GetSendValues();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100480}
481
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100482void QuicConfig::SetLossDetectionToSend(QuicTag loss_detection) {
483 loss_detection_.SetSendValue(loss_detection);
Ben Murdoche5d81f52014-04-03 12:29:45 +0100484}
485
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100486bool QuicConfig::HasReceivedLossDetection() const {
487 return loss_detection_.HasReceivedValue();
488}
489
490QuicTag QuicConfig::ReceivedLossDetection() const {
491 return loss_detection_.GetReceivedValue();
Ben Murdoche5d81f52014-04-03 12:29:45 +0100492}
493
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100494void QuicConfig::set_idle_connection_state_lifetime(
495 QuicTime::Delta max_idle_connection_state_lifetime,
496 QuicTime::Delta default_idle_conection_state_lifetime) {
497 idle_connection_state_lifetime_seconds_.set(
498 max_idle_connection_state_lifetime.ToSeconds(),
499 default_idle_conection_state_lifetime.ToSeconds());
500}
501
502QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
503 return QuicTime::Delta::FromSeconds(
504 idle_connection_state_lifetime_seconds_.GetUint32());
505}
506
507QuicTime::Delta QuicConfig::keepalive_timeout() const {
508 return QuicTime::Delta::FromSeconds(
509 keepalive_timeout_seconds_.GetUint32());
510}
511
512void QuicConfig::set_max_streams_per_connection(size_t max_streams,
513 size_t default_streams) {
514 max_streams_per_connection_.set(max_streams, default_streams);
515}
516
517uint32 QuicConfig::max_streams_per_connection() const {
518 return max_streams_per_connection_.GetUint32();
519}
520
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100521void QuicConfig::set_max_time_before_crypto_handshake(
522 QuicTime::Delta max_time_before_crypto_handshake) {
523 max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
524}
525
526QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
527 return max_time_before_crypto_handshake_;
528}
529
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100530void QuicConfig::SetInitialCongestionWindowToSend(size_t initial_window) {
531 initial_congestion_window_.SetSendValue(initial_window);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000532}
533
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100534bool QuicConfig::HasReceivedInitialCongestionWindow() const {
535 return initial_congestion_window_.HasReceivedValue();
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000536}
537
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100538uint32 QuicConfig::ReceivedInitialCongestionWindow() const {
539 return initial_congestion_window_.GetReceivedValue();
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000540}
541
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100542void QuicConfig::SetInitialRoundTripTimeUsToSend(size_t rtt) {
543 initial_round_trip_time_us_.SetSendValue(rtt);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000544}
545
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100546bool QuicConfig::HasReceivedInitialRoundTripTimeUs() const {
547 return initial_round_trip_time_us_.HasReceivedValue();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000548}
549
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100550uint32 QuicConfig::ReceivedInitialRoundTripTimeUs() const {
551 return initial_round_trip_time_us_.GetReceivedValue();
552}
553
554void QuicConfig::SetInitialFlowControlWindowToSend(uint32 window_bytes) {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100555 if (window_bytes < kDefaultFlowControlSendWindow) {
556 LOG(DFATAL) << "Initial flow control receive window (" << window_bytes
557 << ") cannot be set lower than default ("
558 << kDefaultFlowControlSendWindow << ").";
559 window_bytes = kDefaultFlowControlSendWindow;
560 }
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100561 initial_flow_control_window_bytes_.SetSendValue(window_bytes);
562}
563
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100564uint32 QuicConfig::GetInitialFlowControlWindowToSend() const {
565 return initial_flow_control_window_bytes_.GetSendValue();
566}
567
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100568bool QuicConfig::HasReceivedInitialFlowControlWindowBytes() const {
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100569 return initial_flow_control_window_bytes_.HasReceivedValue();
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100570}
571
572uint32 QuicConfig::ReceivedInitialFlowControlWindowBytes() const {
573 return initial_flow_control_window_bytes_.GetReceivedValue();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000574}
575
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100576void QuicConfig::SetInitialStreamFlowControlWindowToSend(uint32 window_bytes) {
577 if (window_bytes < kDefaultFlowControlSendWindow) {
578 LOG(DFATAL) << "Initial stream flow control receive window ("
579 << window_bytes << ") cannot be set lower than default ("
580 << kDefaultFlowControlSendWindow << ").";
581 window_bytes = kDefaultFlowControlSendWindow;
582 }
583 initial_stream_flow_control_window_bytes_.SetSendValue(window_bytes);
584}
585
586uint32 QuicConfig::GetInitialStreamFlowControlWindowToSend() const {
587 return initial_stream_flow_control_window_bytes_.GetSendValue();
588}
589
590bool QuicConfig::HasReceivedInitialStreamFlowControlWindowBytes() const {
591 return initial_stream_flow_control_window_bytes_.HasReceivedValue();
592}
593
594uint32 QuicConfig::ReceivedInitialStreamFlowControlWindowBytes() const {
595 return initial_stream_flow_control_window_bytes_.GetReceivedValue();
596}
597
598void QuicConfig::SetInitialSessionFlowControlWindowToSend(uint32 window_bytes) {
599 if (window_bytes < kDefaultFlowControlSendWindow) {
600 LOG(DFATAL) << "Initial session flow control receive window ("
601 << window_bytes << ") cannot be set lower than default ("
602 << kDefaultFlowControlSendWindow << ").";
603 window_bytes = kDefaultFlowControlSendWindow;
604 }
605 initial_session_flow_control_window_bytes_.SetSendValue(window_bytes);
606}
607
608uint32 QuicConfig::GetInitialSessionFlowControlWindowToSend() const {
609 return initial_session_flow_control_window_bytes_.GetSendValue();
610}
611
612bool QuicConfig::HasReceivedInitialSessionFlowControlWindowBytes() const {
613 return initial_session_flow_control_window_bytes_.HasReceivedValue();
614}
615
616uint32 QuicConfig::ReceivedInitialSessionFlowControlWindowBytes() const {
617 return initial_session_flow_control_window_bytes_.GetReceivedValue();
618}
619
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100620bool QuicConfig::negotiated() {
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000621 // TODO(ianswett): Add the negotiated parameters once and iterate over all
622 // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
623 // ProcessServerHello.
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100624 return congestion_feedback_.negotiated() &&
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100625 idle_connection_state_lifetime_seconds_.negotiated() &&
626 keepalive_timeout_seconds_.negotiated() &&
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100627 max_streams_per_connection_.negotiated();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100628}
629
630void QuicConfig::SetDefaults() {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100631 QuicTagVector congestion_feedback;
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000632 if (FLAGS_enable_quic_pacing) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100633 congestion_feedback.push_back(kPACE);
Torne (Richard Coles)f2477e02013-11-28 11:55:43 +0000634 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100635 congestion_feedback.push_back(kQBIC);
636 congestion_feedback_.set(congestion_feedback, kQBIC);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100637 idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100638 kDefaultInitialTimeoutSecs);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100639 // kKATO is optional. Return 0 if not negotiated.
640 keepalive_timeout_seconds_.set(0, 0);
641 max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
642 kDefaultMaxStreamsPerConnection);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100643 max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
644 kDefaultMaxTimeForCryptoHandshakeSecs);
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100645
646 SetInitialFlowControlWindowToSend(kDefaultFlowControlSendWindow);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100647 SetInitialStreamFlowControlWindowToSend(kDefaultFlowControlSendWindow);
648 SetInitialSessionFlowControlWindowToSend(kDefaultFlowControlSendWindow);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100649}
650
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000651void QuicConfig::EnablePacing(bool enable_pacing) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100652 QuicTagVector congestion_feedback;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000653 if (enable_pacing) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100654 congestion_feedback.push_back(kPACE);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000655 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100656 congestion_feedback.push_back(kQBIC);
657 congestion_feedback_.set(congestion_feedback, kQBIC);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000658}
659
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100660void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100661 congestion_feedback_.ToHandshakeMessage(out);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100662 idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
663 keepalive_timeout_seconds_.ToHandshakeMessage(out);
664 max_streams_per_connection_.ToHandshakeMessage(out);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100665 initial_congestion_window_.ToHandshakeMessage(out);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000666 initial_round_trip_time_us_.ToHandshakeMessage(out);
Ben Murdoche5d81f52014-04-03 12:29:45 +0100667 loss_detection_.ToHandshakeMessage(out);
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100668 initial_flow_control_window_bytes_.ToHandshakeMessage(out);
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100669 initial_stream_flow_control_window_bytes_.ToHandshakeMessage(out);
670 initial_session_flow_control_window_bytes_.ToHandshakeMessage(out);
Ben Murdoch116680a2014-07-20 18:25:52 -0700671 connection_options_.ToHandshakeMessage(out);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100672}
673
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100674QuicErrorCode QuicConfig::ProcessPeerHello(
675 const CryptoHandshakeMessage& peer_hello,
676 HelloType hello_type,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100677 string* error_details) {
678 DCHECK(error_details != NULL);
679
680 QuicErrorCode error = QUIC_NO_ERROR;
681 if (error == QUIC_NO_ERROR) {
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100682 error = congestion_feedback_.ProcessPeerHello(
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100683 peer_hello, hello_type, error_details);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100684 }
685 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100686 error = idle_connection_state_lifetime_seconds_.ProcessPeerHello(
687 peer_hello, hello_type, error_details);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100688 }
689 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100690 error = keepalive_timeout_seconds_.ProcessPeerHello(
691 peer_hello, hello_type, error_details);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100692 }
693 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100694 error = max_streams_per_connection_.ProcessPeerHello(
695 peer_hello, hello_type, error_details);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100696 }
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000697 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100698 error = initial_congestion_window_.ProcessPeerHello(
699 peer_hello, hello_type, error_details);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000700 }
701 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100702 error = initial_round_trip_time_us_.ProcessPeerHello(
703 peer_hello, hello_type, error_details);
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000704 }
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000705 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100706 error = initial_flow_control_window_bytes_.ProcessPeerHello(
707 peer_hello, hello_type, error_details);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000708 }
Ben Murdoche5d81f52014-04-03 12:29:45 +0100709 if (error == QUIC_NO_ERROR) {
Torne (Richard Coles)6d86b772014-06-25 10:30:53 +0100710 error = initial_stream_flow_control_window_bytes_.ProcessPeerHello(
711 peer_hello, hello_type, error_details);
712 }
713 if (error == QUIC_NO_ERROR) {
714 error = initial_session_flow_control_window_bytes_.ProcessPeerHello(
715 peer_hello, hello_type, error_details);
716 }
717 if (error == QUIC_NO_ERROR) {
Ben Murdoch0529e5d2014-04-24 10:50:13 +0100718 error = loss_detection_.ProcessPeerHello(
719 peer_hello, hello_type, error_details);
Ben Murdoche5d81f52014-04-03 12:29:45 +0100720 }
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100721 if (error == QUIC_NO_ERROR) {
Ben Murdoch116680a2014-07-20 18:25:52 -0700722 error = connection_options_.ProcessPeerHello(
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100723 peer_hello, hello_type, error_details);
724 }
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100725 return error;
726}
727
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100728} // namespace net