summaryrefslogtreecommitdiff
path: root/chromium/net/base/address_tracker_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/base/address_tracker_linux.cc')
-rw-r--r--chromium/net/base/address_tracker_linux.cc110
1 files changed, 80 insertions, 30 deletions
diff --git a/chromium/net/base/address_tracker_linux.cc b/chromium/net/base/address_tracker_linux.cc
index 36738136695..27dd2019ab0 100644
--- a/chromium/net/base/address_tracker_linux.cc
+++ b/chromium/net/base/address_tracker_linux.cc
@@ -97,6 +97,18 @@ const char* GetInterfaceName(int interface_index) {
} // namespace
+AddressTrackerLinux::AddressTrackerLinux()
+ : get_interface_name_(GetInterfaceName),
+ address_callback_(base::Bind(&base::DoNothing)),
+ link_callback_(base::Bind(&base::DoNothing)),
+ tunnel_callback_(base::Bind(&base::DoNothing)),
+ netlink_fd_(-1),
+ is_offline_(true),
+ is_offline_initialized_(false),
+ is_offline_initialized_cv_(&is_offline_lock_),
+ tracking_(false) {
+}
+
AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback,
const base::Closure& link_callback,
const base::Closure& tunnel_callback)
@@ -107,7 +119,8 @@ AddressTrackerLinux::AddressTrackerLinux(const base::Closure& address_callback,
netlink_fd_(-1),
is_offline_(true),
is_offline_initialized_(false),
- is_offline_initialized_cv_(&is_offline_lock_) {
+ is_offline_initialized_cv_(&is_offline_lock_),
+ tracking_(true) {
DCHECK(!address_callback.is_null());
DCHECK(!link_callback.is_null());
}
@@ -124,20 +137,24 @@ void AddressTrackerLinux::Init() {
return;
}
- // Request notifications.
- struct sockaddr_nl addr = {};
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
- // TODO(szym): Track RTMGRP_LINK as well for ifi_type, http://crbug.com/113993
- addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY |
- RTMGRP_LINK;
- int rv = bind(netlink_fd_,
- reinterpret_cast<struct sockaddr*>(&addr),
- sizeof(addr));
- if (rv < 0) {
- PLOG(ERROR) << "Could not bind NETLINK socket";
- AbortAndForceOnline();
- return;
+ int rv;
+
+ if (tracking_) {
+ // Request notifications.
+ struct sockaddr_nl addr = {};
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = getpid();
+ // TODO(szym): Track RTMGRP_LINK as well for ifi_type,
+ // http://crbug.com/113993
+ addr.nl_groups =
+ RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR | RTMGRP_NOTIFY | RTMGRP_LINK;
+ rv = bind(
+ netlink_fd_, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr));
+ if (rv < 0) {
+ PLOG(ERROR) << "Could not bind NETLINK socket";
+ AbortAndForceOnline();
+ return;
+ }
}
// Request dump of addresses.
@@ -186,38 +203,45 @@ void AddressTrackerLinux::Init() {
// Consume pending message to populate links_online_, but don't notify.
ReadMessages(&address_changed, &link_changed, &tunnel_changed);
{
- base::AutoLock lock(is_offline_lock_);
+ AddressTrackerAutoLock lock(*this, is_offline_lock_);
is_offline_initialized_ = true;
is_offline_initialized_cv_.Signal();
}
- rv = base::MessageLoopForIO::current()->WatchFileDescriptor(
- netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
- if (rv < 0) {
- PLOG(ERROR) << "Could not watch NETLINK socket";
- AbortAndForceOnline();
- return;
+ if (tracking_) {
+ rv = base::MessageLoopForIO::current()->WatchFileDescriptor(
+ netlink_fd_, true, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
+ if (rv < 0) {
+ PLOG(ERROR) << "Could not watch NETLINK socket";
+ AbortAndForceOnline();
+ return;
+ }
}
}
void AddressTrackerLinux::AbortAndForceOnline() {
CloseSocket();
- base::AutoLock lock(is_offline_lock_);
+ AddressTrackerAutoLock lock(*this, is_offline_lock_);
is_offline_ = false;
is_offline_initialized_ = true;
is_offline_initialized_cv_.Signal();
}
AddressTrackerLinux::AddressMap AddressTrackerLinux::GetAddressMap() const {
- base::AutoLock lock(address_map_lock_);
+ AddressTrackerAutoLock lock(*this, address_map_lock_);
return address_map_;
}
+base::hash_set<int> AddressTrackerLinux::GetOnlineLinks() const {
+ AddressTrackerAutoLock lock(*this, online_links_lock_);
+ return online_links_;
+}
+
NetworkChangeNotifier::ConnectionType
AddressTrackerLinux::GetCurrentConnectionType() {
// http://crbug.com/125097
base::ThreadRestrictions::ScopedAllowWait allow_wait;
- base::AutoLock lock(is_offline_lock_);
+ AddressTrackerAutoLock lock(*this, is_offline_lock_);
// Make sure the initial offline state is set before returning.
while (!is_offline_initialized_) {
is_offline_initialized_cv_.Wait();
@@ -254,10 +278,15 @@ void AddressTrackerLinux::ReadMessages(bool* address_changed,
return;
}
HandleMessage(buffer, rv, address_changed, link_changed, tunnel_changed);
- };
+ }
if (*link_changed) {
- base::AutoLock lock(is_offline_lock_);
- is_offline_ = online_links_.empty();
+ bool is_offline;
+ {
+ AddressTrackerAutoLock lock(*this, online_links_lock_);
+ is_offline = online_links_.empty();
+ }
+ AddressTrackerAutoLock lock(*this, is_offline_lock_);
+ is_offline_ = is_offline;
}
}
@@ -282,7 +311,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
IPAddressNumber address;
bool really_deprecated;
if (GetAddress(header, &address, &really_deprecated)) {
- base::AutoLock lock(address_map_lock_);
+ AddressTrackerAutoLock lock(*this, address_map_lock_);
struct ifaddrmsg* msg =
reinterpret_cast<struct ifaddrmsg*>(NLMSG_DATA(header));
// Routers may frequently (every few seconds) output the IPv6 ULA
@@ -309,7 +338,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
case RTM_DELADDR: {
IPAddressNumber address;
if (GetAddress(header, &address, NULL)) {
- base::AutoLock lock(address_map_lock_);
+ AddressTrackerAutoLock lock(*this, address_map_lock_);
if (address_map_.erase(address))
*address_changed = true;
}
@@ -319,12 +348,14 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header));
if (!(msg->ifi_flags & IFF_LOOPBACK) && (msg->ifi_flags & IFF_UP) &&
(msg->ifi_flags & IFF_LOWER_UP) && (msg->ifi_flags & IFF_RUNNING)) {
+ AddressTrackerAutoLock lock(*this, online_links_lock_);
if (online_links_.insert(msg->ifi_index).second) {
*link_changed = true;
if (IsTunnelInterface(msg))
*tunnel_changed = true;
}
} else {
+ AddressTrackerAutoLock lock(*this, online_links_lock_);
if (online_links_.erase(msg->ifi_index)) {
*link_changed = true;
if (IsTunnelInterface(msg))
@@ -335,6 +366,7 @@ void AddressTrackerLinux::HandleMessage(char* buffer,
case RTM_DELLINK: {
const struct ifinfomsg* msg =
reinterpret_cast<struct ifinfomsg*>(NLMSG_DATA(header));
+ AddressTrackerAutoLock lock(*this, online_links_lock_);
if (online_links_.erase(msg->ifi_index)) {
*link_changed = true;
if (IsTunnelInterface(msg))
@@ -374,5 +406,23 @@ bool AddressTrackerLinux::IsTunnelInterface(const struct ifinfomsg* msg) const {
return strncmp(get_interface_name_(msg->ifi_index), "tun", 3) == 0;
}
+AddressTrackerLinux::AddressTrackerAutoLock::AddressTrackerAutoLock(
+ const AddressTrackerLinux& tracker,
+ base::Lock& lock)
+ : tracker_(tracker), lock_(lock) {
+ if (tracker_.tracking_) {
+ lock_.Acquire();
+ } else {
+ DCHECK(tracker_.thread_checker_.CalledOnValidThread());
+ }
+}
+
+AddressTrackerLinux::AddressTrackerAutoLock::~AddressTrackerAutoLock() {
+ if (tracker_.tracking_) {
+ lock_.AssertAcquired();
+ lock_.Release();
+ }
+}
+
} // namespace internal
} // namespace net