Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / net / quic / quic_config.cc
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_sent_packet_manager.h"
13 #include "net/quic/quic_utils.h"
14
15 using std::string;
16
17 namespace net {
18
19 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
20     : tag_(tag),
21       presence_(presence),
22       negotiated_(false) {
23 }
24
25 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
26     : QuicNegotiableValue(tag, presence),
27       max_value_(0),
28       default_value_(0) {
29 }
30
31 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
32   DCHECK_LE(default_value, max);
33   max_value_ = max;
34   default_value_ = default_value;
35 }
36
37 uint32 QuicNegotiableUint32::GetUint32() const {
38   if (negotiated_) {
39     return negotiated_value_;
40   }
41   return default_value_;
42 }
43
44 void QuicNegotiableUint32::ToHandshakeMessage(
45     CryptoHandshakeMessage* out) const {
46   if (negotiated_) {
47     out->SetValue(tag_, negotiated_value_);
48   } else {
49     out->SetValue(tag_, max_value_);
50   }
51 }
52
53 QuicErrorCode QuicNegotiableUint32::ReadUint32(
54     const CryptoHandshakeMessage& msg,
55     uint32* out,
56     string* error_details) const {
57   DCHECK(error_details != NULL);
58   QuicErrorCode error = msg.GetUint32(tag_, out);
59   switch (error) {
60     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
61       if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
62         *error_details = "Missing " + QuicUtils::TagToString(tag_);
63         break;
64       }
65       error = QUIC_NO_ERROR;
66       *out = default_value_;
67
68     case QUIC_NO_ERROR:
69       break;
70     default:
71       *error_details = "Bad " + QuicUtils::TagToString(tag_);
72       break;
73   }
74   return error;
75 }
76
77 QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
78     const CryptoHandshakeMessage& client_hello,
79     string* error_details) {
80   DCHECK(!negotiated_);
81   DCHECK(error_details != NULL);
82   uint32 value;
83   QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
84   if (error != QUIC_NO_ERROR) {
85     return error;
86   }
87
88   negotiated_ = true;
89   negotiated_value_ = std::min(value, max_value_);
90
91   return QUIC_NO_ERROR;
92 }
93
94 QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
95     const CryptoHandshakeMessage& server_hello,
96     string* error_details) {
97   DCHECK(!negotiated_);
98   DCHECK(error_details != NULL);
99   uint32 value;
100   QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
101   if (error != QUIC_NO_ERROR) {
102     return error;
103   }
104
105   if (value > max_value_) {
106     *error_details = "Invalid value received for " +
107         QuicUtils::TagToString(tag_);
108     return QUIC_INVALID_NEGOTIATED_VALUE;
109   }
110
111   negotiated_ = true;
112   negotiated_value_ = value;
113   return QUIC_NO_ERROR;
114 }
115
116 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
117     : QuicNegotiableValue(tag, presence),
118       negotiated_tag_(0),
119       default_value_(0) {
120 }
121
122 QuicNegotiableTag::~QuicNegotiableTag() {}
123
124 void QuicNegotiableTag::set(const QuicTagVector& possible,
125                             QuicTag default_value) {
126   DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
127             possible.end());
128   possible_values_ = possible;
129   default_value_ = default_value;
130 }
131
132 QuicTag QuicNegotiableTag::GetTag() const {
133   if (negotiated_) {
134     return negotiated_tag_;
135   }
136   return default_value_;
137 }
138
139 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
140   if (negotiated_) {
141     // Because of the way we serialize and parse handshake messages we can
142     // serialize this as value and still parse it as a vector.
143     out->SetValue(tag_, negotiated_tag_);
144   } else {
145     out->SetVector(tag_, possible_values_);
146   }
147 }
148
149 QuicErrorCode QuicNegotiableTag::ReadVector(
150     const CryptoHandshakeMessage& msg,
151     const QuicTag** out,
152     size_t* out_length,
153     string* error_details) const {
154   DCHECK(error_details != NULL);
155   QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
156   switch (error) {
157     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
158       if (presence_ == PRESENCE_REQUIRED) {
159         *error_details = "Missing " + QuicUtils::TagToString(tag_);
160         break;
161       }
162       error = QUIC_NO_ERROR;
163       *out_length = 1;
164       *out = &default_value_;
165
166     case QUIC_NO_ERROR:
167       break;
168     default:
169       *error_details = "Bad " + QuicUtils::TagToString(tag_);
170       break;
171   }
172   return error;
173 }
174
175 QuicErrorCode QuicNegotiableTag::ProcessClientHello(
176     const CryptoHandshakeMessage& client_hello,
177     string* error_details) {
178   DCHECK(!negotiated_);
179   DCHECK(error_details != NULL);
180   const QuicTag* received_tags;
181   size_t received_tags_length;
182   QuicErrorCode error = ReadVector(client_hello, &received_tags,
183                                    &received_tags_length, error_details);
184   if (error != QUIC_NO_ERROR) {
185     return error;
186   }
187
188   QuicTag negotiated_tag;
189   if (!QuicUtils::FindMutualTag(possible_values_,
190                                 received_tags,
191                                 received_tags_length,
192                                 QuicUtils::LOCAL_PRIORITY,
193                                 &negotiated_tag,
194                                 NULL)) {
195     *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
196     return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
197   }
198
199   negotiated_ = true;
200   negotiated_tag_ = negotiated_tag;
201   return QUIC_NO_ERROR;
202 }
203
204 QuicErrorCode QuicNegotiableTag::ProcessServerHello(
205     const CryptoHandshakeMessage& server_hello,
206     string* error_details) {
207   DCHECK(!negotiated_);
208   DCHECK(error_details != NULL);
209   const QuicTag* received_tags;
210   size_t received_tags_length;
211   QuicErrorCode error = ReadVector(server_hello, &received_tags,
212                                    &received_tags_length, error_details);
213   if (error != QUIC_NO_ERROR) {
214     return error;
215   }
216
217   if (received_tags_length != 1 ||
218       std::find(possible_values_.begin(), possible_values_.end(),
219                 *received_tags) == possible_values_.end()) {
220     *error_details = "Invalid " + QuicUtils::TagToString(tag_);
221     return QUIC_INVALID_NEGOTIATED_VALUE;
222   }
223
224   negotiated_ = true;
225   negotiated_tag_ = *received_tags;
226   return QUIC_NO_ERROR;
227 }
228
229 QuicConfig::QuicConfig() :
230     congestion_control_(kCGST, QuicNegotiableValue::PRESENCE_REQUIRED),
231     idle_connection_state_lifetime_seconds_(
232         kICSL, QuicNegotiableValue::PRESENCE_REQUIRED),
233     keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL),
234     max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED),
235     max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
236     server_initial_congestion_window_(
237         kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
238     initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
239   // All optional non-zero parameters should be initialized here.
240   server_initial_congestion_window_.set(kMaxInitialWindow,
241                                         kDefaultInitialWindow);
242 }
243
244 QuicConfig::~QuicConfig() {}
245
246 void QuicConfig::set_congestion_control(
247     const QuicTagVector& congestion_control,
248     QuicTag default_congestion_control) {
249   congestion_control_.set(congestion_control, default_congestion_control);
250 }
251
252 QuicTag QuicConfig::congestion_control() const {
253   return congestion_control_.GetTag();
254 }
255
256 void QuicConfig::set_idle_connection_state_lifetime(
257     QuicTime::Delta max_idle_connection_state_lifetime,
258     QuicTime::Delta default_idle_conection_state_lifetime) {
259   idle_connection_state_lifetime_seconds_.set(
260       max_idle_connection_state_lifetime.ToSeconds(),
261       default_idle_conection_state_lifetime.ToSeconds());
262 }
263
264 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
265   return QuicTime::Delta::FromSeconds(
266       idle_connection_state_lifetime_seconds_.GetUint32());
267 }
268
269 QuicTime::Delta QuicConfig::keepalive_timeout() const {
270   return QuicTime::Delta::FromSeconds(
271       keepalive_timeout_seconds_.GetUint32());
272 }
273
274 void QuicConfig::set_max_streams_per_connection(size_t max_streams,
275                                                 size_t default_streams) {
276   max_streams_per_connection_.set(max_streams, default_streams);
277 }
278
279 uint32 QuicConfig::max_streams_per_connection() const {
280   return max_streams_per_connection_.GetUint32();
281 }
282
283 void QuicConfig::set_max_time_before_crypto_handshake(
284     QuicTime::Delta max_time_before_crypto_handshake) {
285   max_time_before_crypto_handshake_ = max_time_before_crypto_handshake;
286 }
287
288 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
289   return max_time_before_crypto_handshake_;
290 }
291
292 void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window,
293                                                size_t default_initial_window) {
294   server_initial_congestion_window_.set(max_initial_window,
295                                         default_initial_window);
296 }
297
298 uint32 QuicConfig::server_initial_congestion_window() const {
299   return server_initial_congestion_window_.GetUint32();
300 }
301
302 void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
303                                                 size_t default_rtt) {
304   initial_round_trip_time_us_.set(max_rtt, default_rtt);
305 }
306
307 uint32 QuicConfig::initial_round_trip_time_us() const {
308   return initial_round_trip_time_us_.GetUint32();
309 }
310
311 bool QuicConfig::negotiated() {
312   // TODO(ianswett): Add the negotiated parameters once and iterate over all
313   // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
314   // ProcessServerHello.
315   return congestion_control_.negotiated() &&
316       idle_connection_state_lifetime_seconds_.negotiated() &&
317       keepalive_timeout_seconds_.negotiated() &&
318       max_streams_per_connection_.negotiated() &&
319       server_initial_congestion_window_.negotiated() &&
320       initial_round_trip_time_us_.negotiated();
321 }
322
323 void QuicConfig::SetDefaults() {
324   QuicTagVector congestion_control;
325   if (FLAGS_enable_quic_pacing) {
326     congestion_control.push_back(kPACE);
327   }
328   congestion_control.push_back(kQBIC);
329   congestion_control_.set(congestion_control, kQBIC);
330   idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
331                                               kDefaultInitialTimeoutSecs);
332   // kKATO is optional. Return 0 if not negotiated.
333   keepalive_timeout_seconds_.set(0, 0);
334   max_streams_per_connection_.set(kDefaultMaxStreamsPerConnection,
335                                   kDefaultMaxStreamsPerConnection);
336   max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
337       kDefaultMaxTimeForCryptoHandshakeSecs);
338   server_initial_congestion_window_.set(kDefaultInitialWindow,
339                                         kDefaultInitialWindow);
340 }
341
342 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
343   congestion_control_.ToHandshakeMessage(out);
344   idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
345   keepalive_timeout_seconds_.ToHandshakeMessage(out);
346   max_streams_per_connection_.ToHandshakeMessage(out);
347   server_initial_congestion_window_.ToHandshakeMessage(out);
348   // TODO(ianswett): Don't transmit parameters which are optional and not set.
349   initial_round_trip_time_us_.ToHandshakeMessage(out);
350 }
351
352 QuicErrorCode QuicConfig::ProcessClientHello(
353     const CryptoHandshakeMessage& client_hello,
354     string* error_details) {
355   DCHECK(error_details != NULL);
356
357   QuicErrorCode error = QUIC_NO_ERROR;
358   if (error == QUIC_NO_ERROR) {
359     error = congestion_control_.ProcessClientHello(client_hello, error_details);
360   }
361   if (error == QUIC_NO_ERROR) {
362     error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
363         client_hello, error_details);
364   }
365   if (error == QUIC_NO_ERROR) {
366     error = keepalive_timeout_seconds_.ProcessClientHello(
367         client_hello, error_details);
368   }
369   if (error == QUIC_NO_ERROR) {
370     error = max_streams_per_connection_.ProcessClientHello(
371         client_hello, error_details);
372   }
373   if (error == QUIC_NO_ERROR) {
374     error = server_initial_congestion_window_.ProcessClientHello(
375         client_hello, error_details);
376   }
377   if (error == QUIC_NO_ERROR) {
378     error = initial_round_trip_time_us_.ProcessClientHello(
379         client_hello, error_details);
380   }
381   return error;
382 }
383
384 QuicErrorCode QuicConfig::ProcessServerHello(
385     const CryptoHandshakeMessage& server_hello,
386     string* error_details) {
387   DCHECK(error_details != NULL);
388
389   QuicErrorCode error = QUIC_NO_ERROR;
390   if (error == QUIC_NO_ERROR) {
391     error = congestion_control_.ProcessServerHello(server_hello, error_details);
392   }
393   if (error == QUIC_NO_ERROR) {
394     error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
395         server_hello, error_details);
396   }
397   if (error == QUIC_NO_ERROR) {
398     error = keepalive_timeout_seconds_.ProcessServerHello(
399         server_hello, error_details);
400   }
401   if (error == QUIC_NO_ERROR) {
402     error = max_streams_per_connection_.ProcessServerHello(
403         server_hello, error_details);
404   }
405   if (error == QUIC_NO_ERROR) {
406     error = server_initial_congestion_window_.ProcessServerHello(
407         server_hello, error_details);
408   }
409   if (error == QUIC_NO_ERROR) {
410     error = initial_round_trip_time_us_.ProcessServerHello(
411         server_hello, error_details);
412   }
413   return error;
414 }
415
416 }  // namespace net