1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef NET_SPDY_SPDY_SESSION_POOL_H_
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define NET_SPDY_SPDY_SESSION_POOL_H_
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <map>
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <list>
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/gtest_prod_util.h"
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/cert_database.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/ip_endpoint.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_errors.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/network_change_notifier.h"
223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/ssl_config_service.h"
233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/proxy/proxy_config.h"
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/proxy/proxy_server.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_settings_storage.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass AddressList;
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BoundNetLog;
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ClientSocketHandle;
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass HostResolver;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass HttpNetworkSession;
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdySession;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is a very simple pool for open SpdySessions.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SpdySessionPool
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : public NetworkChangeNotifier::IPAddressObserver,
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      public SSLConfigService::Observer,
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      public CertDatabase::Observer {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  explicit SpdySessionPool(HostResolver* host_resolver,
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                           SSLConfigService* ssl_config_service);
44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual ~SpdySessionPool();
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Either returns an existing SpdySession or creates a new SpdySession for
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // use.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<SpdySession> Get(
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HostPortProxyPair& host_port_proxy_pair,
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BoundNetLog& net_log);
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the maximum concurrent sessions per domain.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static void set_max_sessions_per_domain(int max) {
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (max >= 1)
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      g_max_sessions_per_domain = max;
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Builds a SpdySession from an existing SSL socket.  Users should try
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // calling Get() first to use an existing SpdySession so we don't get
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // multiple SpdySessions per domain.  Note that ownership of |connection| is
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // transferred from the caller to the SpdySession.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |certificate_error_code| is used to indicate the certificate error
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // encountered when connecting the SSL socket.  OK means there was no error.
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // For testing, setting is_secure to false allows Spdy to connect with a
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // pre-existing TCP socket.
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns OK on success, and the |spdy_session| will be provided.
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns an error on failure, and |spdy_session| will be NULL.
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::Error GetSpdySessionFromSocket(
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HostPortProxyPair& host_port_proxy_pair,
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ClientSocketHandle* connection,
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const BoundNetLog& net_log,
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int certificate_error_code,
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      scoped_refptr<SpdySession>* spdy_session,
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      bool is_secure);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(willchan): Consider renaming to HasReusableSession, since perhaps we
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // should be creating a new session.
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  bool HasSession(const HostPortProxyPair& host_port_proxy_pair) const;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Close all SpdySessions, including any new ones created in the process of
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // closing the current ones.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CloseAllSessions();
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Close only the currently existing SpdySessions. Let any new ones created
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // continue to live.
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void CloseCurrentSessions();
8693a4a82bca0155ddfbec36777ade7d6dad6bfb61Kristian Monsen  // Close only the idle SpdySessions.
8793a4a82bca0155ddfbec36777ade7d6dad6bfb61Kristian Monsen  void CloseIdleSessions();
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Removes a SpdySession from the SpdySessionPool. This should only be called
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // by SpdySession, because otherwise session->state_ is not set to CLOSED.
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Remove(const scoped_refptr<SpdySession>& session);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Creates a Value summary of the state of the spdy session pool. The caller
94731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // responsible for deleting the returned value.
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Value* SpdySessionPoolInfoToValue() const;
96731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySettingsStorage* mutable_spdy_settings() { return &spdy_settings_; }
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const SpdySettingsStorage& spdy_settings() const { return spdy_settings_; }
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // NetworkChangeNotifier::IPAddressObserver methods:
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We flush all idle sessions and release references to the active ones so
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // they won't get re-used.  The active ones will either complete successfully
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // or error out due to the IP address change.
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void OnIPAddressChanged();
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // SSLConfigService::Observer methods:
1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We perform the same flushing as described above when SSL settings change.
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual void OnSSLConfigChanged();
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // A debugging mode where we compress all accesses through a single domain.
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static void ForceSingleDomain() { g_force_single_domain = true; }
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Controls whether the pool allows use of a common session for domains
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // which share IP address resolutions.
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static void enable_ip_pooling(bool value) { g_enable_ip_pooling = value; }
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // CertDatabase::Observer methods:
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnUserCertAdded(const X509Certificate* cert);
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void OnCertTrustChanged(const X509Certificate* cert);
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class SpdySessionPoolPeer;  // For testing.
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class SpdyNetworkTransactionTest;  // For testing.
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateOverflow);
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::list<scoped_refptr<SpdySession> > SpdySessionList;
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  typedef std::map<HostPortProxyPair, SpdySessionList*> SpdySessionsMap;
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  typedef std::map<IPEndPoint, HostPortProxyPair> SpdyAliasMap;
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<SpdySession> GetExistingSession(
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      SpdySessionList* list,
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const BoundNetLog& net_log) const;
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scoped_refptr<SpdySession> GetFromAlias(
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const HostPortProxyPair& host_port_proxy_pair,
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      const BoundNetLog& net_log,
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bool record_histograms) const;
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Helper functions for manipulating the lists.
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const HostPortProxyPair& NormalizeListPair(
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      const HostPortProxyPair& host_port_proxy_pair) const;
1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySessionList* AddSessionList(
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HostPortProxyPair& host_port_proxy_pair);
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SpdySessionList* GetSessionList(
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const HostPortProxyPair& host_port_proxy_pair) const;
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void RemoveSessionList(const HostPortProxyPair& host_port_proxy_pair);
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Does a DNS cache lookup for |pair|, and returns the |addresses| found.
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Returns true if addresses found, false otherwise.
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool LookupAddresses(const HostPortProxyPair& pair,
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                       AddressList* addresses) const;
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Add a set of |addresses| as IP-equivalent addresses for |pair|.
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void AddAliases(const AddressList& addresses, const HostPortProxyPair& pair);
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Remove all aliases for |pair| from the aliases table.
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void RemoveAliases(const HostPortProxyPair& pair);
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SpdySettingsStorage spdy_settings_;
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is our weak session pool - one session per domain.
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SpdySessionsMap sessions_;
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // A map of IPEndPoint aliases for sessions.
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  SpdyAliasMap aliases_;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static size_t g_max_sessions_per_domain;
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static bool g_force_single_domain;
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static bool g_enable_ip_pooling;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  const scoped_refptr<SSLConfigService> ssl_config_service_;
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  HostResolver* resolver_;
1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(SpdySessionPool);
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // NET_SPDY_SPDY_SESSION_POOL_H_
180