| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_H_ | |
| #define NET_SOCKET_CLIENT_SOCKET_POOL_H_ | |
| #include <deque> | |
| #include <string> | |
| #include "base/basictypes.h" | |
| #include "base/memory/ref_counted.h" | |
| #include "base/time.h" | |
| #include "base/template_util.h" | |
| #include "net/base/completion_callback.h" | |
| #include "net/base/host_resolver.h" | |
| #include "net/base/load_states.h" | |
| #include "net/base/net_export.h" | |
| #include "net/base/request_priority.h" | |
| namespace base { | |
| class DictionaryValue; | |
| } | |
| namespace net { | |
| class ClientSocketHandle; | |
| class ClientSocketPoolHistograms; | |
| class StreamSocket; | |
| // ClientSocketPools are layered. This defines an interface for lower level | |
| // socket pools to communicate with higher layer pools. | |
| class NET_EXPORT LayeredPool { | |
| public: | |
| virtual ~LayeredPool() {}; | |
| // Instructs the LayeredPool to close an idle connection. Return true if one | |
| // was closed. | |
| virtual bool CloseOneIdleConnection() = 0; | |
| }; | |
| // A ClientSocketPool is used to restrict the number of sockets open at a time. | |
| // It also maintains a list of idle persistent sockets. | |
| // | |
| class NET_EXPORT ClientSocketPool { | |
| public: | |
| // Requests a connected socket for a group_name. | |
| // | |
| // There are five possible results from calling this function: | |
| // 1) RequestSocket returns OK and initializes |handle| with a reused socket. | |
| // 2) RequestSocket returns OK with a newly connected socket. | |
| // 3) RequestSocket returns ERR_IO_PENDING. The handle will be added to a | |
| // wait list until a socket is available to reuse or a new socket finishes | |
| // connecting. |priority| will determine the placement into the wait list. | |
| // 4) An error occurred early on, so RequestSocket returns an error code. | |
| // 5) A recoverable error occurred while setting up the socket. An error | |
| // code is returned, but the |handle| is initialized with the new socket. | |
| // The caller must recover from the error before using the connection, or | |
| // Disconnect the socket before releasing or resetting the |handle|. | |
| // The current recoverable errors are: the errors accepted by | |
| // IsCertificateError(err) and PROXY_AUTH_REQUESTED, or | |
| // HTTPS_PROXY_TUNNEL_RESPONSE when reported by HttpProxyClientSocketPool. | |
| // | |
| // If this function returns OK, then |handle| is initialized upon return. | |
| // The |handle|'s is_initialized method will return true in this case. If a | |
| // StreamSocket was reused, then ClientSocketPool will call | |
| // |handle|->set_reused(true). In either case, the socket will have been | |
| // allocated and will be connected. A client might want to know whether or | |
| // not the socket is reused in order to request a new socket if he encounters | |
| // an error with the reused socket. | |
| // | |
| // If ERR_IO_PENDING is returned, then the callback will be used to notify the | |
| // client of completion. | |
| // | |
| // Profiling information for the request is saved to |net_log| if non-NULL. | |
| virtual int RequestSocket(const std::string& group_name, | |
| const void* params, | |
| RequestPriority priority, | |
| ClientSocketHandle* handle, | |
| const CompletionCallback& callback, | |
| const BoundNetLog& net_log) = 0; | |
| // RequestSockets is used to request that |num_sockets| be connected in the | |
| // connection group for |group_name|. If the connection group already has | |
| // |num_sockets| idle sockets / active sockets / currently connecting sockets, | |
| // then this function doesn't do anything. Otherwise, it will start up as | |
| // many connections as necessary to reach |num_sockets| total sockets for the | |
| // group. It uses |params| to control how to connect the sockets. The | |
| // ClientSocketPool will assign a priority to the new connections, if any. | |
| // This priority will probably be lower than all others, since this method | |
| // is intended to make sure ahead of time that |num_sockets| sockets are | |
| // available to talk to a host. | |
| virtual void RequestSockets(const std::string& group_name, | |
| const void* params, | |
| int num_sockets, | |
| const BoundNetLog& net_log) = 0; | |
| // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The | |
| // same handle parameter must be passed to this method as was passed to the | |
| // RequestSocket call being cancelled. The associated CompletionCallback is | |
| // not run. However, for performance, we will let one ConnectJob complete | |
| // and go idle. | |
| virtual void CancelRequest(const std::string& group_name, | |
| ClientSocketHandle* handle) = 0; | |
| // Called to release a socket once the socket is no longer needed. If the | |
| // socket still has an established connection, then it will be added to the | |
| // set of idle sockets to be used to satisfy future RequestSocket calls. | |
| // Otherwise, the StreamSocket is destroyed. |id| is used to differentiate | |
| // between updated versions of the same pool instance. The pool's id will | |
| // change when it flushes, so it can use this |id| to discard sockets with | |
| // mismatched ids. | |
| virtual void ReleaseSocket(const std::string& group_name, | |
| StreamSocket* socket, | |
| int id) = 0; | |
| // This flushes all state from the ClientSocketPool. This means that all | |
| // idle and connecting sockets are discarded with the given |error|. | |
| // Active sockets being held by ClientSocketPool clients will be discarded | |
| // when released back to the pool. | |
| // Does not flush any pools wrapped by |this|. | |
| virtual void FlushWithError(int error) = 0; | |
| // Returns true if a there is currently a request blocked on the | |
| // per-pool (not per-host) max socket limit. | |
| virtual bool IsStalled() const = 0; | |
| // Called to close any idle connections held by the connection manager. | |
| virtual void CloseIdleSockets() = 0; | |
| // The total number of idle sockets in the pool. | |
| virtual int IdleSocketCount() const = 0; | |
| // The total number of idle sockets in a connection group. | |
| virtual int IdleSocketCountInGroup(const std::string& group_name) const = 0; | |
| // Determine the LoadState of a connecting ClientSocketHandle. | |
| virtual LoadState GetLoadState(const std::string& group_name, | |
| const ClientSocketHandle* handle) const = 0; | |
| // Adds a LayeredPool on top of |this|. | |
| virtual void AddLayeredPool(LayeredPool* layered_pool) = 0; | |
| // Removes a LayeredPool from |this|. | |
| virtual void RemoveLayeredPool(LayeredPool* layered_pool) = 0; | |
| // Retrieves information on the current state of the pool as a | |
| // DictionaryValue. Caller takes possession of the returned value. | |
| // If |include_nested_pools| is true, the states of any nested | |
| // ClientSocketPools will be included. | |
| virtual base::DictionaryValue* GetInfoAsValue( | |
| const std::string& name, | |
| const std::string& type, | |
| bool include_nested_pools) const = 0; | |
| // Returns the maximum amount of time to wait before retrying a connect. | |
| static const int kMaxConnectRetryIntervalMs = 250; | |
| // The set of histograms specific to this pool. We can't use the standard | |
| // UMA_HISTOGRAM_* macros because they are callsite static. | |
| virtual ClientSocketPoolHistograms* histograms() const = 0; | |
| static base::TimeDelta unused_idle_socket_timeout(); | |
| static void set_unused_idle_socket_timeout(base::TimeDelta timeout); | |
| static base::TimeDelta used_idle_socket_timeout(); | |
| static void set_used_idle_socket_timeout(base::TimeDelta timeout); | |
| protected: | |
| ClientSocketPool(); | |
| virtual ~ClientSocketPool(); | |
| // Return the connection timeout for this pool. | |
| virtual base::TimeDelta ConnectionTimeout() const = 0; | |
| private: | |
| DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); | |
| }; | |
| // ClientSocketPool subclasses should indicate valid SocketParams via the | |
| // REGISTER_SOCKET_PARAMS_FOR_POOL macro below. By default, any given | |
| // <PoolType,SocketParams> pair will have its SocketParamsTrait inherit from | |
| // base::false_type, but REGISTER_SOCKET_PARAMS_FOR_POOL will specialize that | |
| // pairing to inherit from base::true_type. This provides compile time | |
| // verification that the correct SocketParams type is used with the appropriate | |
| // PoolType. | |
| template <typename PoolType, typename SocketParams> | |
| struct SocketParamTraits : public base::false_type { | |
| }; | |
| template <typename PoolType, typename SocketParams> | |
| void CheckIsValidSocketParamsForPool() { | |
| COMPILE_ASSERT(!base::is_pointer<scoped_refptr<SocketParams> >::value, | |
| socket_params_cannot_be_pointer); | |
| COMPILE_ASSERT((SocketParamTraits<PoolType, | |
| scoped_refptr<SocketParams> >::value), | |
| invalid_socket_params_for_pool); | |
| } | |
| // Provides an empty definition for CheckIsValidSocketParamsForPool() which | |
| // should be optimized out by the compiler. | |
| #define REGISTER_SOCKET_PARAMS_FOR_POOL(pool_type, socket_params) \ | |
| template<> \ | |
| struct SocketParamTraits<pool_type, scoped_refptr<socket_params> > \ | |
| : public base::true_type { \ | |
| } | |
| template <typename PoolType, typename SocketParams> | |
| void RequestSocketsForPool(PoolType* pool, | |
| const std::string& group_name, | |
| const scoped_refptr<SocketParams>& params, | |
| int num_sockets, | |
| const BoundNetLog& net_log) { | |
| CheckIsValidSocketParamsForPool<PoolType, SocketParams>(); | |
| pool->RequestSockets(group_name, ¶ms, num_sockets, net_log); | |
| } | |
| } // namespace net | |
| #endif // NET_SOCKET_CLIENT_SOCKET_POOL_H_ |