1// Copyright (c) 2012 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_STREAM_FACTORY_H_
6#define NET_QUIC_QUIC_STREAM_FACTORY_H_
7
8#include <list>
9#include <map>
10#include <string>
11#include <vector>
12
13#include "base/logging.h"
14#include "base/memory/weak_ptr.h"
15#include "net/base/address_list.h"
16#include "net/base/completion_callback.h"
17#include "net/base/host_port_pair.h"
18#include "net/base/net_log.h"
19#include "net/base/network_change_notifier.h"
20#include "net/cert/cert_database.h"
21#include "net/proxy/proxy_server.h"
22#include "net/quic/quic_config.h"
23#include "net/quic/quic_crypto_stream.h"
24#include "net/quic/quic_http_stream.h"
25#include "net/quic/quic_protocol.h"
26
27namespace net {
28
29class CertVerifier;
30class ChannelIDService;
31class ClientSocketFactory;
32class HostResolver;
33class HttpServerProperties;
34class QuicClock;
35class QuicClientSession;
36class QuicConnectionHelper;
37class QuicCryptoClientStreamFactory;
38class QuicRandom;
39class QuicServerInfoFactory;
40class QuicServerId;
41class QuicStreamFactory;
42class TransportSecurityState;
43
44namespace test {
45class QuicStreamFactoryPeer;
46}  // namespace test
47
48// Encapsulates a pending request for a QuicHttpStream.
49// If the request is still pending when it is destroyed, it will
50// cancel the request with the factory.
51class NET_EXPORT_PRIVATE QuicStreamRequest {
52 public:
53  explicit QuicStreamRequest(QuicStreamFactory* factory);
54  ~QuicStreamRequest();
55
56  // For http, |is_https| is false.
57  int Request(const HostPortPair& host_port_pair,
58              bool is_https,
59              PrivacyMode privacy_mode,
60              base::StringPiece method,
61              const BoundNetLog& net_log,
62              const CompletionCallback& callback);
63
64  void OnRequestComplete(int rv);
65
66  scoped_ptr<QuicHttpStream> ReleaseStream();
67
68  void set_stream(scoped_ptr<QuicHttpStream> stream);
69
70  const BoundNetLog& net_log() const{
71    return net_log_;
72  }
73
74 private:
75  QuicStreamFactory* factory_;
76  HostPortPair host_port_pair_;
77  bool is_https_;
78  BoundNetLog net_log_;
79  CompletionCallback callback_;
80  scoped_ptr<QuicHttpStream> stream_;
81
82  DISALLOW_COPY_AND_ASSIGN(QuicStreamRequest);
83};
84
85// A factory for creating new QuicHttpStreams on top of a pool of
86// QuicClientSessions.
87class NET_EXPORT_PRIVATE QuicStreamFactory
88    : public NetworkChangeNotifier::IPAddressObserver,
89      public CertDatabase::Observer {
90 public:
91  QuicStreamFactory(
92      HostResolver* host_resolver,
93      ClientSocketFactory* client_socket_factory,
94      base::WeakPtr<HttpServerProperties> http_server_properties,
95      CertVerifier* cert_verifier,
96      ChannelIDService* channel_id_service,
97      TransportSecurityState* transport_security_state,
98      QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
99      QuicRandom* random_generator,
100      QuicClock* clock,
101      size_t max_packet_length,
102      const std::string& user_agent_id,
103      const QuicVersionVector& supported_versions,
104      bool enable_port_selection,
105      bool enable_time_based_loss_detection,
106      bool always_require_handshake_confirmation,
107      bool disable_connection_pooling,
108      const QuicTagVector& connection_options);
109  virtual ~QuicStreamFactory();
110
111  // Creates a new QuicHttpStream to |host_port_pair| which will be
112  // owned by |request|. |is_https| specifies if the protocol is https or not.
113  // If a matching session already exists, this method will return OK.  If no
114  // matching session exists, this will return ERR_IO_PENDING and will invoke
115  // OnRequestComplete asynchronously.
116  int Create(const HostPortPair& host_port_pair,
117             bool is_https,
118             PrivacyMode privacy_mode,
119             base::StringPiece method,
120             const BoundNetLog& net_log,
121             QuicStreamRequest* request);
122
123  // Called by a session when it becomes idle.
124  void OnIdleSession(QuicClientSession* session);
125
126  // Called by a session when it is going away and no more streams should be
127  // created on it.
128  void OnSessionGoingAway(QuicClientSession* session);
129
130  // Called by a session after it shuts down.
131  void OnSessionClosed(QuicClientSession* session);
132
133  // Called by a session whose connection has timed out.
134  void OnSessionConnectTimeout(QuicClientSession* session);
135
136  // Cancels a pending request.
137  void CancelRequest(QuicStreamRequest* request);
138
139  // Closes all current sessions.
140  void CloseAllSessions(int error);
141
142  base::Value* QuicStreamFactoryInfoToValue() const;
143
144  // Delete all cached state objects in |crypto_config_|.
145  void ClearCachedStatesInCryptoConfig();
146
147  // NetworkChangeNotifier::IPAddressObserver methods:
148
149  // Until the servers support roaming, close all connections when the local
150  // IP address changes.
151  virtual void OnIPAddressChanged() OVERRIDE;
152
153  // CertDatabase::Observer methods:
154
155  // We close all sessions when certificate database is changed.
156  virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
157  virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
158
159  bool require_confirmation() const {
160    return require_confirmation_;
161  }
162
163  void set_require_confirmation(bool require_confirmation);
164
165  QuicConnectionHelper* helper() { return helper_.get(); }
166
167  bool enable_port_selection() const { return enable_port_selection_; }
168
169  bool has_quic_server_info_factory() {
170    return quic_server_info_factory_ != NULL;
171  }
172
173  void set_quic_server_info_factory(
174      QuicServerInfoFactory* quic_server_info_factory) {
175    DCHECK(!quic_server_info_factory_);
176    quic_server_info_factory_ = quic_server_info_factory;
177  }
178
179 private:
180  class Job;
181  friend class test::QuicStreamFactoryPeer;
182
183  // The key used to find session by ip. Includes
184  // the ip address, port, and scheme.
185  struct NET_EXPORT_PRIVATE IpAliasKey {
186    IpAliasKey();
187    IpAliasKey(IPEndPoint ip_endpoint, bool is_https);
188    ~IpAliasKey();
189
190    IPEndPoint ip_endpoint;
191    bool is_https;
192
193    // Needed to be an element of std::set.
194    bool operator<(const IpAliasKey &other) const;
195    bool operator==(const IpAliasKey &other) const;
196  };
197
198  typedef std::map<QuicServerId, QuicClientSession*> SessionMap;
199  typedef std::map<QuicClientSession*, QuicServerId> SessionIdMap;
200  typedef std::set<QuicServerId> AliasSet;
201  typedef std::map<QuicClientSession*, AliasSet> SessionAliasMap;
202  typedef std::set<QuicClientSession*> SessionSet;
203  typedef std::map<IpAliasKey, SessionSet> IPAliasMap;
204  typedef std::map<QuicServerId, QuicCryptoClientConfig*> CryptoConfigMap;
205  typedef std::map<QuicServerId, Job*> JobMap;
206  typedef std::map<QuicStreamRequest*, Job*> RequestMap;
207  typedef std::set<QuicStreamRequest*> RequestSet;
208  typedef std::map<Job*, RequestSet> JobRequestsMap;
209
210  // Returns a newly created QuicHttpStream owned by the caller, if a
211  // matching session already exists.  Returns NULL otherwise.
212  scoped_ptr<QuicHttpStream> CreateIfSessionExists(const QuicServerId& key,
213                                                   const BoundNetLog& net_log);
214
215  bool OnResolution(const QuicServerId& server_id,
216                    const AddressList& address_list);
217  void OnJobComplete(Job* job, int rv);
218  bool HasActiveSession(const QuicServerId& server_id) const;
219  bool HasActiveJob(const QuicServerId& server_id) const;
220  int CreateSession(const QuicServerId& server_id,
221                    scoped_ptr<QuicServerInfo> quic_server_info,
222                    const AddressList& address_list,
223                    const BoundNetLog& net_log,
224                    QuicClientSession** session);
225  void ActivateSession(const QuicServerId& key,
226                       QuicClientSession* session);
227
228  // Initializes the cached state associated with |server_id| in
229  // |crypto_config_| with the information in |server_info|.
230  void InitializeCachedStateInCryptoConfig(
231      const QuicServerId& server_id,
232      const scoped_ptr<QuicServerInfo>& server_info);
233
234  void ProcessGoingAwaySession(QuicClientSession* session,
235                               const QuicServerId& server_id,
236                               bool was_session_active);
237
238  bool require_confirmation_;
239  HostResolver* host_resolver_;
240  ClientSocketFactory* client_socket_factory_;
241  base::WeakPtr<HttpServerProperties> http_server_properties_;
242  TransportSecurityState* transport_security_state_;
243  QuicServerInfoFactory* quic_server_info_factory_;
244  QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
245  QuicRandom* random_generator_;
246  scoped_ptr<QuicClock> clock_;
247  const size_t max_packet_length_;
248
249  // The helper used for all connections.
250  scoped_ptr<QuicConnectionHelper> helper_;
251
252  // Contains owning pointers to all sessions that currently exist.
253  SessionIdMap all_sessions_;
254  // Contains non-owning pointers to currently active session
255  // (not going away session, once they're implemented).
256  SessionMap active_sessions_;
257  // Map from session to set of aliases that this session is known by.
258  SessionAliasMap session_aliases_;
259  // Map from IP address to sessions which are connected to this address.
260  IPAliasMap ip_aliases_;
261
262  // Origins which have gone away recently.
263  AliasSet gone_away_aliases_;
264
265  const QuicConfig config_;
266  QuicCryptoClientConfig crypto_config_;
267
268  JobMap active_jobs_;
269  JobRequestsMap job_requests_map_;
270  RequestMap active_requests_;
271
272  QuicVersionVector supported_versions_;
273
274  // Determine if we should consistently select a client UDP port. If false,
275  // then we will just let the OS select a random client port for each new
276  // connection.
277  bool enable_port_selection_;
278
279  // Set if we always require handshake confirmation. If true, this will
280  // introduce at least one RTT for the handshake before the client sends data.
281  bool always_require_handshake_confirmation_;
282
283  // Set if we do not want connection pooling.
284  bool disable_connection_pooling_;
285
286  // Each profile will (probably) have a unique port_seed_ value.  This value is
287  // used to help seed a pseudo-random number generator (PortSuggester) so that
288  // we consistently (within this profile) suggest the same ephemeral port when
289  // we re-connect to any given server/port.  The differences between profiles
290  // (probablistically) prevent two profiles from colliding in their ephemeral
291  // port requests.
292  uint64 port_seed_;
293
294  // Local address of socket that was created in CreateSession.
295  IPEndPoint local_address_;
296  bool check_persisted_supports_quic_;
297
298  base::WeakPtrFactory<QuicStreamFactory> weak_factory_;
299
300  DISALLOW_COPY_AND_ASSIGN(QuicStreamFactory);
301};
302
303}  // namespace net
304
305#endif  // NET_QUIC_QUIC_STREAM_FACTORY_H_
306