diff options
author | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 23:41:50 +0000 |
---|---|---|
committer | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-27 23:41:50 +0000 |
commit | 50ab61dee0c6926215b6bc68151359c69829a24d (patch) | |
tree | 8e863e5dc246ec59eb2370c0637ad0af563786ed | |
parent | d2667b6962c06d35f38516b7cb77540b7b4a3e74 (diff) | |
download | chromium_src-50ab61dee0c6926215b6bc68151359c69829a24d.zip chromium_src-50ab61dee0c6926215b6bc68151359c69829a24d.tar.gz chromium_src-50ab61dee0c6926215b6bc68151359c69829a24d.tar.bz2 |
Add an implementation for async_network_alive to Linux
BUG=33091
TEST=none
Review URL: http://codereview.chromium.org/552162
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37342 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | chrome/browser/sync/engine/syncapi.cc | 2 | ||||
-rw-r--r-- | chrome/browser/sync/notifier/base/linux/async_network_alive_linux.cc | 124 | ||||
-rw-r--r-- | chrome/browser/sync/notifier/base/linux/network_status_detector_task_linux.cc | 15 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 5 |
4 files changed, 126 insertions, 20 deletions
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 8facc52..4de9587 100755 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -252,7 +252,7 @@ class AddressWatchTask : public Task { break; } - // If result is 0, select timed out. + // If fd is set, the network address might have changed. if (FD_ISSET(fd, &rdfs)) { char buf[4096]; struct iovec iov = { buf, sizeof(buf) }; diff --git a/chrome/browser/sync/notifier/base/linux/async_network_alive_linux.cc b/chrome/browser/sync/notifier/base/linux/async_network_alive_linux.cc new file mode 100644 index 0000000..28e89a9 --- /dev/null +++ b/chrome/browser/sync/notifier/base/linux/async_network_alive_linux.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/sync/notifier/base/async_network_alive.h" + +#include <sys/socket.h> +#include <asm/types.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +#include "base/logging.h" +#include "talk/base/physicalsocketserver.h" + +namespace notifier { + +class AsyncNetworkAliveLinux : public AsyncNetworkAlive { + public: + AsyncNetworkAliveLinux() { + if (pipe(exit_pipe_) == -1) { + PLOG(ERROR) << "Could not create pipe for exit signal."; + exit_pipe_[0] = 0; + exit_pipe_[1] = 0; + } + } + + virtual ~AsyncNetworkAliveLinux() { + if (exit_pipe_[1]) { + close(exit_pipe_[1]); + } + } + + protected: + // SignalThread Interface + virtual void DoWork() { + if (!exit_pipe_[0]) { + // If we don't have an exit flag to listen for, set the error flag and + // abort. + error_ = true; + return; + } + + // This function listens for changes to network interfaces, and link state. + // It's copied from syncapi.cc. + struct sockaddr_nl socket_address; + + memset(&socket_address, 0, sizeof(socket_address)); + socket_address.nl_family = AF_NETLINK; + socket_address.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR; + + // NETLINK_ROUTE is the protocol used to update the kernel routing table. + int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + bind(fd, (struct sockaddr *) &socket_address, sizeof(socket_address)); + + fd_set rdfs; + FD_ZERO(&rdfs); + FD_SET(fd, &rdfs); + FD_SET(exit_pipe_[0], &rdfs); + + int max_fd = fd > exit_pipe_[0] ? fd : exit_pipe_[0]; + + int result = select(max_fd + 1, &rdfs, NULL, NULL, NULL); + + if (result <= 0) { + error_ = true; + PLOG(ERROR) << "select() returned unexpected result " << result; + close(fd); + close(exit_pipe_[0]); + return; + } + + // Since we recieved a change from the socket, read the change in. + if (FD_ISSET(fd, &rdfs)) { + char buf[4096]; + struct iovec iov = { buf, sizeof(buf) }; + struct sockaddr_nl sa; + + struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 }; + recvmsg(fd, &msg, 0); + } + + close(fd); + + // If exit_pipe was written to, we must be shutting down. + if (FD_ISSET(exit_pipe_[0], &rdfs)) { + alive_ = false; + error_ = true; + close(exit_pipe_[0]); + return; + } + + // If there is an active connection, check that talk.google.com:5222 + // is reachable. + talk_base::PhysicalSocketServer physical; + scoped_ptr<talk_base::Socket> socket(physical.CreateSocket(SOCK_STREAM)); + if (socket->Connect(talk_base::SocketAddress("talk.google.com", 5222))) { + alive_ = false; + } else { + alive_ = true; + } + } + + virtual void OnWorkStop() { + if (exit_pipe_[1]) { + char data = 0; + // We can't ignore the return value on write(), since that generates a + // compile warning. However, since we're exiting, there's nothing we can + // do if this fails except to log it. + if (write(exit_pipe_[1], &data, 1) == -1) { + PLOG(WARNING) << "Error sending error signal to AsyncNetworkAliveLinux"; + } + } + } + + private: + int exit_pipe_[2]; + DISALLOW_COPY_AND_ASSIGN(AsyncNetworkAliveLinux); +}; + +AsyncNetworkAlive* AsyncNetworkAlive::Create() { + return new AsyncNetworkAliveLinux(); +} + +} // namespace notifier diff --git a/chrome/browser/sync/notifier/base/linux/network_status_detector_task_linux.cc b/chrome/browser/sync/notifier/base/linux/network_status_detector_task_linux.cc deleted file mode 100644 index 3d135be..0000000 --- a/chrome/browser/sync/notifier/base/linux/network_status_detector_task_linux.cc +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/sync/notifier/base/network_status_detector_task.h" - -namespace notifier { - -NetworkStatusDetectorTask* NetworkStatusDetectorTask::Create( - talk_base::Task* parent) { - // TODO(sync): No implementation for linux. - return NULL; -} - -} // namespace notifier diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 3122a1c..7f11b33 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -734,7 +734,7 @@ 'browser/sync/notifier/base/async_dns_lookup.h', 'browser/sync/notifier/base/async_network_alive.h', 'browser/sync/notifier/base/fastalloc.h', - 'browser/sync/notifier/base/linux/network_status_detector_task_linux.cc', + 'browser/sync/notifier/base/linux/async_network_alive_linux.cc', 'browser/sync/notifier/base/mac/network_status_detector_task_mac.h', 'browser/sync/notifier/base/mac/network_status_detector_task_mac.cc', 'browser/sync/notifier/base/nethelpers.cc', @@ -823,9 +823,6 @@ ], 'conditions': [ ['OS=="linux"', { - 'sources!': [ - 'browser/sync/notifier/base/network_status_detector_task_mt.cc', - ], 'dependencies': [ '../build/linux/system.gyp:gtk' ], |