diff options
-rw-r--r-- | net/base/client_socket_handle.cc (renamed from net/http/http_connection.cc) | 22 | ||||
-rw-r--r-- | net/base/client_socket_handle.h (renamed from net/http/http_connection.h) | 49 | ||||
-rw-r--r-- | net/base/client_socket_pool.cc (renamed from net/http/http_connection_manager.cc) | 71 | ||||
-rw-r--r-- | net/base/client_socket_pool.h (renamed from net/http/http_connection_manager.h) | 88 | ||||
-rw-r--r-- | net/base/client_socket_pool_unittest.cc (renamed from net/http/http_connection_manager_unittest.cc) | 153 | ||||
-rw-r--r-- | net/build/net.vcproj | 32 | ||||
-rw-r--r-- | net/build/net_unittests.vcproj | 8 | ||||
-rw-r--r-- | net/http/http_network_layer.cc | 2 | ||||
-rw-r--r-- | net/http/http_network_session.h | 13 | ||||
-rw-r--r-- | net/http/http_network_transaction.cc | 2 |
10 files changed, 231 insertions, 209 deletions
diff --git a/net/http/http_connection.cc b/net/base/client_socket_handle.cc index 0ca8a3d..a7b668e 100644 --- a/net/http/http_connection.cc +++ b/net/base/client_socket_handle.cc @@ -27,36 +27,36 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "net/http/http_connection.h" +#include "net/base/client_socket_handle.h" #include "net/base/client_socket.h" -#include "net/http/http_connection_manager.h" +#include "net/base/client_socket_pool.h" namespace net { -HttpConnection::HttpConnection(HttpConnectionManager* mgr) - : mgr_(mgr), socket_(NULL) { +ClientSocketHandle::ClientSocketHandle(ClientSocketPool* pool) + : pool_(pool), socket_(NULL) { } -HttpConnection::~HttpConnection() { +ClientSocketHandle::~ClientSocketHandle() { Reset(); } -int HttpConnection::Init(const std::string& group_name, - CompletionCallback* callback) { +int ClientSocketHandle::Init(const std::string& group_name, + CompletionCallback* callback) { Reset(); group_name_ = group_name; - return mgr_->RequestSocket(group_name_, &socket_, callback); + return pool_->RequestSocket(this, callback); } -void HttpConnection::Reset() { +void ClientSocketHandle::Reset() { if (group_name_.empty()) // Was Init called? return; if (socket_) { - mgr_->ReleaseSocket(group_name_, socket_); + pool_->ReleaseSocket(this); socket_ = NULL; } else { - mgr_->CancelRequest(group_name_, &socket_); + pool_->CancelRequest(this); } group_name_.clear(); } diff --git a/net/http/http_connection.h b/net/base/client_socket_handle.h index e3a6496..f5cab7f 100644 --- a/net/http/http_connection.h +++ b/net/base/client_socket_handle.h @@ -27,8 +27,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef NET_HTTP_HTTP_CONNECTION_H_ -#define NET_HTTP_HTTP_CONNECTION_H_ +#ifndef NET_BASE_CLIENT_SOCKET_HANDLE_H_ +#define NET_BASE_CLIENT_SOCKET_HANDLE_H_ #include <string> @@ -39,29 +39,29 @@ namespace net { -class HttpConnectionManager; +class ClientSocketPool; -// A container for a ClientSocket, representing a HTTP connection. +// A container for a connected ClientSocket. // -// The connection's |group_name| uniquely identifies the origin and type of the -// connection. It is used by the HttpConnectionManager to group similar http -// connection objects. +// The handle's |group_name| uniquely identifies the origin and type of the +// connection. It is used by the ClientSocketPool to group similar connected +// client socket objects. // -// A connection object is initialized with a null socket. It is the consumer's -// job to initialize a ClientSocket object and set it on the connection. +// A handle is initialized with a null socket. It is the consumer's job to +// initialize a ClientSocket object and set it on the handle. // -class HttpConnection { +class ClientSocketHandle { public: - explicit HttpConnection(HttpConnectionManager* mgr); - ~HttpConnection(); + explicit ClientSocketHandle(ClientSocketPool* pool); + ~ClientSocketHandle(); - // Initializes a HttpConnection object, which involves talking to the - // HttpConnectionManager to locate a socket to possibly reuse. This method + // Initializes a ClientSocketHandle object, which involves talking to the + // ClientSocketPool to locate a socket to possibly reuse. This method // returns either OK or ERR_IO_PENDING. // // If this method succeeds, then the socket member will be set to an existing // socket if an existing socket was available to reuse. Otherwise, the - // consumer should set the socket member of this connection object. + // consumer should set the socket member of this handle. // // This method returns ERR_IO_PENDING if it cannot complete synchronously, in // which case the consumer should wait for the completion callback to run. @@ -70,11 +70,14 @@ class HttpConnection { // int Init(const std::string& group_name, CompletionCallback* callback); - // An initialized connection can be reset, which causes it to return to the + // An initialized handle can be reset, which causes it to return to the // un-initialized state. This releases the underlying socket, which in the - // case of a socket that is not disconnected, indicates that the socket may - // be kept alive for use by a subsequent HttpConnection. NOTE: To prevent - // the socket from being kept alive, be sure to call its Disconnect method. + // case of a socket that still has an established connection, indicates that + // the socket may be kept alive for use by a subsequent ClientSocketHandle. + // + // NOTE: To prevent the socket from being kept alive, be sure to call its + // Disconnect method. + // void Reset(); // Returns true when Init has completed successfully. @@ -85,13 +88,15 @@ class HttpConnection { void set_socket(ClientSocket* s) { socket_->reset(s); } private: - scoped_refptr<HttpConnectionManager> mgr_; + friend class ClientSocketPool; + + scoped_refptr<ClientSocketPool> pool_; scoped_ptr<ClientSocket>* socket_; std::string group_name_; - DISALLOW_EVIL_CONSTRUCTORS(HttpConnection); + DISALLOW_COPY_AND_ASSIGN(ClientSocketHandle); }; } // namespace net -#endif // NET_HTTP_HTTP_CONNECTION_H_ +#endif // NET_BASE_CLIENT_SOCKET_HANDLE_H_ diff --git a/net/http/http_connection_manager.cc b/net/base/client_socket_pool.cc index 7064c4f..fb81dce 100644 --- a/net/http/http_connection_manager.cc +++ b/net/base/client_socket_pool.cc @@ -27,10 +27,11 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include "net/http/http_connection_manager.h" +#include "net/base/client_socket_pool.h" #include "base/message_loop.h" #include "net/base/client_socket.h" +#include "net/base/client_socket_handle.h" #include "net/base/net_errors.h" namespace { @@ -42,13 +43,14 @@ const int kCleanupInterval = 5; namespace net { -HttpConnectionManager::HttpConnectionManager() +ClientSocketPool::ClientSocketPool(int max_sockets_per_group) : timer_(TimeDelta::FromSeconds(kCleanupInterval)), - idle_socket_count_(0) { + idle_socket_count_(0), + max_sockets_per_group_(max_sockets_per_group) { timer_.set_task(this); } -HttpConnectionManager::~HttpConnectionManager() { +ClientSocketPool::~ClientSocketPool() { timer_.set_task(NULL); // Clean up any idle sockets. Assert that we have no remaining active sockets @@ -59,15 +61,14 @@ HttpConnectionManager::~HttpConnectionManager() { DCHECK(group_map_.empty()); } -int HttpConnectionManager::RequestSocket(const std::string& group_name, - SocketHandle** handle, - CompletionCallback* callback) { - Group& group = group_map_[group_name]; +int ClientSocketPool::RequestSocket(ClientSocketHandle* handle, + CompletionCallback* callback) { + Group& group = group_map_[handle->group_name_]; // Can we make another active socket now? - if (group.active_socket_count == kMaxSocketsPerGroup) { + if (group.active_socket_count == max_sockets_per_group_) { Request r; - r.result = handle; + r.handle = handle; DCHECK(callback); r.callback = callback; group.pending_requests.push_back(r); @@ -80,53 +81,53 @@ int HttpConnectionManager::RequestSocket(const std::string& group_name, // Use idle sockets in LIFO order because they're more likely to be // still connected. while (!group.idle_sockets.empty()) { - SocketHandle* h = group.idle_sockets.back(); + ClientSocketPtr* ptr = group.idle_sockets.back(); group.idle_sockets.pop_back(); DecrementIdleCount(); - if (h->get()->IsConnected()) { + if ((*ptr)->IsConnected()) { // We found one we can reuse! - *handle = h; + handle->socket_ = ptr; return OK; } - delete h; + delete ptr; } - *handle = new SocketHandle(); + handle->socket_ = new ClientSocketPtr(); return OK; } -void HttpConnectionManager::CancelRequest(const std::string& group_name, - SocketHandle** handle) { - Group& group = group_map_[group_name]; +void ClientSocketPool::CancelRequest(ClientSocketHandle* handle) { + Group& group = group_map_[handle->group_name_]; // In order for us to be canceling a pending request, we must have active // sockets equaling the limit. NOTE: The correctness of the code doesn't // require this assertion. - DCHECK(group.active_socket_count == kMaxSocketsPerGroup); + DCHECK(group.active_socket_count == max_sockets_per_group_); // Search pending_requests for matching handle. std::deque<Request>::iterator it = group.pending_requests.begin(); for (; it != group.pending_requests.end(); ++it) { - if (it->result == handle) { + if (it->handle == handle) { group.pending_requests.erase(it); break; } } } -void HttpConnectionManager::ReleaseSocket(const std::string& group_name, - SocketHandle* handle) { +void ClientSocketPool::ReleaseSocket(ClientSocketHandle* handle) { // Run this asynchronously to allow the caller to finish before we let // another to begin doing work. This also avoids nasty recursion issues. + // NOTE: We cannot refer to the handle argument after this method returns. MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( - this, &HttpConnectionManager::DoReleaseSocket, group_name, handle)); + this, &ClientSocketPool::DoReleaseSocket, handle->group_name_, + handle->socket_)); } -void HttpConnectionManager::CloseIdleSockets() { +void ClientSocketPool::CloseIdleSockets() { MaybeCloseIdleSockets(false); } -void HttpConnectionManager::MaybeCloseIdleSockets( +void ClientSocketPool::MaybeCloseIdleSockets( bool only_if_disconnected) { if (idle_socket_count_ == 0) return; @@ -135,7 +136,7 @@ void HttpConnectionManager::MaybeCloseIdleSockets( while (i != group_map_.end()) { Group& group = i->second; - std::deque<SocketHandle*>::iterator j = group.idle_sockets.begin(); + std::deque<ClientSocketPtr*>::iterator j = group.idle_sockets.begin(); while (j != group.idle_sockets.end()) { if (!only_if_disconnected || !(*j)->get()->IsConnected()) { delete *j; @@ -156,18 +157,18 @@ void HttpConnectionManager::MaybeCloseIdleSockets( } } -void HttpConnectionManager::IncrementIdleCount() { +void ClientSocketPool::IncrementIdleCount() { if (++idle_socket_count_ == 1) timer_.Start(); } -void HttpConnectionManager::DecrementIdleCount() { +void ClientSocketPool::DecrementIdleCount() { if (--idle_socket_count_ == 0) timer_.Stop(); } -void HttpConnectionManager::DoReleaseSocket(const std::string& group_name, - SocketHandle* handle) { +void ClientSocketPool::DoReleaseSocket(const std::string& group_name, + ClientSocketPtr* ptr) { GroupMap::iterator i = group_map_.find(group_name); DCHECK(i != group_map_.end()); @@ -176,19 +177,19 @@ void HttpConnectionManager::DoReleaseSocket(const std::string& group_name, DCHECK(group.active_socket_count > 0); group.active_socket_count--; - bool can_reuse = handle->get() && handle->get()->IsConnected(); + bool can_reuse = ptr->get() && (*ptr)->IsConnected(); if (can_reuse) { - group.idle_sockets.push_back(handle); + group.idle_sockets.push_back(ptr); IncrementIdleCount(); } else { - delete handle; + delete ptr; } // Process one pending request. if (!group.pending_requests.empty()) { Request r = group.pending_requests.front(); group.pending_requests.pop_front(); - int rv = RequestSocket(i->first, r.result, NULL); + int rv = RequestSocket(r.handle, NULL); DCHECK(rv == OK); r.callback->Run(rv); return; @@ -201,7 +202,7 @@ void HttpConnectionManager::DoReleaseSocket(const std::string& group_name, } } -void HttpConnectionManager::Run() { +void ClientSocketPool::Run() { MaybeCloseIdleSockets(true); } diff --git a/net/http/http_connection_manager.h b/net/base/client_socket_pool.h index fc5402c..1f43166 100644 --- a/net/http/http_connection_manager.h +++ b/net/base/client_socket_pool.h @@ -27,8 +27,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#ifndef NET_HTTP_HTTP_CONNECTION_MANAGER_H_ -#define NET_HTTP_HTTP_CONNECTION_MANAGER_H_ +#ifndef NET_BASE_CLIENT_SOCKET_POOL_H_ +#define NET_BASE_CLIENT_SOCKET_POOL_H_ #include <deque> #include <map> @@ -41,54 +41,61 @@ namespace net { class ClientSocket; +class ClientSocketHandle; -// A HttpConnectionManager is used to restrict the number of HTTP sockets -// open at a time. It also maintains a list of idle persistent sockets. +// A ClientSocketPool is used to restrict the number of sockets open at a time. +// It also maintains a list of idle persistent sockets. // -// The HttpConnectionManager allocates SocketHandle objects, but it is not -// responsible for allocating the associated ClientSocket objects. The -// consumer must do so if it gets a SocketHandle with a null ClientSocket. +// 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 HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, - public Task { +class ClientSocketPool : public base::RefCounted<ClientSocketPool>, + public Task { public: - HttpConnectionManager(); - - // The maximum number of simultaneous sockets per group. - enum { kMaxSocketsPerGroup = 6 }; - - typedef scoped_ptr<ClientSocket> SocketHandle; - - // Called to get access to a SocketHandle object for the given group name. + 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. // - // If this function returns OK, then |*handle| will reference a SocketHandle - // object. If ERR_IO_PENDING is returned, then the completion callback will - // be called when |*handle| has been populated. + // 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. // - // If the resultant SocketHandle object has a null member, then it is the - // caller's job to create a ClientSocket and associate it with the handle. + // If ERR_IO_PENDING is returned, then the completion callback will be called + // when |handle| has been initialized. // - int RequestSocket(const std::string& group_name, SocketHandle** handle, - CompletionCallback* callback); + int RequestSocket(ClientSocketHandle* handle, CompletionCallback* callback); // Called to cancel a RequestSocket call that returned ERR_IO_PENDING. The - // same group_name and handle parameters must be passed to this method as - // were passed to the RequestSocket call being cancelled. The associated - // CompletionCallback is not run. - void CancelRequest(const std::string& group_name, SocketHandle** handle); - - // Called to release a SocketHandle object that is no longer in use. If the - // handle has a ClientSocket that is still connected, then this handle may be - // added to the keep-alive set of sockets. - void ReleaseSocket(const std::string& group_name, SocketHandle* handle); + // 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); + + // 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 close any idle connections held by the connection manager. void CloseIdleSockets(); private: - friend class base::RefCounted<HttpConnectionManager>; + friend class base::RefCounted<ClientSocketPool>; + + typedef scoped_ptr<ClientSocket> ClientSocketPtr; - ~HttpConnectionManager(); + ~ClientSocketPool(); // Closes all idle sockets if |only_if_disconnected| is false. Else, only // idle sockets that are disconnected get closed. "Maybe" refers to the @@ -101,7 +108,7 @@ class HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, void DecrementIdleCount(); // Called via PostTask by ReleaseSocket. - void DoReleaseSocket(const std::string& group_name, SocketHandle* handle); + void DoReleaseSocket(const std::string& group_name, ClientSocketPtr* ptr); // Task implementation. This method scans the idle sockets checking to see // if any have been disconnected. @@ -110,7 +117,7 @@ class HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, // A Request is allocated per call to RequestSocket that results in // ERR_IO_PENDING. struct Request { - SocketHandle** result; + ClientSocketHandle* handle; CompletionCallback* callback; }; @@ -118,7 +125,7 @@ class HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, // requests. Otherwise, the Group object is removed from the map. struct Group { Group() : active_socket_count(0) {} - std::deque<SocketHandle*> idle_sockets; + std::deque<ClientSocketPtr*> idle_sockets; std::deque<Request> pending_requests; int active_socket_count; }; @@ -131,8 +138,11 @@ class HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, // The total number of idle sockets in the system. int idle_socket_count_; + + // The maximum number of sockets kept per group. + int max_sockets_per_group_; }; } // namespace net -#endif // NET_HTTP_HTTP_CONNECTION_MANAGER_H_ +#endif // NET_BASE_CLIENT_SOCKET_POOL_H_ diff --git a/net/http/http_connection_manager_unittest.cc b/net/base/client_socket_pool_unittest.cc index 503097b..8a89e6d 100644 --- a/net/http/http_connection_manager_unittest.cc +++ b/net/base/client_socket_pool_unittest.cc @@ -29,13 +29,16 @@ #include "base/message_loop.h" #include "net/base/client_socket.h" +#include "net/base/client_socket_handle.h" +#include "net/base/client_socket_pool.h" #include "net/base/net_errors.h" -#include "net/http/http_connection_manager.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -typedef testing::Test HttpConnectionManagerTest; +typedef testing::Test ClientSocketPoolTest; + +const int kMaxSocketsPerGroup = 6; class MockClientSocket : public net::ClientSocket { public: @@ -78,22 +81,22 @@ int MockClientSocket::allocation_count = 0; class TestSocketRequest : public CallbackRunner< Tuple1<int> > { public: - TestSocketRequest() : handle(NULL) {} + TestSocketRequest(net::ClientSocketPool* pool) : handle(pool) {} - net::HttpConnectionManager::SocketHandle* handle; + net::ClientSocketHandle handle; - void InitHandle() { - DCHECK(handle); - if (!handle->get()) { - handle->reset(new MockClientSocket()); - handle->get()->Connect(NULL); + void EnsureSocket() { + DCHECK(handle.is_initialized()); + if (!handle.socket()) { + handle.set_socket(new MockClientSocket()); + handle.socket()->Connect(NULL); } } virtual void RunWithParams(const Tuple1<int>& params) { DCHECK(params.a == net::OK); completion_count++; - InitHandle(); + EnsureSocket(); } static int completion_count; @@ -101,56 +104,56 @@ class TestSocketRequest : public CallbackRunner< Tuple1<int> > { int TestSocketRequest::completion_count = 0; -// Call ReleaseSocket and wait for it to complete. It runs via PostTask, so we -// can just empty the MessageLoop to ensure that ReleaseSocket finished. -void CallReleaseSocket(net::HttpConnectionManager* connection_mgr, - const std::string& group_name, - net::HttpConnectionManager::SocketHandle* handle) { - connection_mgr->ReleaseSocket(group_name, handle); - MessageLoop::current()->Quit(); - MessageLoop::current()->Run(); -} - } // namespace -TEST(HttpConnectionManagerTest, Basic) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); +TEST(ClientSocketPoolTest, Basic) { + scoped_refptr<net::ClientSocketPool> pool = + new net::ClientSocketPool(kMaxSocketsPerGroup); - TestSocketRequest r; + TestSocketRequest r(pool); int rv; - rv = mgr->RequestSocket("a", &r.handle, &r); + rv = r.handle.Init("a", &r); EXPECT_EQ(net::OK, rv); - EXPECT_TRUE(r.handle != NULL); + EXPECT_TRUE(r.handle.is_initialized()); - CallReleaseSocket(mgr, "a", r.handle); + r.handle.Reset(); + + // The handle's Reset method may have posted a task. + MessageLoop::current()->RunAllPending(); } -TEST(HttpConnectionManagerTest, WithIdleConnection) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); +TEST(ClientSocketPoolTest, WithIdleConnection) { + scoped_refptr<net::ClientSocketPool> pool = + new net::ClientSocketPool(kMaxSocketsPerGroup); - TestSocketRequest r; + TestSocketRequest r(pool); int rv; - rv = mgr->RequestSocket("a", &r.handle, &r); + rv = r.handle.Init("a", &r); EXPECT_EQ(net::OK, rv); - EXPECT_TRUE(r.handle != NULL); + EXPECT_TRUE(r.handle.is_initialized()); + + // Create a socket. + r.EnsureSocket(); - r.InitHandle(); + // Release the socket. It should find its way into the idle list. We're + // testing that this does not trigger a crash. + r.handle.Reset(); - CallReleaseSocket(mgr, "a", r.handle); + // The handle's Reset method may have posted a task. + MessageLoop::current()->RunAllPending(); } -TEST(HttpConnectionManagerTest, PendingRequests) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); +TEST(ClientSocketPoolTest, PendingRequests) { + scoped_refptr<net::ClientSocketPool> pool = + new net::ClientSocketPool(kMaxSocketsPerGroup); int rv; - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; + scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; + for (size_t i = 0; i < arraysize(reqs); ++i) + reqs[i].reset(new TestSocketRequest(pool)); // Reset MockClientSocket::allocation_count = 0; @@ -158,10 +161,10 @@ TEST(HttpConnectionManagerTest, PendingRequests) { // Create connections or queue up requests. for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); + rv = reqs[i]->handle.Init("a", reqs[i].get()); if (rv != net::ERR_IO_PENDING) { EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); + reqs[i]->EnsureSocket(); } } @@ -170,27 +173,27 @@ TEST(HttpConnectionManagerTest, PendingRequests) { do { released_one = false; for (size_t i = 0; i < arraysize(reqs); ++i) { - if (reqs[i].handle) { - CallReleaseSocket(mgr, "a", reqs[i].handle); - reqs[i].handle = NULL; + if (reqs[i]->handle.is_initialized()) { + reqs[i]->handle.Reset(); + MessageLoop::current()->RunAllPending(); released_one = true; } } } while (released_one); - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup, - MockClientSocket::allocation_count); + EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); EXPECT_EQ(10, TestSocketRequest::completion_count); } -TEST(HttpConnectionManagerTest, PendingRequests_NoKeepAlive) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); +TEST(ClientSocketPoolTest, PendingRequests_NoKeepAlive) { + scoped_refptr<net::ClientSocketPool> pool = + new net::ClientSocketPool(kMaxSocketsPerGroup); int rv; - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; + scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; + for (size_t i = 0; i < arraysize(reqs); ++i) + reqs[i].reset(new TestSocketRequest(pool)); // Reset MockClientSocket::allocation_count = 0; @@ -198,10 +201,10 @@ TEST(HttpConnectionManagerTest, PendingRequests_NoKeepAlive) { // Create connections or queue up requests. for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); + rv = reqs[i]->handle.Init("a", reqs[i].get()); if (rv != net::ERR_IO_PENDING) { EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); + reqs[i]->EnsureSocket(); } } @@ -210,28 +213,28 @@ TEST(HttpConnectionManagerTest, PendingRequests_NoKeepAlive) { do { released_one = false; for (size_t i = 0; i < arraysize(reqs); ++i) { - if (reqs[i].handle) { - reqs[i].handle->get()->Disconnect(); - CallReleaseSocket(mgr, "a", reqs[i].handle); - reqs[i].handle = NULL; + if (reqs[i]->handle.is_initialized()) { + reqs[i]->handle.socket()->Disconnect(); + reqs[i]->handle.Reset(); + MessageLoop::current()->RunAllPending(); released_one = true; } } } while (released_one); - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup + 10, - MockClientSocket::allocation_count); + EXPECT_EQ(kMaxSocketsPerGroup + 10, MockClientSocket::allocation_count); EXPECT_EQ(10, TestSocketRequest::completion_count); } -TEST(HttpConnectionManagerTest, CancelRequest) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); +TEST(ClientSocketPoolTest, CancelRequest) { + scoped_refptr<net::ClientSocketPool> pool = + new net::ClientSocketPool(kMaxSocketsPerGroup); int rv; - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; + scoped_ptr<TestSocketRequest> reqs[kMaxSocketsPerGroup + 10]; + for (size_t i = 0; i < arraysize(reqs); ++i) + reqs[i].reset(new TestSocketRequest(pool)); // Reset MockClientSocket::allocation_count = 0; @@ -239,33 +242,31 @@ TEST(HttpConnectionManagerTest, CancelRequest) { // Create connections or queue up requests. for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); + rv = reqs[i]->handle.Init("a", reqs[i].get()); if (rv != net::ERR_IO_PENDING) { EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); + reqs[i]->EnsureSocket(); } } // Cancel a request. - size_t index_to_cancel = - net::HttpConnectionManager::kMaxSocketsPerGroup + 2; - EXPECT_TRUE(reqs[index_to_cancel].handle == NULL); - mgr->CancelRequest("a", &reqs[index_to_cancel].handle); + size_t index_to_cancel = kMaxSocketsPerGroup + 2; + EXPECT_TRUE(!reqs[index_to_cancel]->handle.is_initialized()); + reqs[index_to_cancel]->handle.Reset(); // Release any connections until we have no connections. bool released_one; do { released_one = false; for (size_t i = 0; i < arraysize(reqs); ++i) { - if (reqs[i].handle) { - CallReleaseSocket(mgr, "a", reqs[i].handle); - reqs[i].handle = NULL; + if (reqs[i]->handle.is_initialized()) { + reqs[i]->handle.Reset(); + MessageLoop::current()->RunAllPending(); released_one = true; } } } while (released_one); - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup, - MockClientSocket::allocation_count); + EXPECT_EQ(kMaxSocketsPerGroup, MockClientSocket::allocation_count); EXPECT_EQ(9, TestSocketRequest::completion_count); } diff --git a/net/build/net.vcproj b/net/build/net.vcproj index 8329527..3da1c7b 100644 --- a/net/build/net.vcproj +++ b/net/build/net.vcproj @@ -189,6 +189,22 @@ > </File> <File + RelativePath="..\base\client_socket_handle.cc" + > + </File> + <File + RelativePath="..\base\client_socket_handle.h" + > + </File> + <File + RelativePath="..\base\client_socket_pool.cc" + > + </File> + <File + RelativePath="..\base\client_socket_pool.h" + > + </File> + <File RelativePath="..\base\completion_callback.h" > </File> @@ -637,22 +653,6 @@ > </File> <File - RelativePath="..\http\http_connection.cc" - > - </File> - <File - RelativePath="..\http\http_connection.h" - > - </File> - <File - RelativePath="..\http\http_connection_manager.cc" - > - </File> - <File - RelativePath="..\http\http_connection_manager.h" - > - </File> - <File RelativePath="..\http\http_network_layer.cc" > </File> diff --git a/net/build/net_unittests.vcproj b/net/build/net_unittests.vcproj index d31226e..3426bf0 100644 --- a/net/build/net_unittests.vcproj +++ b/net/build/net_unittests.vcproj @@ -235,10 +235,6 @@ > </File> <File - RelativePath="..\http\http_connection_manager_unittest.cc" - > - </File> - <File RelativePath="..\http\http_network_layer_unittest.cc" > </File> @@ -295,6 +291,10 @@ > </File> <File + RelativePath="..\base\client_socket_pool_unittest.cc" + > + </File> + <File RelativePath="..\base\cookie_monster_unittest.cc" > </File> diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc index 2fd846c..426b987 100644 --- a/net/http/http_network_layer.cc +++ b/net/http/http_network_layer.cc @@ -93,7 +93,7 @@ void HttpNetworkLayer::Suspend(bool suspend) { suspended_ = suspend; if (suspend) - session_->connection_manager()->CloseIdleSockets(); + session_->connection_pool()->CloseIdleSockets(); } } // namespace net diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index dc31ed1..58cbb2f 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -32,7 +32,7 @@ #include "base/ref_counted.h" #include "net/base/auth_cache.h" -#include "net/http/http_connection_manager.h" +#include "net/base/client_socket_pool.h" #include "net/http/http_proxy_service.h" namespace net { @@ -40,19 +40,24 @@ namespace net { // This class holds session objects used by HttpNetworkTransaction objects. class HttpNetworkSession : public base::RefCounted<HttpNetworkSession> { public: + // Allow up to 6 connections per host. + enum { + MAX_SOCKETS_PER_GROUP = 6 + }; + HttpNetworkSession(HttpProxyResolver* proxy_resolver) - : connection_manager_(new HttpConnectionManager()), + : connection_pool_(new ClientSocketPool(MAX_SOCKETS_PER_GROUP)), proxy_resolver_(proxy_resolver), proxy_service_(proxy_resolver) { } AuthCache* auth_cache() { return &auth_cache_; } - HttpConnectionManager* connection_manager() { return connection_manager_; } + ClientSocketPool* connection_pool() { return connection_pool_; } HttpProxyService* proxy_service() { return &proxy_service_; } private: AuthCache auth_cache_; - scoped_refptr<HttpConnectionManager> connection_manager_; + scoped_refptr<ClientSocketPool> connection_pool_; scoped_ptr<HttpProxyResolver> proxy_resolver_; HttpProxyService proxy_service_; }; diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 807c87d..1d45191 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc @@ -60,7 +60,7 @@ HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session, request_(NULL), pac_request_(NULL), socket_factory_(csf), - connection_(session->connection_manager()), + connection_(session->connection_pool()), reused_socket_(false), using_ssl_(false), using_proxy_(false), |