Home | History | Annotate | Download | only in p2p
      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 #include "content/renderer/p2p/ipc_network_manager.h"
      6 #include <string>
      7 #include "base/bind.h"
      8 #include "base/command_line.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/sys_byteorder.h"
     11 #include "content/public/common/content_switches.h"
     12 #include "net/base/net_util.h"
     13 
     14 namespace content {
     15 
     16 namespace {
     17 
     18 rtc::AdapterType ConvertConnectionTypeToAdapterType(
     19     net::NetworkChangeNotifier::ConnectionType type) {
     20   switch (type) {
     21     case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
     22         return rtc::ADAPTER_TYPE_UNKNOWN;
     23     case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
     24         return rtc::ADAPTER_TYPE_ETHERNET;
     25     case net::NetworkChangeNotifier::CONNECTION_WIFI:
     26         return rtc::ADAPTER_TYPE_WIFI;
     27     case net::NetworkChangeNotifier::CONNECTION_2G:
     28     case net::NetworkChangeNotifier::CONNECTION_3G:
     29     case net::NetworkChangeNotifier::CONNECTION_4G:
     30         return rtc::ADAPTER_TYPE_CELLULAR;
     31     default:
     32         return rtc::ADAPTER_TYPE_UNKNOWN;
     33   }
     34 }
     35 
     36 }  // namespace
     37 
     38 IpcNetworkManager::IpcNetworkManager(NetworkListManager* network_list_manager)
     39     : network_list_manager_(network_list_manager),
     40       start_count_(0),
     41       network_list_received_(false),
     42       weak_factory_(this) {
     43   network_list_manager_->AddNetworkListObserver(this);
     44 }
     45 
     46 IpcNetworkManager::~IpcNetworkManager() {
     47   DCHECK(!start_count_);
     48   network_list_manager_->RemoveNetworkListObserver(this);
     49 }
     50 
     51 void IpcNetworkManager::StartUpdating() {
     52   if (network_list_received_) {
     53     // Post a task to avoid reentrancy.
     54     base::MessageLoop::current()->PostTask(
     55         FROM_HERE,
     56         base::Bind(&IpcNetworkManager::SendNetworksChangedSignal,
     57                    weak_factory_.GetWeakPtr()));
     58   }
     59   ++start_count_;
     60 }
     61 
     62 void IpcNetworkManager::StopUpdating() {
     63   DCHECK_GT(start_count_, 0);
     64   --start_count_;
     65 }
     66 
     67 void IpcNetworkManager::OnNetworkListChanged(
     68     const net::NetworkInterfaceList& list) {
     69 
     70   // Update flag if network list received for the first time.
     71   if (!network_list_received_)
     72     network_list_received_ = true;
     73 
     74   // rtc::Network uses these prefix_length to compare network
     75   // interfaces discovered.
     76   std::vector<rtc::Network*> networks;
     77   int ipv4_interfaces = 0;
     78   int ipv6_interfaces = 0;
     79   for (net::NetworkInterfaceList::const_iterator it = list.begin();
     80        it != list.end(); it++) {
     81     if (it->address.size() == net::kIPv4AddressSize) {
     82       uint32 address;
     83       memcpy(&address, &it->address[0], sizeof(uint32));
     84       address = rtc::NetworkToHost32(address);
     85       rtc::IPAddress prefix =
     86           rtc::TruncateIP(rtc::IPAddress(address), it->network_prefix);
     87       rtc::Network* network =
     88           new rtc::Network(it->name,
     89                            it->name,
     90                            prefix,
     91                            it->network_prefix,
     92                            ConvertConnectionTypeToAdapterType(it->type));
     93       network->AddIP(rtc::IPAddress(address));
     94       networks.push_back(network);
     95       ++ipv4_interfaces;
     96     } else if (it->address.size() == net::kIPv6AddressSize) {
     97       in6_addr address;
     98       memcpy(&address, &it->address[0], sizeof(in6_addr));
     99       rtc::IPAddress ip6_addr(address);
    100       if (!rtc::IPIsPrivate(ip6_addr)) {
    101         rtc::IPAddress prefix =
    102             rtc::TruncateIP(rtc::IPAddress(ip6_addr), it->network_prefix);
    103         rtc::Network* network =
    104             new rtc::Network(it->name,
    105                              it->name,
    106                              prefix,
    107                              it->network_prefix,
    108                              ConvertConnectionTypeToAdapterType(it->type));
    109         network->AddIP(ip6_addr);
    110         networks.push_back(network);
    111         ++ipv6_interfaces;
    112       }
    113     }
    114   }
    115 
    116 
    117   // Send interface counts to UMA.
    118   UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
    119                            ipv4_interfaces);
    120   UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
    121                            ipv6_interfaces);
    122 
    123   if (CommandLine::ForCurrentProcess()->HasSwitch(
    124       switches::kAllowLoopbackInPeerConnection)) {
    125     std::string name_v4("loopback_ipv4");
    126     rtc::IPAddress ip_address_v4(INADDR_LOOPBACK);
    127     rtc::Network* network_v4 = new rtc::Network(
    128         name_v4, name_v4, ip_address_v4, 32, rtc::ADAPTER_TYPE_UNKNOWN);
    129     network_v4->AddIP(ip_address_v4);
    130     networks.push_back(network_v4);
    131 
    132     std::string name_v6("loopback_ipv6");
    133     rtc::IPAddress ip_address_v6(in6addr_loopback);
    134     rtc::Network* network_v6 = new rtc::Network(
    135         name_v6, name_v6, ip_address_v6, 64, rtc::ADAPTER_TYPE_UNKNOWN);
    136     network_v6->AddIP(ip_address_v6);
    137     networks.push_back(network_v6);
    138   }
    139 
    140   bool changed = false;
    141   MergeNetworkList(networks, &changed);
    142   if (changed)
    143     SignalNetworksChanged();
    144 }
    145 
    146 void IpcNetworkManager::SendNetworksChangedSignal() {
    147   SignalNetworksChanged();
    148 }
    149 
    150 }  // namespace content
    151