- add sources.
[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
11 using std::string;
12
13 namespace net {
14
15 QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
16     : tag_(tag),
17       presence_(presence),
18       negotiated_(false) {
19 }
20
21 QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
22     : QuicNegotiableValue(tag, presence),
23       max_value_(0),
24       default_value_(0) {
25 }
26
27 void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
28   DCHECK_LE(default_value, max);
29   max_value_ = max;
30   default_value_ = default_value;
31 }
32
33 uint32 QuicNegotiableUint32::GetUint32() const {
34   if (negotiated_) {
35     return negotiated_value_;
36   }
37   return default_value_;
38 }
39
40 void QuicNegotiableUint32::ToHandshakeMessage(
41     CryptoHandshakeMessage* out) const {
42   if (negotiated_) {
43     out->SetValue(tag_, negotiated_value_);
44   } else {
45     out->SetValue(tag_, max_value_);
46   }
47 }
48
49 QuicErrorCode QuicNegotiableUint32::ReadUint32(
50     const CryptoHandshakeMessage& msg,
51     uint32* out,
52     string* error_details) const {
53   DCHECK(error_details != NULL);
54   QuicErrorCode error = msg.GetUint32(tag_, out);
55   switch (error) {
56     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
57       if (presence_ == QuicNegotiableValue::PRESENCE_REQUIRED) {
58         *error_details = "Missing " + QuicUtils::TagToString(tag_);
59         break;
60       }
61       error = QUIC_NO_ERROR;
62       *out = default_value_;
63
64     case QUIC_NO_ERROR:
65       break;
66     default:
67       *error_details = "Bad " + QuicUtils::TagToString(tag_);
68       break;
69   }
70   return error;
71 }
72
73 QuicErrorCode QuicNegotiableUint32::ProcessClientHello(
74     const CryptoHandshakeMessage& client_hello,
75     string* error_details) {
76   DCHECK(!negotiated_);
77   DCHECK(error_details != NULL);
78   uint32 value;
79   QuicErrorCode error = ReadUint32(client_hello, &value, error_details);
80   if (error != QUIC_NO_ERROR) {
81     return error;
82   }
83
84   negotiated_ = true;
85   negotiated_value_ = std::min(value, max_value_);
86
87   return QUIC_NO_ERROR;
88 }
89
90 QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
91     const CryptoHandshakeMessage& server_hello,
92     string* error_details) {
93   DCHECK(!negotiated_);
94   DCHECK(error_details != NULL);
95   uint32 value;
96   QuicErrorCode error = ReadUint32(server_hello, &value, error_details);
97   if (error != QUIC_NO_ERROR) {
98     return error;
99   }
100
101   if (value > max_value_) {
102     *error_details = "Invalid value received for " +
103         QuicUtils::TagToString(tag_);
104     return QUIC_INVALID_NEGOTIATED_VALUE;
105   }
106
107   negotiated_ = true;
108   negotiated_value_ = value;
109   return QUIC_NO_ERROR;
110 }
111
112 QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
113     : QuicNegotiableValue(tag, presence) {
114 }
115
116 QuicNegotiableTag::~QuicNegotiableTag() {}
117
118 void QuicNegotiableTag::set(const QuicTagVector& possible,
119                             QuicTag default_value) {
120   DCHECK(std::find(possible.begin(), possible.end(), default_value) !=
121             possible.end());
122   possible_values_ = possible;
123   default_value_ = default_value;
124 }
125
126 QuicTag QuicNegotiableTag::GetTag() const {
127   if (negotiated_) {
128     return negotiated_tag_;
129   }
130   return default_value_;
131 }
132
133 void QuicNegotiableTag::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
134   if (negotiated_) {
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_);
138   } else {
139     out->SetVector(tag_, possible_values_);
140   }
141 }
142
143 QuicErrorCode QuicNegotiableTag::ReadVector(
144     const CryptoHandshakeMessage& msg,
145     const QuicTag** out,
146     size_t* out_length,
147     string* error_details) const {
148   DCHECK(error_details != NULL);
149   QuicErrorCode error = msg.GetTaglist(tag_, out, out_length);
150   switch (error) {
151     case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
152       if (presence_ == PRESENCE_REQUIRED) {
153         *error_details = "Missing " + QuicUtils::TagToString(tag_);
154         break;
155       }
156       error = QUIC_NO_ERROR;
157       *out_length = 1;
158       *out = &default_value_;
159
160     case QUIC_NO_ERROR:
161       break;
162     default:
163       *error_details = "Bad " + QuicUtils::TagToString(tag_);
164       break;
165   }
166   return error;
167 }
168
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) {
179     return error;
180   }
181
182   QuicTag negotiated_tag;
183   if (!QuicUtils::FindMutualTag(possible_values_,
184                                 received_tags,
185                                 received_tags_length,
186                                 QuicUtils::LOCAL_PRIORITY,
187                                 &negotiated_tag,
188                                 NULL)) {
189     *error_details = "Unsuported " + QuicUtils::TagToString(tag_);
190     return QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP;
191   }
192
193   negotiated_ = true;
194   negotiated_tag_ = negotiated_tag;
195   return QUIC_NO_ERROR;
196 }
197
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) {
208     return error;
209   }
210
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;
216   }
217
218   negotiated_ = true;
219   negotiated_tag_ = *received_tags;
220   return QUIC_NO_ERROR;
221 }
222
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);
238 }
239
240 QuicConfig::~QuicConfig() {}
241
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);
246 }
247
248 QuicTag QuicConfig::congestion_control() const {
249   return congestion_control_.GetTag();
250 }
251
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());
258 }
259
260 QuicTime::Delta QuicConfig::idle_connection_state_lifetime() const {
261   return QuicTime::Delta::FromSeconds(
262       idle_connection_state_lifetime_seconds_.GetUint32());
263 }
264
265 QuicTime::Delta QuicConfig::keepalive_timeout() const {
266   return QuicTime::Delta::FromSeconds(
267       keepalive_timeout_seconds_.GetUint32());
268 }
269
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);
273 }
274
275 uint32 QuicConfig::max_streams_per_connection() const {
276   return max_streams_per_connection_.GetUint32();
277 }
278
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;
282 }
283
284 QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
285   return max_time_before_crypto_handshake_;
286 }
287
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);
292 }
293
294 uint32 QuicConfig::server_initial_congestion_window() const {
295   return server_initial_congestion_window_.GetUint32();
296 }
297
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);
301 }
302
303 uint32 QuicConfig::server_max_packet_size() const {
304   return server_max_packet_size_.GetUint32();
305 }
306
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);
310 }
311
312 uint32 QuicConfig::initial_round_trip_time_us() const {
313   return initial_round_trip_time_us_.GetUint32();
314 }
315
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();
327 }
328
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);
342 }
343
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);
353 }
354
355 QuicErrorCode QuicConfig::ProcessClientHello(
356     const CryptoHandshakeMessage& client_hello,
357     string* error_details) {
358   DCHECK(error_details != NULL);
359
360   QuicErrorCode error = QUIC_NO_ERROR;
361   if (error == QUIC_NO_ERROR) {
362     error = congestion_control_.ProcessClientHello(client_hello, error_details);
363   }
364   if (error == QUIC_NO_ERROR) {
365     error = idle_connection_state_lifetime_seconds_.ProcessClientHello(
366         client_hello, error_details);
367   }
368   if (error == QUIC_NO_ERROR) {
369     error = keepalive_timeout_seconds_.ProcessClientHello(
370         client_hello, error_details);
371   }
372   if (error == QUIC_NO_ERROR) {
373     error = max_streams_per_connection_.ProcessClientHello(
374         client_hello, error_details);
375   }
376   if (error == QUIC_NO_ERROR) {
377     error = server_initial_congestion_window_.ProcessClientHello(
378         client_hello, error_details);
379   }
380   if (error == QUIC_NO_ERROR) {
381     error = server_max_packet_size_.ProcessClientHello(
382         client_hello, error_details);
383   }
384   if (error == QUIC_NO_ERROR) {
385     error = initial_round_trip_time_us_.ProcessClientHello(
386         client_hello, error_details);
387   }
388   return error;
389 }
390
391 QuicErrorCode QuicConfig::ProcessServerHello(
392     const CryptoHandshakeMessage& server_hello,
393     string* error_details) {
394   DCHECK(error_details != NULL);
395
396   QuicErrorCode error = QUIC_NO_ERROR;
397   if (error == QUIC_NO_ERROR) {
398     error = congestion_control_.ProcessServerHello(server_hello, error_details);
399   }
400   if (error == QUIC_NO_ERROR) {
401     error = idle_connection_state_lifetime_seconds_.ProcessServerHello(
402         server_hello, error_details);
403   }
404   if (error == QUIC_NO_ERROR) {
405     error = keepalive_timeout_seconds_.ProcessServerHello(
406         server_hello, error_details);
407   }
408   if (error == QUIC_NO_ERROR) {
409     error = max_streams_per_connection_.ProcessServerHello(
410         server_hello, error_details);
411   }
412   if (error == QUIC_NO_ERROR) {
413     error = server_initial_congestion_window_.ProcessServerHello(
414         server_hello, error_details);
415   }
416   if (error == QUIC_NO_ERROR) {
417     error = server_max_packet_size_.ProcessServerHello(
418         server_hello, error_details);
419   }
420   if (error == QUIC_NO_ERROR) {
421     error = initial_round_trip_time_us_.ProcessServerHello(
422         server_hello, error_details);
423   }
424   return error;
425 }
426
427 }  // namespace net
428