summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authorwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-21 21:08:35 +0000
committerwillchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-21 21:08:35 +0000
commit100d5fb906712b03495b961c35f9c9b21381a74a (patch)
tree284b84c9e6baba6da57427243a8b7729f67cb132 /net/socket
parent92683b5a068ab7c7f58251dbee9b047314977bae (diff)
downloadchromium_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.cc16
-rw-r--r--net/socket/client_socket_pool_base.h38
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc2
-rw-r--r--net/socket/tcp_client_socket_pool.cc6
-rw-r--r--net/socket/tcp_client_socket_pool.h10
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc32
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