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_SOCKET_CLIENT_SOCKET_POOL_H_ 6 #define NET_SOCKET_CLIENT_SOCKET_POOL_H_ 7 8 #include <deque> 9 #include <string> 10 11 #include "base/basictypes.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/template_util.h" 15 #include "base/time/time.h" 16 #include "net/base/completion_callback.h" 17 #include "net/base/load_states.h" 18 #include "net/base/net_export.h" 19 #include "net/base/request_priority.h" 20 #include "net/dns/host_resolver.h" 21 22 namespace base { 23 class DictionaryValue; 24 } 25 26 namespace net { 27 28 class ClientSocketHandle; 29 class ClientSocketPoolHistograms; 30 class StreamSocket; 31 32 // ClientSocketPools are layered. This defines an interface for lower level 33 // socket pools to communicate with higher layer pools. 34 class NET_EXPORT HigherLayeredPool { 35 public: 36 virtual ~HigherLayeredPool() {} 37 38 // Instructs the HigherLayeredPool to close an idle connection. Return true if 39 // one was closed. Closing an idle connection will call into the lower layer 40 // pool it came from, so must be careful of re-entrancy when using this. 41 virtual bool CloseOneIdleConnection() = 0; 42 }; 43 44 // ClientSocketPools are layered. This defines an interface for higher level 45 // socket pools to communicate with lower layer pools. 46 class NET_EXPORT LowerLayeredPool { 47 public: 48 virtual ~LowerLayeredPool() {} 49 50 // Returns true if a there is currently a request blocked on the per-pool 51 // (not per-host) max socket limit, either in this pool, or one that it is 52 // layered on top of. 53 virtual bool IsStalled() const = 0; 54 55 // Called to add or remove a higher layer pool on top of |this|. A higher 56 // layer pool may be added at most once to |this|, and must be removed prior 57 // to destruction of |this|. 58 virtual void AddHigherLayeredPool(HigherLayeredPool* higher_pool) = 0; 59 virtual void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) = 0; 60 }; 61 62 // A ClientSocketPool is used to restrict the number of sockets open at a time. 63 // It also maintains a list of idle persistent sockets. 64 // 65 class NET_EXPORT ClientSocketPool : public LowerLayeredPool { 66 public: 67 // Subclasses must also have an inner class SocketParams which is 68 // the type for the |params| argument in RequestSocket() and 69 // RequestSockets() below. 70 71 // Requests a connected socket for a group_name. 72 // 73 // There are five possible results from calling this function: 74 // 1) RequestSocket returns OK and initializes |handle| with a reused socket. 75 // 2) RequestSocket returns OK with a newly connected socket. 76 // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a 77 // wait list until a socket is available to reuse or a new socket finishes 78 // connecting. |priority| will determine the placement into the wait list. 79 // 4) An error occurred early on, so RequestSocket returns an error code. 80 // 5) A recoverable error occurred while setting up the socket. An error 81 // code is returned, but the |handle| is initialized with the new socket. 82 // The caller must recover from the error before using the connection, or 83 // Disconnect the socket before releasing or resetting the |handle|. 84 // The current recoverable errors are: the errors accepted by 85 // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or 86 // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool. 87 // 88 // If this function returns OK, then |handle| is initialized upon return. 89 // The |handle|'s is_initialized method will return true in this case. If a 90 // StreamSocket was reused, then ClientSocketPool will call 91 // |handle|->set_reused(true). In either case, the socket will have been 92 // allocated and will be connected. A client might want to know whether or 93 // not the socket is reused in order to request a new socket if he encounters 94 // an error with the reused socket. 95 // 96 // If ERR_IO_PENDING is returned, then the callback will be used to notify the 97 // client of completion. 98 // 99 // Profiling information for the request is saved to |net_log| if non-NULL. 100 virtual int RequestSocket(const std::string& group_name, 101 const void* params, 102 RequestPriority priority, 103 ClientSocketHandle* handle, 104 const CompletionCallback& callback, 105 const BoundNetLog& net_log) = 0; 106 107 // RequestSockets is used to request that |num_sockets| be connected in the 108 // connection group for |group_name|. If the connection group already has 109 // |num_sockets| idle sockets / active sockets / currently connecting sockets, 110 // then this function doesn't do anything. Otherwise, it will start up as 111 // many connections as necessary to reach |num_sockets| total sockets for the 112 // group. It uses |params| to control how to connect the sockets. The 113 // ClientSocketPool will assign a priority to the new connections, if any. 114 // This priority will probably be lower than all others, since this method 115 // is intended to make sure ahead of time that |num_sockets| sockets are 116 // available to talk to a host. 117 virtual void RequestSockets(const std::string& group_name, 118 const void* params, 119 int num_sockets, 120 const BoundNetLog& net_log) = 0; 121 122 // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The 123 // same handle parameter must be passed to this method as was passed to the 124 // RequestSocket call being cancelled. The associated CompletionCallback is 125 // not run. However, for performance, we will let one ConnectJob complete 126 // and go idle. 127 virtual void CancelRequest(const std::string& group_name, 128 ClientSocketHandle* handle) = 0; 129 130 // Called to release a socket once the socket is no longer needed. If the 131 // socket still has an established connection, then it will be added to the 132 // set of idle sockets to be used to satisfy future RequestSocket calls. 133 // Otherwise, the StreamSocket is destroyed. |id| is used to differentiate 134 // between updated versions of the same pool instance. The pool's id will 135 // change when it flushes, so it can use this |id| to discard sockets with 136 // mismatched ids. 137 virtual void ReleaseSocket(const std::string& group_name, 138 scoped_ptr<StreamSocket> socket, 139 int id) = 0; 140 141 // This flushes all state from the ClientSocketPool. This means that all 142 // idle and connecting sockets are discarded with the given |error|. 143 // Active sockets being held by ClientSocketPool clients will be discarded 144 // when released back to the pool. 145 // Does not flush any pools wrapped by |this|. 146 virtual void FlushWithError(int error) = 0; 147 148 // Called to close any idle connections held by the connection manager. 149 virtual void CloseIdleSockets() = 0; 150 151 // The total number of idle sockets in the pool. 152 virtual int IdleSocketCount() const = 0; 153 154 // The total number of idle sockets in a connection group. 155 virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0; 156 157 // Determine the LoadState of a connecting ClientSocketHandle. 158 virtual LoadState GetLoadState(const std::string& group_name, 159 const ClientSocketHandle* handle) const = 0; 160 161 // Retrieves information on the current state of the pool as a 162 // DictionaryValue. Caller takes possession of the returned value. 163 // If |include_nested_pools| is true, the states of any nested 164 // ClientSocketPools will be included. 165 virtual base::DictionaryValue* GetInfoAsValue( 166 const std::string& name, 167 const std::string& type, 168 bool include_nested_pools) const = 0; 169 170 // Returns the maximum amount of time to wait before retrying a connect. 171 static const int kMaxConnectRetryIntervalMs = 250; 172 173 // The set of histograms specific to this pool. We can't use the standard 174 // UMA_HISTOGRAM_* macros because they are callsite static. 175 virtual ClientSocketPoolHistograms* histograms() const = 0; 176 177 static base::TimeDelta unused_idle_socket_timeout(); 178 static void set_unused_idle_socket_timeout(base::TimeDelta timeout); 179 180 static base::TimeDelta used_idle_socket_timeout(); 181 static void set_used_idle_socket_timeout(base::TimeDelta timeout); 182 183 protected: 184 ClientSocketPool(); 185 virtual ~ClientSocketPool(); 186 187 // Return the connection timeout for this pool. 188 virtual base::TimeDelta ConnectionTimeout() const = 0; 189 190 private: 191 DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); 192 }; 193 194 template <typename PoolType> 195 void RequestSocketsForPool( 196 PoolType* pool, 197 const std::string& group_name, 198 const scoped_refptr<typename PoolType::SocketParams>& params, 199 int num_sockets, 200 const BoundNetLog& net_log) { 201 pool->RequestSockets(group_name, ¶ms, num_sockets, net_log); 202 } 203 204 } // namespace net 205 206 #endif // NET_SOCKET_CLIENT_SOCKET_POOL_H_ 207