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#ifndef NET_QUIC_QUIC_CONFIG_H_
6#define NET_QUIC_QUIC_CONFIG_H_
7
8#include <string>
9
10#include "base/basictypes.h"
11#include "net/quic/quic_protocol.h"
12#include "net/quic/quic_time.h"
13
14namespace net {
15
16namespace test {
17class QuicConfigPeer;
18}  // namespace test
19
20class CryptoHandshakeMessage;
21
22// Describes whether or not a given QuicTag is required or optional in the
23// handshake message.
24enum QuicConfigPresence {
25  // This negotiable value can be absent from the handshake message. Default
26  // value is selected as the negotiated value in such a case.
27  PRESENCE_OPTIONAL,
28  // This negotiable value is required in the handshake message otherwise the
29  // Process*Hello function returns an error.
30  PRESENCE_REQUIRED,
31};
32
33// Whether the CryptoHandshakeMessage is from the client or server.
34enum HelloType {
35  CLIENT,
36  SERVER,
37};
38
39// An abstract base class that stores a value that can be sent in CHLO/SHLO
40// message. These values can be OPTIONAL or REQUIRED, depending on |presence_|.
41class NET_EXPORT_PRIVATE QuicConfigValue {
42 public:
43  QuicConfigValue(QuicTag tag, QuicConfigPresence presence);
44  virtual ~QuicConfigValue();
45
46  // Serialises tag name and value(s) to |out|.
47  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const = 0;
48
49  // Selects a mutually acceptable value from those offered in |peer_hello|
50  // and those defined in the subclass.
51  virtual QuicErrorCode ProcessPeerHello(
52      const CryptoHandshakeMessage& peer_hello,
53      HelloType hello_type,
54      std::string* error_details) = 0;
55
56 protected:
57  const QuicTag tag_;
58  const QuicConfigPresence presence_;
59};
60
61class NET_EXPORT_PRIVATE QuicNegotiableValue : public QuicConfigValue {
62 public:
63  QuicNegotiableValue(QuicTag tag, QuicConfigPresence presence);
64  virtual ~QuicNegotiableValue();
65
66  bool negotiated() const {
67    return negotiated_;
68  }
69
70 protected:
71  bool negotiated_;
72};
73
74class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
75 public:
76  // Default and max values default to 0.
77  QuicNegotiableUint32(QuicTag name, QuicConfigPresence presence);
78  virtual ~QuicNegotiableUint32();
79
80  // Sets the maximum possible value that can be achieved after negotiation and
81  // also the default values to be assumed if PRESENCE_OPTIONAL and the *HLO msg
82  // doesn't contain a value corresponding to |name_|. |max| is serialised via
83  // ToHandshakeMessage call if |negotiated_| is false.
84  void set(uint32 max, uint32 default_value);
85
86  // Returns the value negotiated if |negotiated_| is true, otherwise returns
87  // default_value_ (used to set default values before negotiation finishes).
88  uint32 GetUint32() const;
89
90  // Serialises |name_| and value to |out|. If |negotiated_| is true then
91  // |negotiated_value_| is serialised, otherwise |max_value_| is serialised.
92  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
93
94  // Sets |negotiated_value_| to the minimum of |max_value_| and the
95  // corresponding value from |peer_hello|. If the corresponding value is
96  // missing and PRESENCE_OPTIONAL then |negotiated_value_| is set to
97  // |default_value_|.
98  virtual QuicErrorCode ProcessPeerHello(
99      const CryptoHandshakeMessage& peer_hello,
100      HelloType hello_type,
101      std::string* error_details) OVERRIDE;
102
103 private:
104  uint32 max_value_;
105  uint32 default_value_;
106  uint32 negotiated_value_;
107};
108
109class NET_EXPORT_PRIVATE QuicNegotiableTag : public QuicNegotiableValue {
110 public:
111  QuicNegotiableTag(QuicTag name, QuicConfigPresence presence);
112  virtual ~QuicNegotiableTag();
113
114  // Sets the possible values that |negotiated_tag_| can take after negotiation
115  // and the default value that |negotiated_tag_| takes if OPTIONAL and *HLO
116  // msg doesn't contain tag |name_|.
117  void set(const QuicTagVector& possible_values, QuicTag default_value);
118
119  // Returns the negotiated tag if |negotiated_| is true, otherwise returns
120  // |default_value_| (used to set default values before negotiation finishes).
121  QuicTag GetTag() const;
122
123  // Serialises |name_| and vector (either possible or negotiated) to |out|. If
124  // |negotiated_| is true then |negotiated_tag_| is serialised, otherwise
125  // |possible_values_| is serialised.
126  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
127
128  // Selects the tag common to both tags in |client_hello| for |name_| and
129  // |possible_values_| with preference to tag in |possible_values_|. The
130  // selected tag is set as |negotiated_tag_|.
131  virtual QuicErrorCode ProcessPeerHello(
132      const CryptoHandshakeMessage& peer_hello,
133      HelloType hello_type,
134      std::string* error_details) OVERRIDE;
135
136 private:
137  // Reads the vector corresponding to |name_| from |msg| into |out|. If the
138  // |name_| is absent in |msg| and |presence_| is set to OPTIONAL |out| is set
139  // to |possible_values_|.
140  QuicErrorCode ReadVector(const CryptoHandshakeMessage& msg,
141                           const QuicTag** out,
142                           size_t* out_length,
143                           std::string* error_details) const;
144
145  QuicTag negotiated_tag_;
146  QuicTagVector possible_values_;
147  QuicTag default_value_;
148};
149
150// Stores uint32 from CHLO or SHLO messages that are not negotiated.
151class NET_EXPORT_PRIVATE QuicFixedUint32 : public QuicConfigValue {
152 public:
153  QuicFixedUint32(QuicTag name, QuicConfigPresence presence);
154  virtual ~QuicFixedUint32();
155
156  bool HasSendValue() const;
157
158  uint32 GetSendValue() const;
159
160  void SetSendValue(uint32 value);
161
162  bool HasReceivedValue() const;
163
164  uint32 GetReceivedValue() const;
165
166  void SetReceivedValue(uint32 value);
167
168  // If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
169  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
170
171  // Sets |value_| to the corresponding value from |peer_hello_| if it exists.
172  virtual QuicErrorCode ProcessPeerHello(
173      const CryptoHandshakeMessage& peer_hello,
174      HelloType hello_type,
175      std::string* error_details) OVERRIDE;
176
177 private:
178  uint32 send_value_;
179  bool has_send_value_;
180  uint32 receive_value_;
181  bool has_receive_value_;
182};
183
184// Stores tag from CHLO or SHLO messages that are not negotiated.
185class NET_EXPORT_PRIVATE QuicFixedTag : public QuicConfigValue {
186 public:
187  QuicFixedTag(QuicTag name, QuicConfigPresence presence);
188  virtual ~QuicFixedTag();
189
190  bool HasSendValue() const;
191
192  QuicTag GetSendValue() const;
193
194  void SetSendValue(QuicTag value);
195
196  bool HasReceivedValue() const;
197
198  QuicTag GetReceivedValue() const;
199
200  void SetReceivedValue(QuicTag value);
201
202  // If has_send_value is true, serialises |tag_| and |send_value_| to |out|.
203  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
204
205  // Sets |value_| to the corresponding value from |client_hello_| if it exists.
206  virtual QuicErrorCode ProcessPeerHello(
207      const CryptoHandshakeMessage& peer_hello,
208      HelloType hello_type,
209      std::string* error_details) OVERRIDE;
210
211 private:
212  QuicTag send_value_;
213  bool has_send_value_;
214  QuicTag receive_value_;
215  bool has_receive_value_;
216};
217
218// Stores tag from CHLO or SHLO messages that are not negotiated.
219class NET_EXPORT_PRIVATE QuicFixedTagVector : public QuicConfigValue {
220 public:
221  QuicFixedTagVector(QuicTag name, QuicConfigPresence presence);
222  virtual ~QuicFixedTagVector();
223
224  bool HasSendValues() const;
225
226  QuicTagVector GetSendValues() const;
227
228  void SetSendValues(const QuicTagVector& values);
229
230  bool HasReceivedValues() const;
231
232  QuicTagVector GetReceivedValues() const;
233
234  void SetReceivedValues(const QuicTagVector& values);
235
236  // If has_send_value is true, serialises |tag_vector_| and |send_value_| to
237  // |out|.
238  virtual void ToHandshakeMessage(CryptoHandshakeMessage* out) const OVERRIDE;
239
240  // Sets |receive_values_| to the corresponding value from |client_hello_| if
241  // it exists.
242  virtual QuicErrorCode ProcessPeerHello(
243      const CryptoHandshakeMessage& peer_hello,
244      HelloType hello_type,
245      std::string* error_details) OVERRIDE;
246
247 private:
248  QuicTagVector send_values_;
249  bool has_send_values_;
250  QuicTagVector receive_values_;
251  bool has_receive_values_;
252};
253
254// QuicConfig contains non-crypto configuration options that are negotiated in
255// the crypto handshake.
256class NET_EXPORT_PRIVATE QuicConfig {
257 public:
258  QuicConfig();
259  ~QuicConfig();
260
261  void set_congestion_feedback(const QuicTagVector& congestion_feedback,
262                               QuicTag default_congestion_feedback);
263
264  QuicTag congestion_feedback() const;
265
266  void SetConnectionOptionsToSend(const QuicTagVector& connection_options);
267
268  bool HasReceivedConnectionOptions() const;
269
270  QuicTagVector ReceivedConnectionOptions() const;
271
272  bool HasSendConnectionOptions() const;
273
274  QuicTagVector SendConnectionOptions() const;
275
276  void SetLossDetectionToSend(QuicTag loss_detection);
277
278  bool HasReceivedLossDetection() const;
279
280  QuicTag ReceivedLossDetection() const;
281
282  void set_idle_connection_state_lifetime(
283      QuicTime::Delta max_idle_connection_state_lifetime,
284      QuicTime::Delta default_idle_conection_state_lifetime);
285
286  QuicTime::Delta idle_connection_state_lifetime() const;
287
288  QuicTime::Delta keepalive_timeout() const;
289
290  void set_max_streams_per_connection(size_t max_streams,
291                                      size_t default_streams);
292
293  uint32 max_streams_per_connection() const;
294
295  void set_max_time_before_crypto_handshake(
296      QuicTime::Delta max_time_before_crypto_handshake);
297
298  QuicTime::Delta max_time_before_crypto_handshake() const;
299
300  // Sets the peer's default initial congestion window in packets.
301  void SetInitialCongestionWindowToSend(size_t initial_window);
302
303  bool HasReceivedInitialCongestionWindow() const;
304
305  uint32 ReceivedInitialCongestionWindow() const;
306
307  // Sets an estimated initial round trip time in us.
308  void SetInitialRoundTripTimeUsToSend(size_t rtt_us);
309
310  bool HasReceivedInitialRoundTripTimeUs() const;
311
312  uint32 ReceivedInitialRoundTripTimeUs() const;
313
314  bool HasInitialRoundTripTimeUsToSend() const;
315
316  uint32 GetInitialRoundTripTimeUsToSend() const;
317
318  // TODO(rjshade): Remove all InitialFlowControlWindow methods when removing
319  // QUIC_VERSION_19.
320  // Sets an initial stream flow control window size to transmit to the peer.
321  void SetInitialFlowControlWindowToSend(uint32 window_bytes);
322
323  uint32 GetInitialFlowControlWindowToSend() const;
324
325  bool HasReceivedInitialFlowControlWindowBytes() const;
326
327  uint32 ReceivedInitialFlowControlWindowBytes() const;
328
329  // Sets an initial stream flow control window size to transmit to the peer.
330  void SetInitialStreamFlowControlWindowToSend(uint32 window_bytes);
331
332  uint32 GetInitialStreamFlowControlWindowToSend() const;
333
334  bool HasReceivedInitialStreamFlowControlWindowBytes() const;
335
336  uint32 ReceivedInitialStreamFlowControlWindowBytes() const;
337
338  // Sets an initial session flow control window size to transmit to the peer.
339  void SetInitialSessionFlowControlWindowToSend(uint32 window_bytes);
340
341  uint32 GetInitialSessionFlowControlWindowToSend() const;
342
343  bool HasReceivedInitialSessionFlowControlWindowBytes() const;
344
345  uint32 ReceivedInitialSessionFlowControlWindowBytes() const;
346
347  // Sets socket receive buffer to transmit to the peer.
348  void SetSocketReceiveBufferToSend(uint32 window_bytes);
349
350  uint32 GetSocketReceiveBufferToSend() const;
351
352  bool HasReceivedSocketReceiveBuffer() const;
353
354  uint32 ReceivedSocketReceiveBuffer() const;
355
356  bool negotiated();
357
358  // SetDefaults sets the members to sensible, default values.
359  void SetDefaults();
360
361  // ToHandshakeMessage serialises the settings in this object as a series of
362  // tags /value pairs and adds them to |out|.
363  void ToHandshakeMessage(CryptoHandshakeMessage* out) const;
364
365  // Calls ProcessPeerHello on each negotiable parameter. On failure returns
366  // the corresponding QuicErrorCode and sets detailed error in |error_details|.
367  QuicErrorCode ProcessPeerHello(const CryptoHandshakeMessage& peer_hello,
368                                 HelloType hello_type,
369                                 std::string* error_details);
370
371 private:
372  friend class test::QuicConfigPeer;
373
374  // Congestion control feedback type.
375  QuicNegotiableTag congestion_feedback_;
376  // Connection options.
377  QuicFixedTagVector connection_options_;
378  // Loss detection feedback type.
379  QuicFixedTag loss_detection_;
380  // Idle connection state lifetime
381  QuicNegotiableUint32 idle_connection_state_lifetime_seconds_;
382  // Keepalive timeout, or 0 to turn off keepalive probes
383  QuicNegotiableUint32 keepalive_timeout_seconds_;
384  // Maximum number of streams that the connection can support.
385  QuicNegotiableUint32 max_streams_per_connection_;
386  // Maximum time till the session can be alive before crypto handshake is
387  // finished. (Not negotiated).
388  QuicTime::Delta max_time_before_crypto_handshake_;
389  // Initial congestion window in packets.
390  QuicFixedUint32 initial_congestion_window_;
391  // Initial round trip time estimate in microseconds.
392  QuicFixedUint32 initial_round_trip_time_us_;
393
394  // TODO(rjshade): Remove when removing QUIC_VERSION_19.
395  // Initial flow control receive window in bytes.
396  QuicFixedUint32 initial_flow_control_window_bytes_;
397
398  // Initial stream flow control receive window in bytes.
399  QuicFixedUint32 initial_stream_flow_control_window_bytes_;
400  // Initial session flow control receive window in bytes.
401  QuicFixedUint32 initial_session_flow_control_window_bytes_;
402
403  // Socket receive buffer in bytes.
404  QuicFixedUint32 socket_receive_buffer_;
405};
406
407}  // namespace net
408
409#endif  // NET_QUIC_QUIC_CONFIG_H_
410