summaryrefslogtreecommitdiffstats
path: root/net/base/client_socket_pool.h
diff options
context:
space:
mode:
Diffstat (limited to 'net/base/client_socket_pool.h')
-rw-r--r--net/base/client_socket_pool.h133
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);
};