diff options
Diffstat (limited to 'net/base/client_socket_pool.h')
-rw-r--r-- | net/base/client_socket_pool.h | 133 |
1 files changed, 101 insertions, 32 deletions
diff --git a/net/base/client_socket_pool.h b/net/base/client_socket_pool.h index 6c92f37..0ee3ffe 100644 --- a/net/base/client_socket_pool.h +++ b/net/base/client_socket_pool.h @@ -12,58 +12,66 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/timer.h" +#include "net/base/address_list.h" #include "net/base/completion_callback.h" +#include "net/base/host_resolver.h" +#include "net/base/load_states.h" namespace net { class ClientSocket; +class ClientSocketFactory; class ClientSocketHandle; // A ClientSocketPool is used to restrict the number of sockets open at a time. // It also maintains a list of idle persistent sockets. // -// The ClientSocketPool allocates scoped_ptr<ClientSocket> objects, but it is -// not responsible for allocating the associated ClientSocket objects. The -// consumer must do so if it gets a scoped_ptr<ClientSocket> with a null value. -// class ClientSocketPool : public base::RefCounted<ClientSocketPool> { public: - explicit ClientSocketPool(int max_sockets_per_group); - - // Called to request a socket for the given handle. There are three possible - // results: 1) the handle will be initialized with a socket to reuse, 2) the - // handle will be initialized without a socket such that the consumer needs - // to supply a socket, or 3) the handle will be added to a wait list until a - // socket is available to reuse or the opportunity to create a new socket - // arises. The completion callback is notified in the 3rd case. |priority| - // will determine the placement into the wait list. + ClientSocketPool(int max_sockets_per_group, + ClientSocketFactory* client_socket_factory); + + // Requests a connected socket for a group_name. + // + // There are four 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. // // 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 - // ClientSocket was reused, then |handle|'s socket member will be non-NULL. - // Otherwise, the consumer will need to supply |handle| with a socket by - // allocating a new ClientSocket object and calling the |handle|'s set_socket - // method. + // ClientSocket 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 know whether or not he needs to + // perform SSL connection or tunnel setup or to request a new socket if he + // encounters an error with the reused socket. // - // If ERR_IO_PENDING is returned, then the completion callback will be called - // when |handle| has been initialized. + // If ERR_IO_PENDING is returned, then the callback will be used to notify the + // client of completion. // - int RequestSocket(ClientSocketHandle* handle, + int RequestSocket(const std::string& group_name, + const std::string& host, + int port, int priority, + ClientSocketHandle* handle, CompletionCallback* callback); // 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. - void CancelRequest(ClientSocketHandle* handle); + void CancelRequest(const std::string& group_name, + const ClientSocketHandle* handle); - // Called to release the socket member of an initialized ClientSocketHandle - // once the socket is no longer needed. If the socket member is non-null and - // still has an established connection, then it will be added to the idle set - // of sockets to be used to satisfy future RequestSocket calls. Otherwise, - // the ClientSocket is destroyed. - void ReleaseSocket(ClientSocketHandle* handle); + // 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 ClientSocket is destroyed. + void ReleaseSocket(const std::string& group_name, ClientSocket* socket); // Called to close any idle connections held by the connection manager. void CloseIdleSockets(); @@ -76,22 +84,27 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { // The total number of idle sockets in a connection group. int IdleSocketCountInGroup(const std::string& group_name) const; + // Determine the LoadState of a connecting ClientSocketHandle. + LoadState GetLoadState(const std::string& group_name, + const ClientSocketHandle* handle) const; + private: friend class base::RefCounted<ClientSocketPool>; - typedef scoped_ptr<ClientSocket> ClientSocketPtr; - // A Request is allocated per call to RequestSocket that results in // ERR_IO_PENDING. struct Request { ClientSocketHandle* handle; CompletionCallback* callback; int priority; + std::string host; + int port; + LoadState load_state; }; // Entry for a persistent socket which became idle at time |start_time|. struct IdleSocket { - ClientSocketPtr* ptr; + ClientSocket* socket; base::TimeTicks start_time; // An idle socket should be removed if it can't be reused, or has been idle @@ -105,6 +118,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { }; typedef std::deque<Request> RequestQueue; + typedef std::map<const ClientSocketHandle*, Request> RequestMap; // A Group is allocated per group_name when there are idle sockets or pending // requests. Otherwise, the Group object is removed from the map. @@ -112,11 +126,62 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { Group() : active_socket_count(0) {} std::deque<IdleSocket> idle_sockets; RequestQueue pending_requests; + RequestMap connecting_requests; int active_socket_count; }; typedef std::map<std::string, Group> GroupMap; + // ConnectingSocket handles the host resolution necessary for socket creation + // and the Connect(). + class ConnectingSocket { + public: + enum State { + STATE_RESOLVE_HOST, + STATE_CONNECT + }; + + ConnectingSocket(const std::string& group_name, + const ClientSocketHandle* handle, + ClientSocketFactory* client_socket_factory, + ClientSocketPool* pool); + ~ConnectingSocket(); + + // Begins the host resolution and the TCP connect. Returns OK on success, + // in which case |callback| is not called. On pending IO, Connect returns + // ERR_IO_PENDING and runs |callback| on completion. + int Connect(const std::string& host, + int port, + CompletionCallback* callback); + + // If Connect() returns OK, ClientSocketPool may invoke this method to get + // the ConnectingSocket to release |socket_| to be set into the + // ClientSocketHandle immediately. + ClientSocket* ReleaseSocket(); + + // Called by the ClientSocketPool to cancel this ConnectingSocket. Only + // necessary if a ClientSocketHandle is reused. + void Cancel(); + + private: + void OnIOComplete(int result); + + const std::string group_name_; + const ClientSocketHandle* const handle_; + ClientSocketFactory* const client_socket_factory_; + CompletionCallbackImpl<ConnectingSocket> callback_; + scoped_ptr<ClientSocket> socket_; + scoped_refptr<ClientSocketPool> pool_; + HostResolver resolver_; + AddressList addresses_; + bool canceled_; + + // The time the Connect() method was called (if it got called). + base::Time connect_start_time_; + + DISALLOW_COPY_AND_ASSIGN(ConnectingSocket); + }; + ~ClientSocketPool(); static void InsertRequestIntoQueue(const Request& r, @@ -131,7 +196,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { void DecrementIdleCount(); // Called via PostTask by ReleaseSocket. - void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); + void DoReleaseSocket(const std::string& group_name, ClientSocket* socket); // Called when timer_ fires. This method scans the idle sockets removing // sockets that timed out or can't be reused. @@ -139,8 +204,12 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { CleanupIdleSockets(false); } + ClientSocketFactory* const client_socket_factory_; + GroupMap group_map_; + std::map<const ClientSocketHandle*, ConnectingSocket*> connecting_socket_map_; + // Timer used to periodically prune idle sockets that timed out or can't be // reused. base::RepeatingTimer<ClientSocketPool> timer_; @@ -149,7 +218,7 @@ class ClientSocketPool : public base::RefCounted<ClientSocketPool> { int idle_socket_count_; // The maximum number of sockets kept per group. - int max_sockets_per_group_; + const int max_sockets_per_group_; DISALLOW_COPY_AND_ASSIGN(ClientSocketPool); }; |