Chromium 网络栈之NetworkChangeNotifier

发布于 2021-11-15


NetworkChangeNotifier

NetworkChangeNotifier 是监控系统网络环境变化的类。

Observer

我们可以向它注册一些 observer,来获取相关的事件。

NetworkChangeNotifier 目前有以下几种 Observer:

  • IPAddressObserver,通知 IP 地址发生了变化
  • ConnectionTypeObserver,通知网络连接发生了变化
  • DNSObserver,通知 DNS 配置发生了变化
  • NetworkChangeObserver,通知网络发生了变化,功能跟上面的 Observer 有些重复
  • MaxBandwidthObserver,通知网络最大带宽发生了变化
  • NetworkObserver,通知网络的连接与断开

LoggingNetworkChangeObserver

LoggingNetworkChangeObserver 类就是继承实现了 NetworkChangeNotifier 里面的一些 Observer 接口,从而把网络变化相关的事件转发给 NetLog。

NetworkWatcher

我们也可以实现一个 NetworkWatcher 的类,看看能从 NetworkChangeNotifier 那里获取到哪些信息。

network_watcher.h 文件内容:

#ifndef NETWORK_WATCHER_H_
#define NETWORK_WATCHER_H_

#include "base/macros.h"
#include "net/base/network_change_notifier.h"
#include "net/dns/dns_config.h"

class NetworkWatcher
    : public net::NetworkChangeNotifier::IPAddressObserver,
      public net::NetworkChangeNotifier::ConnectionTypeObserver,
      public net::NetworkChangeNotifier::DNSObserver,
      public net::NetworkChangeNotifier::NetworkChangeObserver {
 public:
  NetworkWatcher();
  ~NetworkWatcher() override;

  void Init();
  void Shutdown();

 private:
  // IPAddressObserver
  void OnIPAddressChanged() override;

  // ConnectionTypeObserver
  void OnConnectionTypeChanged(
      net::NetworkChangeNotifier::ConnectionType type) override;

  // DNSObserver
  void OnDNSChanged() override;
  void OnInitialDNSConfigRead() override;

  // NetworkChangeObserver
  void OnNetworkChanged(
      net::NetworkChangeNotifier::ConnectionType type) override;

  void PrintDnsConfig();
  void PrintNetwork();

  std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
  DISALLOW_COPY_AND_ASSIGN(NetworkWatcher);
};
#endif  // NETWORK_WATCHER_H_

----------------------------------------------------------------------

network_watcher.cc 文件内容:

#include "network_watcher.h"

#include "base/logging.h"
#include "net/base/network_interfaces.h"

NetworkWatcher::NetworkWatcher() {}

NetworkWatcher::~NetworkWatcher() {}

void NetworkWatcher::Init() {
  network_change_notifier_.reset(net::NetworkChangeNotifier::Create());

  net::NetworkChangeNotifier::AddIPAddressObserver(this);
  net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
  net::NetworkChangeNotifier::AddDNSObserver(this);
  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
}

void NetworkWatcher::Shutdown() {
  if (network_change_notifier_) {
    net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
    net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
    net::NetworkChangeNotifier::RemoveDNSObserver(this);
    net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
  }
  network_change_notifier_.reset();
}

void NetworkWatcher::OnIPAddressChanged() {
  LOG(WARNING) << "NetworkWatcher::OnIPAddressChanged";
  PrintNetwork();
}

void NetworkWatcher::OnConnectionTypeChanged(
    net::NetworkChangeNotifier::ConnectionType type) {
  LOG(WARNING) << "NetworkWatcher::OnConnectionTypeChanged "
               << net::NetworkChangeNotifier::ConnectionTypeToString(type);

  PrintNetwork();
}

void NetworkWatcher::OnDNSChanged() {
  LOG(WARNING) << "NetworkWatcher::OnDNSChanged";
  PrintDnsConfig();
}

void NetworkWatcher::OnInitialDNSConfigRead() {
  LOG(WARNING) << "NetworkWatcher::OnInitialDNSConfigRead";
  PrintDnsConfig();
}

void NetworkWatcher::OnNetworkChanged(
    net::NetworkChangeNotifier::ConnectionType type) {
  LOG(WARNING) << "NetworkWatcher::OnNetworkChanged "
               << net::NetworkChangeNotifier::ConnectionTypeToString(type);
  PrintNetwork();
}

void NetworkWatcher::PrintDnsConfig() {
  net::DnsConfig dns_config;
  net::NetworkChangeNotifier::GetDnsConfig(&dns_config);

  for (net::IPEndPoint nameserver : dns_config.nameservers) {
    printf("nameserver %s\n", nameserver.ToString().c_str());
  }

  for (std::string s : dns_config.search) {
    printf("search %s\n", s.c_str());
  }

  for (auto host : dns_config.hosts) {
    printf("host:%s\t%s\n", host.first.first.c_str(),
           host.second.ToString().c_str());
  }
}

void NetworkWatcher::PrintNetwork() {
  net::NetworkChangeNotifier::ConnectionType connection_type =
      net::NetworkChangeNotifier::GetConnectionType();
  printf("connection_type %s\n",
         net::NetworkChangeNotifier::ConnectionTypeToString(connection_type));

  net::NetworkInterfaceList network_interface_list;
  if (net::GetNetworkList(&network_interface_list,
                          net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
    for (auto n : network_interface_list) {
      printf("network interface name --- %s ---------------\n", n.name.c_str());
      printf("network interface friendly_name %s\n", n.friendly_name.c_str());
      printf("network interface connection_type %s\n",
             net::NetworkChangeNotifier::ConnectionTypeToString(n.type));
      printf("network interface address %s\n", n.address.ToString().c_str());
    }
  }
}