1 // Copyright (c) 2011 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 #pragma once 8 9 #include <map> 10 #include <list> 11 #include <string> 12 13 #include "base/basictypes.h" 14 #include "base/gtest_prod_util.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/memory/scoped_ptr.h" 17 #include "net/base/cert_database.h" 18 #include "net/base/host_port_pair.h" 19 #include "net/base/ip_endpoint.h" 20 #include "net/base/net_errors.h" 21 #include "net/base/network_change_notifier.h" 22 #include "net/base/ssl_config_service.h" 23 #include "net/proxy/proxy_config.h" 24 #include "net/proxy/proxy_server.h" 25 #include "net/spdy/spdy_settings_storage.h" 26 27 namespace net { 28 29 class AddressList; 30 class BoundNetLog; 31 class ClientSocketHandle; 32 class HostResolver; 33 class HttpNetworkSession; 34 class SpdySession; 35 36 // This is a very simple pool for open SpdySessions. 37 class SpdySessionPool 38 : public NetworkChangeNotifier::IPAddressObserver, 39 public SSLConfigService::Observer, 40 public CertDatabase::Observer { 41 public: 42 explicit SpdySessionPool(HostResolver* host_resolver, 43 SSLConfigService* ssl_config_service); 44 virtual ~SpdySessionPool(); 45 46 // Either returns an existing SpdySession or creates a new SpdySession for 47 // use. 48 scoped_refptr<SpdySession> Get( 49 const HostPortProxyPair& host_port_proxy_pair, 50 const BoundNetLog& net_log); 51 52 // Set the maximum concurrent sessions per domain. 53 static void set_max_sessions_per_domain(int max) { 54 if (max >= 1) 55 g_max_sessions_per_domain = max; 56 } 57 58 // Builds a SpdySession from an existing SSL socket. Users should try 59 // calling Get() first to use an existing SpdySession so we don't get 60 // multiple SpdySessions per domain. Note that ownership of |connection| is 61 // transferred from the caller to the SpdySession. 62 // |certificate_error_code| is used to indicate the certificate error 63 // encountered when connecting the SSL socket. OK means there was no error. 64 // For testing, setting is_secure to false allows Spdy to connect with a 65 // pre-existing TCP socket. 66 // Returns OK on success, and the |spdy_session| will be provided. 67 // Returns an error on failure, and |spdy_session| will be NULL. 68 net::Error GetSpdySessionFromSocket( 69 const HostPortProxyPair& host_port_proxy_pair, 70 ClientSocketHandle* connection, 71 const BoundNetLog& net_log, 72 int certificate_error_code, 73 scoped_refptr<SpdySession>* spdy_session, 74 bool is_secure); 75 76 // TODO(willchan): Consider renaming to HasReusableSession, since perhaps we 77 // should be creating a new session. 78 bool HasSession(const HostPortProxyPair& host_port_proxy_pair) const; 79 80 // Close all SpdySessions, including any new ones created in the process of 81 // closing the current ones. 82 void CloseAllSessions(); 83 // Close only the currently existing SpdySessions. Let any new ones created 84 // continue to live. 85 void CloseCurrentSessions(); 86 // Close only the idle SpdySessions. 87 void CloseIdleSessions(); 88 89 // Removes a SpdySession from the SpdySessionPool. This should only be called 90 // by SpdySession, because otherwise session->state_ is not set to CLOSED. 91 void Remove(const scoped_refptr<SpdySession>& session); 92 93 // Creates a Value summary of the state of the spdy session pool. The caller 94 // responsible for deleting the returned value. 95 Value* SpdySessionPoolInfoToValue() const; 96 97 SpdySettingsStorage* mutable_spdy_settings() { return &spdy_settings_; } 98 const SpdySettingsStorage& spdy_settings() const { return spdy_settings_; } 99 100 // NetworkChangeNotifier::IPAddressObserver methods: 101 102 // We flush all idle sessions and release references to the active ones so 103 // they won't get re-used. The active ones will either complete successfully 104 // or error out due to the IP address change. 105 virtual void OnIPAddressChanged(); 106 107 // SSLConfigService::Observer methods: 108 109 // We perform the same flushing as described above when SSL settings change. 110 virtual void OnSSLConfigChanged(); 111 112 // A debugging mode where we compress all accesses through a single domain. 113 static void ForceSingleDomain() { g_force_single_domain = true; } 114 115 // Controls whether the pool allows use of a common session for domains 116 // which share IP address resolutions. 117 static void enable_ip_pooling(bool value) { g_enable_ip_pooling = value; } 118 119 // CertDatabase::Observer methods: 120 virtual void OnUserCertAdded(const X509Certificate* cert); 121 virtual void OnCertTrustChanged(const X509Certificate* cert); 122 123 private: 124 friend class SpdySessionPoolPeer; // For testing. 125 friend class SpdyNetworkTransactionTest; // For testing. 126 FRIEND_TEST_ALL_PREFIXES(SpdyNetworkTransactionTest, WindowUpdateOverflow); 127 128 typedef std::list<scoped_refptr<SpdySession> > SpdySessionList; 129 typedef std::map<HostPortProxyPair, SpdySessionList*> SpdySessionsMap; 130 typedef std::map<IPEndPoint, HostPortProxyPair> SpdyAliasMap; 131 132 scoped_refptr<SpdySession> GetExistingSession( 133 SpdySessionList* list, 134 const BoundNetLog& net_log) const; 135 scoped_refptr<SpdySession> GetFromAlias( 136 const HostPortProxyPair& host_port_proxy_pair, 137 const BoundNetLog& net_log, 138 bool record_histograms) const; 139 140 // Helper functions for manipulating the lists. 141 const HostPortProxyPair& NormalizeListPair( 142 const HostPortProxyPair& host_port_proxy_pair) const; 143 SpdySessionList* AddSessionList( 144 const HostPortProxyPair& host_port_proxy_pair); 145 SpdySessionList* GetSessionList( 146 const HostPortProxyPair& host_port_proxy_pair) const; 147 void RemoveSessionList(const HostPortProxyPair& host_port_proxy_pair); 148 149 // Does a DNS cache lookup for |pair|, and returns the |addresses| found. 150 // Returns true if addresses found, false otherwise. 151 bool LookupAddresses(const HostPortProxyPair& pair, 152 AddressList* addresses) const; 153 154 // Add a set of |addresses| as IP-equivalent addresses for |pair|. 155 void AddAliases(const AddressList& addresses, const HostPortProxyPair& pair); 156 157 // Remove all aliases for |pair| from the aliases table. 158 void RemoveAliases(const HostPortProxyPair& pair); 159 160 SpdySettingsStorage spdy_settings_; 161 162 // This is our weak session pool - one session per domain. 163 SpdySessionsMap sessions_; 164 // A map of IPEndPoint aliases for sessions. 165 SpdyAliasMap aliases_; 166 167 static size_t g_max_sessions_per_domain; 168 static bool g_force_single_domain; 169 static bool g_enable_ip_pooling; 170 171 const scoped_refptr<SSLConfigService> ssl_config_service_; 172 HostResolver* resolver_; 173 174 DISALLOW_COPY_AND_ASSIGN(SpdySessionPool); 175 }; 176 177 } // namespace net 178 179 #endif // NET_SPDY_SPDY_SESSION_POOL_H_ 180