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_SPDY_SPDY_SESSION_POOL_H_
6#define NET_SPDY_SPDY_SESSION_POOL_H_
7
8#include <map>
9#include <set>
10#include <string>
11#include <vector>
12
13#include "base/basictypes.h"
14#include "base/gtest_prod_util.h"
15#include "base/memory/ref_counted.h"
16#include "base/memory/weak_ptr.h"
17#include "net/base/host_port_pair.h"
18#include "net/base/ip_endpoint.h"
19#include "net/base/net_errors.h"
20#include "net/base/net_export.h"
21#include "net/base/network_change_notifier.h"
22#include "net/cert/cert_database.h"
23#include "net/proxy/proxy_config.h"
24#include "net/proxy/proxy_server.h"
25#include "net/socket/next_proto.h"
26#include "net/spdy/spdy_session_key.h"
27#include "net/ssl/ssl_config_service.h"
28
29namespace net {
30
31class AddressList;
32class BoundNetLog;
33class ClientSocketHandle;
34class HostResolver;
35class HttpServerProperties;
36class SpdySession;
37class TransportSecurityState;
38
39// This is a very simple pool for open SpdySessions.
40class NET_EXPORT SpdySessionPool
41    : public NetworkChangeNotifier::IPAddressObserver,
42      public SSLConfigService::Observer,
43      public CertDatabase::Observer {
44 public:
45  typedef base::TimeTicks (*TimeFunc)(void);
46
47  // |default_protocol| may be kProtoUnknown (e.g., if SPDY is
48  // disabled), in which case it's set to a default value. Otherwise,
49  // it must be a SPDY protocol.
50  SpdySessionPool(
51      HostResolver* host_resolver,
52      SSLConfigService* ssl_config_service,
53      const base::WeakPtr<HttpServerProperties>& http_server_properties,
54      TransportSecurityState* transport_security_state,
55      bool force_single_domain,
56      bool enable_compression,
57      bool enable_ping_based_connection_checking,
58      NextProto default_protocol,
59      size_t stream_initial_recv_window_size,
60      size_t initial_max_concurrent_streams,
61      size_t max_concurrent_streams_limit,
62      SpdySessionPool::TimeFunc time_func,
63      const std::string& trusted_spdy_proxy);
64  virtual ~SpdySessionPool();
65
66  // In the functions below, a session is "available" if this pool has
67  // a reference to it and there is some SpdySessionKey for which
68  // FindAvailableSession() will return it. A session is "unavailable"
69  // if this pool has a reference to it but it won't be returned by
70  // FindAvailableSession() for any SpdySessionKey; for example, this
71  // can happen when a session receives a GOAWAY frame and is still
72  // processing existing streams.
73
74  // Create a new SPDY session from an existing socket.  There must
75  // not already be a session for the given key. This pool must have
76  // been constructed with a valid |default_protocol| value.
77  //
78  // |is_secure| can be false for testing or when SPDY is configured
79  // to work with non-secure sockets. If |is_secure| is true,
80  // |certificate_error_code| indicates that the certificate error
81  // encountered when connecting the SSL socket, with OK meaning there
82  // was no error.
83  //
84  // Returns the new SpdySession. Note that the SpdySession begins reading from
85  // |connection| on a subsequent event loop iteration, so it may be closed
86  // immediately afterwards if the first read of |connection| fails.
87  base::WeakPtr<SpdySession> CreateAvailableSessionFromSocket(
88      const SpdySessionKey& key,
89      scoped_ptr<ClientSocketHandle> connection,
90      const BoundNetLog& net_log,
91      int certificate_error_code,
92      bool is_secure);
93
94  // Find an available session for the given key, or NULL if there isn't one.
95  base::WeakPtr<SpdySession> FindAvailableSession(const SpdySessionKey& key,
96                                                  const BoundNetLog& net_log);
97
98  // Remove all mappings and aliases for the given session, which must
99  // still be available. Except for in tests, this must be called by
100  // the given session itself.
101  void MakeSessionUnavailable(
102      const base::WeakPtr<SpdySession>& available_session);
103
104  // Removes an unavailable session from the pool.  Except for in
105  // tests, this must be called by the given session itself.
106  void RemoveUnavailableSession(
107      const base::WeakPtr<SpdySession>& unavailable_session);
108
109  // Close only the currently existing SpdySessions with |error|.
110  // Let any new ones created while this method is running continue to
111  // live.
112  void CloseCurrentSessions(net::Error error);
113
114  // Close only the currently existing SpdySessions that are idle.
115  // Let any new ones created while this method is running continue to
116  // live.
117  void CloseCurrentIdleSessions();
118
119  // Close all SpdySessions, including any new ones created in the process of
120  // closing the current ones.
121  void CloseAllSessions();
122
123  // Creates a Value summary of the state of the spdy session pool. The caller
124  // responsible for deleting the returned value.
125  base::Value* SpdySessionPoolInfoToValue() const;
126
127  base::WeakPtr<HttpServerProperties> http_server_properties() {
128    return http_server_properties_;
129  }
130
131  // NetworkChangeNotifier::IPAddressObserver methods:
132
133  // We flush all idle sessions and release references to the active ones so
134  // they won't get re-used.  The active ones will either complete successfully
135  // or error out due to the IP address change.
136  virtual void OnIPAddressChanged() OVERRIDE;
137
138  // SSLConfigService::Observer methods:
139
140  // We perform the same flushing as described above when SSL settings change.
141  virtual void OnSSLConfigChanged() OVERRIDE;
142
143  // CertDatabase::Observer methods:
144
145  // We perform the same flushing as described above when certificate database
146  // is changed.
147  virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
148  virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
149
150 private:
151  friend class SpdySessionPoolPeer;  // For testing.
152
153  typedef std::set<SpdySession*> SessionSet;
154  typedef std::vector<base::WeakPtr<SpdySession> > WeakSessionList;
155  typedef std::map<SpdySessionKey, base::WeakPtr<SpdySession> >
156      AvailableSessionMap;
157  typedef std::map<IPEndPoint, SpdySessionKey> AliasMap;
158
159  // Returns true iff |session| is in |available_sessions_|.
160  bool IsSessionAvailable(const base::WeakPtr<SpdySession>& session) const;
161
162  // Returns a normalized version of the given key suitable for lookup
163  // into |available_sessions_|.
164  const SpdySessionKey& NormalizeListKey(const SpdySessionKey& key) const;
165
166  // Map the given key to the given session. There must not already be
167  // a mapping for |key|.
168  void MapKeyToAvailableSession(const SpdySessionKey& key,
169                                const base::WeakPtr<SpdySession>& session);
170
171  // Returns an iterator into |available_sessions_| for the given key,
172  // which may be equal to |available_sessions_.end()|.
173  AvailableSessionMap::iterator LookupAvailableSessionByKey(
174      const SpdySessionKey& key);
175
176  // Remove the mapping of the given key, which must exist.
177  void UnmapKey(const SpdySessionKey& key);
178
179  // Remove all aliases for |key| from the aliases table.
180  void RemoveAliases(const SpdySessionKey& key);
181
182  // Get a copy of the current sessions as a list of WeakPtrs. Used by
183  // CloseCurrentSessionsHelper() below.
184  WeakSessionList GetCurrentSessions() const;
185
186  // Close only the currently existing SpdySessions with |error|.  Let
187  // any new ones created while this method is running continue to
188  // live. If |idle_only| is true only idle sessions are closed.
189  void CloseCurrentSessionsHelper(
190      Error error,
191      const std::string& description,
192      bool idle_only);
193
194  const base::WeakPtr<HttpServerProperties> http_server_properties_;
195
196  TransportSecurityState* transport_security_state_;
197
198  // The set of all sessions. This is a superset of the sessions in
199  // |available_sessions_|.
200  //
201  // |sessions_| owns all its SpdySession objects.
202  SessionSet sessions_;
203
204  // This is a map of available sessions by key. A session may appear
205  // more than once in this map if it has aliases.
206  AvailableSessionMap available_sessions_;
207
208  // A map of IPEndPoint aliases for sessions.
209  AliasMap aliases_;
210
211  static bool g_force_single_domain;
212
213  const scoped_refptr<SSLConfigService> ssl_config_service_;
214  HostResolver* const resolver_;
215
216  // Defaults to true. May be controlled via SpdySessionPoolPeer for tests.
217  bool verify_domain_authentication_;
218  bool enable_sending_initial_data_;
219  bool force_single_domain_;
220  bool enable_compression_;
221  bool enable_ping_based_connection_checking_;
222  const NextProto default_protocol_;
223  size_t stream_initial_recv_window_size_;
224  size_t initial_max_concurrent_streams_;
225  size_t max_concurrent_streams_limit_;
226  TimeFunc time_func_;
227
228  // This SPDY proxy is allowed to push resources from origins that are
229  // different from those of their associated streams.
230  HostPortPair trusted_spdy_proxy_;
231
232  DISALLOW_COPY_AND_ASSIGN(SpdySessionPool);
233};
234
235}  // namespace net
236
237#endif  // NET_SPDY_SPDY_SESSION_POOL_H_
238