diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-21 21:08:35 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-21 21:08:35 +0000 |
commit | 100d5fb906712b03495b961c35f9c9b21381a74a (patch) | |
tree | 284b84c9e6baba6da57427243a8b7729f67cb132 /net/socket | |
parent | 92683b5a068ab7c7f58251dbee9b047314977bae (diff) | |
download | chromium_src-100d5fb906712b03495b961c35f9c9b21381a74a.zip chromium_src-100d5fb906712b03495b961c35f9c9b21381a74a.tar.gz chromium_src-100d5fb906712b03495b961c35f9c9b21381a74a.tar.bz2 |
Detects network changes. Only for Mac OS X so far. Hooks up TCPClientSocketPool to flush idle sockets on IP address change.
BUG=http://crbug.com/26156
TEST=Run chrome with both network cable and wireless on. Go to www.google.com, twice. Verify second time via chrome://net-internals that the second request did not need a TCP_CONNECT_JOB, since we reused idle sockets. Unplug network cable. This should flush idle sockets. Go back to www.google.com. Check chrome://net-internals. Verify that there is a TCP_CONNECT_JOB for that request, because there was no idle socket to reuse.
Review URL: http://codereview.chromium.org/460149
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35107 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r-- | net/socket/client_socket_pool_base.cc | 16 | ||||
-rw-r--r-- | net/socket/client_socket_pool_base.h | 38 | ||||
-rw-r--r-- | net/socket/client_socket_pool_base_unittest.cc | 2 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_pool.cc | 6 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_pool.h | 10 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_pool_unittest.cc | 32 |
6 files changed, 81 insertions, 23 deletions
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc index 9701937..44e2187 100644 --- a/net/socket/client_socket_pool_base.cc +++ b/net/socket/client_socket_pool_base.cc @@ -100,7 +100,8 @@ ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( int max_sockets_per_group, base::TimeDelta unused_idle_socket_timeout, base::TimeDelta used_idle_socket_timeout, - ConnectJobFactory* connect_job_factory) + ConnectJobFactory* connect_job_factory, + const scoped_refptr<NetworkChangeNotifier>& network_change_notifier) : idle_socket_count_(0), connecting_socket_count_(0), handed_out_socket_count_(0), @@ -109,9 +110,13 @@ ClientSocketPoolBaseHelper::ClientSocketPoolBaseHelper( unused_idle_socket_timeout_(unused_idle_socket_timeout), used_idle_socket_timeout_(used_idle_socket_timeout), may_have_stalled_group_(false), - connect_job_factory_(connect_job_factory) { + connect_job_factory_(connect_job_factory), + network_change_notifier_(network_change_notifier) { DCHECK_LE(0, max_sockets_per_group); DCHECK_LE(max_sockets_per_group, max_sockets); + + if (network_change_notifier_) + network_change_notifier_->AddObserver(this); } ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { @@ -123,6 +128,9 @@ ClientSocketPoolBaseHelper::~ClientSocketPoolBaseHelper() { CloseIdleSockets(); DCHECK(group_map_.empty()); DCHECK(connect_job_map_.empty()); + + if (network_change_notifier_) + network_change_notifier_->RemoveObserver(this); } // InsertRequestIntoQueue inserts the request into the queue based on @@ -522,6 +530,10 @@ void ClientSocketPoolBaseHelper::OnConnectJobComplete( } } +void ClientSocketPoolBaseHelper::OnIPAddressChanged() { + CloseIdleSockets(); +} + void ClientSocketPoolBaseHelper::EnableLateBindingOfSockets(bool enabled) { g_late_binding = enabled; } diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h index 897ffec..b21bfb8 100644 --- a/net/socket/client_socket_pool_base.h +++ b/net/socket/client_socket_pool_base.h @@ -28,6 +28,7 @@ #include <string> #include "base/basictypes.h" +#include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/time.h" #include "base/timer.h" @@ -36,6 +37,7 @@ #include "net/base/load_log.h" #include "net/base/load_states.h" #include "net/base/net_errors.h" +#include "net/base/network_change_notifier.h" #include "net/base/request_priority.h" #include "net/socket/client_socket.h" #include "net/socket/client_socket_pool.h" @@ -121,7 +123,8 @@ namespace internal { // ClientSocketPoolBase instead. class ClientSocketPoolBaseHelper : public base::RefCounted<ClientSocketPoolBaseHelper>, - public ConnectJob::Delegate { + public ConnectJob::Delegate, + public NetworkChangeNotifier::Observer { public: class Request { public: @@ -163,11 +166,13 @@ class ClientSocketPoolBaseHelper DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory); }; - ClientSocketPoolBaseHelper(int max_sockets, - int max_sockets_per_group, - base::TimeDelta unused_idle_socket_timeout, - base::TimeDelta used_idle_socket_timeout, - ConnectJobFactory* connect_job_factory); + ClientSocketPoolBaseHelper( + int max_sockets, + int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, + base::TimeDelta used_idle_socket_timeout, + ConnectJobFactory* connect_job_factory, + const scoped_refptr<NetworkChangeNotifier>& network_change_notifier); // See ClientSocketPool::RequestSocket for documentation on this function. // Note that |request| must be heap allocated. If ERR_IO_PENDING is returned, @@ -201,6 +206,9 @@ class ClientSocketPoolBaseHelper // ConnectJob::Delegate methods: virtual void OnConnectJobComplete(int result, ConnectJob* job); + // NetworkChangeNotifier::Observer methods: + virtual void OnIPAddressChanged(); + // Enables late binding of sockets. In this mode, socket requests are // decoupled from socket connection jobs. A socket request may initiate a // socket connection job, but there is no guarantee that that socket @@ -385,9 +393,10 @@ class ClientSocketPoolBaseHelper const scoped_ptr<ConnectJobFactory> connect_job_factory_; + const scoped_refptr<NetworkChangeNotifier> network_change_notifier_; + // Controls whether or not we use late binding of sockets. static bool g_late_binding; - }; } // namespace internal @@ -441,15 +450,18 @@ class ClientSocketPoolBase { // long to leave an unused idle socket open before closing it. // |used_idle_socket_timeout| specifies how long to leave a previously used // idle socket open before closing it. - ClientSocketPoolBase(int max_sockets, - int max_sockets_per_group, - base::TimeDelta unused_idle_socket_timeout, - base::TimeDelta used_idle_socket_timeout, - ConnectJobFactory* connect_job_factory) + ClientSocketPoolBase( + int max_sockets, + int max_sockets_per_group, + base::TimeDelta unused_idle_socket_timeout, + base::TimeDelta used_idle_socket_timeout, + ConnectJobFactory* connect_job_factory, + const scoped_refptr<NetworkChangeNotifier>& network_change_notifier) : helper_(new internal::ClientSocketPoolBaseHelper( max_sockets, max_sockets_per_group, unused_idle_socket_timeout, used_idle_socket_timeout, - new ConnectJobFactoryAdaptor(connect_job_factory))) {} + new ConnectJobFactoryAdaptor(connect_job_factory), + network_change_notifier)) {} virtual ~ClientSocketPoolBase() {} diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 3c4c5cd..db61140 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc @@ -279,7 +279,7 @@ class TestClientSocketPool : public ClientSocketPool { TestClientSocketPoolBase::ConnectJobFactory* connect_job_factory) : base_(max_sockets, max_sockets_per_group, unused_idle_socket_timeout, used_idle_socket_timeout, - connect_job_factory) {} + connect_job_factory, NULL) {} virtual int RequestSocket( const std::string& group_name, diff --git a/net/socket/tcp_client_socket_pool.cc b/net/socket/tcp_client_socket_pool.cc index 84899da..1c6876a 100644 --- a/net/socket/tcp_client_socket_pool.cc +++ b/net/socket/tcp_client_socket_pool.cc @@ -161,11 +161,13 @@ TCPClientSocketPool::TCPClientSocketPool( int max_sockets, int max_sockets_per_group, HostResolver* host_resolver, - ClientSocketFactory* client_socket_factory) + ClientSocketFactory* client_socket_factory, + const scoped_refptr<NetworkChangeNotifier>& network_change_notifier) : base_(max_sockets, max_sockets_per_group, base::TimeDelta::FromSeconds(kUnusedIdleSocketTimeout), base::TimeDelta::FromSeconds(kUsedIdleSocketTimeout), - new TCPConnectJobFactory(client_socket_factory, host_resolver)) {} + new TCPConnectJobFactory(client_socket_factory, host_resolver), + network_change_notifier) {} TCPClientSocketPool::~TCPClientSocketPool() {} diff --git a/net/socket/tcp_client_socket_pool.h b/net/socket/tcp_client_socket_pool.h index 49c0aa7..96ebe73 100644 --- a/net/socket/tcp_client_socket_pool.h +++ b/net/socket/tcp_client_socket_pool.h @@ -76,10 +76,12 @@ class TCPConnectJob : public ConnectJob { class TCPClientSocketPool : public ClientSocketPool { public: - TCPClientSocketPool(int max_sockets, - int max_sockets_per_group, - HostResolver* host_resolver, - ClientSocketFactory* client_socket_factory); + TCPClientSocketPool( + int max_sockets, + int max_sockets_per_group, + HostResolver* host_resolver, + ClientSocketFactory* client_socket_factory, + const scoped_refptr<NetworkChangeNotifier>& network_change_notifier); // ClientSocketPool methods: diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc index b3560be..8aa9ea0 100644 --- a/net/socket/tcp_client_socket_pool_unittest.cc +++ b/net/socket/tcp_client_socket_pool_unittest.cc @@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/message_loop.h" #include "net/base/mock_host_resolver.h" +#include "net/base/mock_network_change_notifier.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/socket/client_socket.h" @@ -197,10 +198,12 @@ class TCPClientSocketPoolTest : public ClientSocketPoolTest { TCPClientSocketPoolTest() : ignored_request_info_("ignored", 80), host_resolver_(new MockHostResolver), + notifier_(new MockNetworkChangeNotifier), pool_(new TCPClientSocketPool(kMaxSockets, kMaxSocketsPerGroup, host_resolver_, - &client_socket_factory_)) { + &client_socket_factory_, + notifier_)) { } int StartRequest(const std::string& group_name, RequestPriority priority) { @@ -211,6 +214,7 @@ class TCPClientSocketPoolTest : public ClientSocketPoolTest { HostResolver::RequestInfo ignored_request_info_; scoped_refptr<MockHostResolver> host_resolver_; MockClientSocketFactory client_socket_factory_; + scoped_refptr<MockNetworkChangeNotifier> notifier_; scoped_refptr<TCPClientSocketPool> pool_; }; @@ -580,6 +584,32 @@ TEST_F(TCPClientSocketPoolTest, FailingActiveRequestWithPendingRequests) { EXPECT_EQ(ERR_CONNECTION_FAILED, requests_[i]->WaitForResult()); } +TEST_F(TCPClientSocketPoolTest, ResetIdleSocketsOnIPAddressChange) { + TestCompletionCallback callback; + ClientSocketHandle handle; + HostResolver::RequestInfo info("www.google.com", 80); + int rv = handle.Init("a", info, LOW, &callback, pool_.get(), NULL); + EXPECT_EQ(ERR_IO_PENDING, rv); + EXPECT_FALSE(handle.is_initialized()); + EXPECT_FALSE(handle.socket()); + + EXPECT_EQ(OK, callback.WaitForResult()); + EXPECT_TRUE(handle.is_initialized()); + EXPECT_TRUE(handle.socket()); + + handle.Reset(); + + // Need to run all pending to release the socket back to the pool. + MessageLoop::current()->RunAllPending(); + + // Now we should have 1 idle socket. + EXPECT_EQ(1, pool_->IdleSocketCount()); + + // After an IP address change, we should have 0 idle sockets. + notifier_->NotifyIPAddressChange(); + EXPECT_EQ(0, pool_->IdleSocketCount()); +} + } // namespace } // namespace net |