diff options
author | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-06 23:57:07 +0000 |
---|---|---|
committer | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-06 23:57:07 +0000 |
commit | e1e0626250c6accd6e72168636630ce2aedf4953 (patch) | |
tree | 0b6206aac9e8140eba48f6bb1e261926d448f1eb /net/http | |
parent | 78b02d540d5d4ee753b319b4811842273be9d509 (diff) | |
download | chromium_src-e1e0626250c6accd6e72168636630ce2aedf4953.zip chromium_src-e1e0626250c6accd6e72168636630ce2aedf4953.tar.gz chromium_src-e1e0626250c6accd6e72168636630ce2aedf4953.tar.bz2 |
Rename HttpConnection to ClientSocketHandle, and rename HttpConnectionManager to ClientSocketPool.
The max number of sockets per group is now a constructor argument to ClientSocketPool.
I also changed the API on the pool to take ClientSocketHandle pointers. The former SocketHandle typedef is now a private ClientSocketPtr typedef for use within the implementation of ClientSocketPool.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@471 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r-- | net/http/http_connection.cc | 64 | ||||
-rw-r--r-- | net/http/http_connection.h | 97 | ||||
-rw-r--r-- | net/http/http_connection_manager.cc | 208 | ||||
-rw-r--r-- | net/http/http_connection_manager.h | 138 | ||||
-rw-r--r-- | net/http/http_connection_manager_unittest.cc | 271 | ||||
-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 |
8 files changed, 11 insertions, 784 deletions
diff --git a/net/http/http_connection.cc b/net/http/http_connection.cc deleted file mode 100644 index 0ca8a3d..0000000 --- a/net/http/http_connection.cc +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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.h" -#include "net/http/http_connection_manager.h" - -namespace net { - -HttpConnection::HttpConnection(HttpConnectionManager* mgr) - : mgr_(mgr), socket_(NULL) { -} - -HttpConnection::~HttpConnection() { - Reset(); -} - -int HttpConnection::Init(const std::string& group_name, - CompletionCallback* callback) { - Reset(); - group_name_ = group_name; - return mgr_->RequestSocket(group_name_, &socket_, callback); -} - -void HttpConnection::Reset() { - if (group_name_.empty()) // Was Init called? - return; - if (socket_) { - mgr_->ReleaseSocket(group_name_, socket_); - socket_ = NULL; - } else { - mgr_->CancelRequest(group_name_, &socket_); - } - group_name_.clear(); -} - -} // namespace net diff --git a/net/http/http_connection.h b/net/http/http_connection.h deleted file mode 100644 index e3a6496..0000000 --- a/net/http/http_connection.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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_ - -#include <string> - -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "net/base/client_socket.h" -#include "net/base/completion_callback.h" - -namespace net { - -class HttpConnectionManager; - -// A container for a ClientSocket, representing a HTTP connection. -// -// 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. -// -// 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. -// -class HttpConnection { - public: - explicit HttpConnection(HttpConnectionManager* mgr); - ~HttpConnection(); - - // Initializes a HttpConnection object, which involves talking to the - // HttpConnectionManager 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. - // - // This method returns ERR_IO_PENDING if it cannot complete synchronously, in - // which case the consumer should wait for the completion callback to run. - // - // Init may be called multiple times. - // - int Init(const std::string& group_name, CompletionCallback* callback); - - // An initialized connection 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. - void Reset(); - - // Returns true when Init has completed successfully. - bool is_initialized() const { return socket_ != NULL; } - - // These may only be used if is_initialized() is true. - ClientSocket* socket() { return socket_->get(); } - void set_socket(ClientSocket* s) { socket_->reset(s); } - - private: - scoped_refptr<HttpConnectionManager> mgr_; - scoped_ptr<ClientSocket>* socket_; - std::string group_name_; - - DISALLOW_EVIL_CONSTRUCTORS(HttpConnection); -}; - -} // namespace net - -#endif // NET_HTTP_HTTP_CONNECTION_H_ diff --git a/net/http/http_connection_manager.cc b/net/http/http_connection_manager.cc deleted file mode 100644 index 7064c4f..0000000 --- a/net/http/http_connection_manager.cc +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 "base/message_loop.h" -#include "net/base/client_socket.h" -#include "net/base/net_errors.h" - -namespace { - -// The timeout value, in seconds, used to clean up disconnected idle sockets. -const int kCleanupInterval = 5; - -} // namespace - -namespace net { - -HttpConnectionManager::HttpConnectionManager() - : timer_(TimeDelta::FromSeconds(kCleanupInterval)), - idle_socket_count_(0) { - timer_.set_task(this); -} - -HttpConnectionManager::~HttpConnectionManager() { - timer_.set_task(NULL); - - // Clean up any idle sockets. Assert that we have no remaining active sockets - // or pending requests. They should have all been cleaned up prior to the - // manager being destroyed. - - CloseIdleSockets(); - DCHECK(group_map_.empty()); -} - -int HttpConnectionManager::RequestSocket(const std::string& group_name, - SocketHandle** handle, - CompletionCallback* callback) { - Group& group = group_map_[group_name]; - - // Can we make another active socket now? - if (group.active_socket_count == kMaxSocketsPerGroup) { - Request r; - r.result = handle; - DCHECK(callback); - r.callback = callback; - group.pending_requests.push_back(r); - return ERR_IO_PENDING; - } - - // OK, we are going to activate one. - group.active_socket_count++; - - // 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(); - group.idle_sockets.pop_back(); - DecrementIdleCount(); - if (h->get()->IsConnected()) { - // We found one we can reuse! - *handle = h; - return OK; - } - delete h; - } - - *handle = new SocketHandle(); - return OK; -} - -void HttpConnectionManager::CancelRequest(const std::string& group_name, - SocketHandle** handle) { - Group& group = group_map_[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); - - // 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) { - group.pending_requests.erase(it); - break; - } - } -} - -void HttpConnectionManager::ReleaseSocket(const std::string& group_name, - SocketHandle* handle) { - // Run this asynchronously to allow the caller to finish before we let - // another to begin doing work. This also avoids nasty recursion issues. - MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( - this, &HttpConnectionManager::DoReleaseSocket, group_name, handle)); -} - -void HttpConnectionManager::CloseIdleSockets() { - MaybeCloseIdleSockets(false); -} - -void HttpConnectionManager::MaybeCloseIdleSockets( - bool only_if_disconnected) { - if (idle_socket_count_ == 0) - return; - - GroupMap::iterator i = group_map_.begin(); - while (i != group_map_.end()) { - Group& group = i->second; - - std::deque<SocketHandle*>::iterator j = group.idle_sockets.begin(); - while (j != group.idle_sockets.end()) { - if (!only_if_disconnected || !(*j)->get()->IsConnected()) { - delete *j; - j = group.idle_sockets.erase(j); - DecrementIdleCount(); - } else { - ++j; - } - } - - // Delete group if no longer needed. - if (group.active_socket_count == 0 && group.idle_sockets.empty()) { - DCHECK(group.pending_requests.empty()); - group_map_.erase(i++); - } else { - ++i; - } - } -} - -void HttpConnectionManager::IncrementIdleCount() { - if (++idle_socket_count_ == 1) - timer_.Start(); -} - -void HttpConnectionManager::DecrementIdleCount() { - if (--idle_socket_count_ == 0) - timer_.Stop(); -} - -void HttpConnectionManager::DoReleaseSocket(const std::string& group_name, - SocketHandle* handle) { - GroupMap::iterator i = group_map_.find(group_name); - DCHECK(i != group_map_.end()); - - Group& group = i->second; - - DCHECK(group.active_socket_count > 0); - group.active_socket_count--; - - bool can_reuse = handle->get() && handle->get()->IsConnected(); - if (can_reuse) { - group.idle_sockets.push_back(handle); - IncrementIdleCount(); - } else { - delete handle; - } - - // 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); - DCHECK(rv == OK); - r.callback->Run(rv); - return; - } - - // Delete group if no longer needed. - if (group.active_socket_count == 0 && group.idle_sockets.empty()) { - DCHECK(group.pending_requests.empty()); - group_map_.erase(i); - } -} - -void HttpConnectionManager::Run() { - MaybeCloseIdleSockets(true); -} - -} // namespace net diff --git a/net/http/http_connection_manager.h b/net/http/http_connection_manager.h deleted file mode 100644 index fc5402c..0000000 --- a/net/http/http_connection_manager.h +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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_ - -#include <deque> -#include <map> -#include <string> - -#include "base/ref_counted.h" -#include "base/timer.h" -#include "net/base/completion_callback.h" - -namespace net { - -class ClientSocket; - -// A HttpConnectionManager is used to restrict the number of HTTP 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. -// -class HttpConnectionManager : public base::RefCounted<HttpConnectionManager>, - 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. - // - // 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 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. - // - int RequestSocket(const std::string& group_name, SocketHandle** 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); - - // Called to close any idle connections held by the connection manager. - void CloseIdleSockets(); - - private: - friend class base::RefCounted<HttpConnectionManager>; - - ~HttpConnectionManager(); - - // Closes all idle sockets if |only_if_disconnected| is false. Else, only - // idle sockets that are disconnected get closed. "Maybe" refers to the - // fact that it doesn't close all idle sockets if |only_if_disconnected| is - // true. - void MaybeCloseIdleSockets(bool only_if_disconnected); - - // Called when the number of idle sockets changes. - void IncrementIdleCount(); - void DecrementIdleCount(); - - // Called via PostTask by ReleaseSocket. - void DoReleaseSocket(const std::string& group_name, SocketHandle* handle); - - // Task implementation. This method scans the idle sockets checking to see - // if any have been disconnected. - virtual void Run(); - - // A Request is allocated per call to RequestSocket that results in - // ERR_IO_PENDING. - struct Request { - SocketHandle** result; - CompletionCallback* callback; - }; - - // A Group is allocated per group_name when there are idle sockets or pending - // requests. Otherwise, the Group object is removed from the map. - struct Group { - Group() : active_socket_count(0) {} - std::deque<SocketHandle*> idle_sockets; - std::deque<Request> pending_requests; - int active_socket_count; - }; - - typedef std::map<std::string, Group> GroupMap; - GroupMap group_map_; - - // Timer used to periodically prune sockets that have been disconnected. - RepeatingTimer timer_; - - // The total number of idle sockets in the system. - int idle_socket_count_; -}; - -} // namespace net - -#endif // NET_HTTP_HTTP_CONNECTION_MANAGER_H_ diff --git a/net/http/http_connection_manager_unittest.cc b/net/http/http_connection_manager_unittest.cc deleted file mode 100644 index 503097b..0000000 --- a/net/http/http_connection_manager_unittest.cc +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 "base/message_loop.h" -#include "net/base/client_socket.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; - -class MockClientSocket : public net::ClientSocket { - public: - MockClientSocket() : connected_(false) { - allocation_count++; - } - - // ClientSocket methods: - virtual int Connect(net::CompletionCallback* callback) { - connected_ = true; - return net::OK; - } - virtual int ReconnectIgnoringLastError(net::CompletionCallback* callback) { - return net::ERR_FAILED; - } - virtual void Disconnect() { - connected_ = false; - } - virtual bool IsConnected() const { - return connected_; - } - - // Socket methods: - virtual int Read(char* buf, int buf_len, - net::CompletionCallback* callback) { - return net::ERR_FAILED; - } - virtual int Write(const char* buf, int buf_len, - net::CompletionCallback* callback) { - return net::ERR_FAILED; - } - - static int allocation_count; - - private: - bool connected_; -}; - -int MockClientSocket::allocation_count = 0; - -class TestSocketRequest : public CallbackRunner< Tuple1<int> > { - public: - TestSocketRequest() : handle(NULL) {} - - net::HttpConnectionManager::SocketHandle* handle; - - void InitHandle() { - DCHECK(handle); - if (!handle->get()) { - handle->reset(new MockClientSocket()); - handle->get()->Connect(NULL); - } - } - - virtual void RunWithParams(const Tuple1<int>& params) { - DCHECK(params.a == net::OK); - completion_count++; - InitHandle(); - } - - static int completion_count; -}; - -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(); - - TestSocketRequest r; - int rv; - - rv = mgr->RequestSocket("a", &r.handle, &r); - EXPECT_EQ(net::OK, rv); - EXPECT_TRUE(r.handle != NULL); - - CallReleaseSocket(mgr, "a", r.handle); -} - -TEST(HttpConnectionManagerTest, WithIdleConnection) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); - - TestSocketRequest r; - int rv; - - rv = mgr->RequestSocket("a", &r.handle, &r); - EXPECT_EQ(net::OK, rv); - EXPECT_TRUE(r.handle != NULL); - - r.InitHandle(); - - CallReleaseSocket(mgr, "a", r.handle); -} - -TEST(HttpConnectionManagerTest, PendingRequests) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); - - int rv; - - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; - - // Reset - MockClientSocket::allocation_count = 0; - TestSocketRequest::completion_count = 0; - - // Create connections or queue up requests. - for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); - if (rv != net::ERR_IO_PENDING) { - EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); - } - } - - // 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; - released_one = true; - } - } - } while (released_one); - - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup, - MockClientSocket::allocation_count); - EXPECT_EQ(10, TestSocketRequest::completion_count); -} - -TEST(HttpConnectionManagerTest, PendingRequests_NoKeepAlive) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); - - int rv; - - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; - - // Reset - MockClientSocket::allocation_count = 0; - TestSocketRequest::completion_count = 0; - - // Create connections or queue up requests. - for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); - if (rv != net::ERR_IO_PENDING) { - EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); - } - } - - // 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) { - reqs[i].handle->get()->Disconnect(); - CallReleaseSocket(mgr, "a", reqs[i].handle); - reqs[i].handle = NULL; - released_one = true; - } - } - } while (released_one); - - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup + 10, - MockClientSocket::allocation_count); - EXPECT_EQ(10, TestSocketRequest::completion_count); -} - -TEST(HttpConnectionManagerTest, CancelRequest) { - scoped_refptr<net::HttpConnectionManager> mgr = - new net::HttpConnectionManager(); - - int rv; - - TestSocketRequest reqs[ - net::HttpConnectionManager::kMaxSocketsPerGroup + 10]; - - // Reset - MockClientSocket::allocation_count = 0; - TestSocketRequest::completion_count = 0; - - // Create connections or queue up requests. - for (size_t i = 0; i < arraysize(reqs); ++i) { - rv = mgr->RequestSocket("a", &reqs[i].handle, &reqs[i]); - if (rv != net::ERR_IO_PENDING) { - EXPECT_EQ(net::OK, rv); - reqs[i].InitHandle(); - } - } - - // 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); - - // 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; - released_one = true; - } - } - } while (released_one); - - EXPECT_EQ(net::HttpConnectionManager::kMaxSocketsPerGroup, - MockClientSocket::allocation_count); - EXPECT_EQ(9, TestSocketRequest::completion_count); -} 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), |