Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_BASE_ADDRESS_TRACKER_LINUX_H_
      6 #define NET_BASE_ADDRESS_TRACKER_LINUX_H_
      7 
      8 #include <sys/socket.h>  // Needed to include netlink.
      9 // Mask superfluous definition of |struct net|. This is fixed in Linux 2.6.38.
     10 #define net net_kernel
     11 #include <linux/rtnetlink.h>
     12 #undef net
     13 
     14 #include <map>
     15 
     16 #include "base/basictypes.h"
     17 #include "base/callback.h"
     18 #include "base/compiler_specific.h"
     19 #include "base/containers/hash_tables.h"
     20 #include "base/message_loop/message_loop.h"
     21 #include "base/synchronization/condition_variable.h"
     22 #include "base/synchronization/lock.h"
     23 #include "net/base/net_util.h"
     24 #include "net/base/network_change_notifier.h"
     25 
     26 namespace net {
     27 namespace internal {
     28 
     29 // Keeps track of network interface addresses using rtnetlink. Used by
     30 // NetworkChangeNotifier to provide signals to registered IPAddressObservers.
     31 class NET_EXPORT_PRIVATE AddressTrackerLinux :
     32     public base::MessageLoopForIO::Watcher {
     33  public:
     34   typedef std::map<IPAddressNumber, struct ifaddrmsg> AddressMap;
     35 
     36   // Will run |address_callback| when the AddressMap changes and will run
     37   // |link_callback| when the list of online links changes.
     38   AddressTrackerLinux(const base::Closure& address_callback,
     39                       const base::Closure& link_callback);
     40   virtual ~AddressTrackerLinux();
     41 
     42   // Starts watching system configuration for changes. The current thread must
     43   // have a MessageLoopForIO.
     44   void Init();
     45 
     46   AddressMap GetAddressMap() const;
     47 
     48   // Implementation of NetworkChangeNotifierLinux::GetCurrentConnectionType().
     49   // Safe to call from any thread, but will block until Init() has completed.
     50   NetworkChangeNotifier::ConnectionType GetCurrentConnectionType();
     51 
     52  private:
     53   friend class AddressTrackerLinuxTest;
     54 
     55   // Sets |*address_changed| to indicate whether |address_map_| changed and
     56   // sets |*link_changed| to indicate if |online_links_| changed while reading
     57   // messages from |netlink_fd_|.
     58   void ReadMessages(bool* address_changed, bool* link_changed);
     59 
     60   // Sets |*address_changed| to true if |address_map_| changed, sets
     61   // |*link_changed| to true if |online_links_| changed while reading the
     62   // message from |buffer|.
     63   void HandleMessage(const char* buffer,
     64                      size_t length,
     65                      bool* address_changed,
     66                      bool* link_changed);
     67 
     68   // Call when some part of initialization failed; forces online and unblocks.
     69   void AbortAndForceOnline();
     70 
     71   // MessageLoopForIO::Watcher:
     72   virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE;
     73   virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE;
     74 
     75   // Close |netlink_fd_|
     76   void CloseSocket();
     77 
     78   base::Closure address_callback_;
     79   base::Closure link_callback_;
     80 
     81   int netlink_fd_;
     82   base::MessageLoopForIO::FileDescriptorWatcher watcher_;
     83 
     84   mutable base::Lock address_map_lock_;
     85   AddressMap address_map_;
     86 
     87   // Set of interface indices for links that are currently online.
     88   base::hash_set<int> online_links_;
     89 
     90   base::Lock is_offline_lock_;
     91   bool is_offline_;
     92   bool is_offline_initialized_;
     93   base::ConditionVariable is_offline_initialized_cv_;
     94 };
     95 
     96 }  // namespace internal
     97 }  // namespace net
     98 
     99 #endif  // NET_BASE_ADDRESS_TRACKER_LINUX_H_
    100