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