| Index: net/base/client_socket_pool.h
|
| diff --git a/net/base/client_socket_pool.h b/net/base/client_socket_pool.h
|
| index 6c92f37ac0d6c35f9ba2213eb727469c1a8b51e9..0ee3ffecf484f3b05e240fa1f49fd71bfee11d07 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);
|
| };
|
|
|