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 7 #include "base/bind.h" 8 #include "base/sys_byteorder.h" 9 #include "net/base/net_util.h" 10 11 namespace content { 12 13 IpcNetworkManager::IpcNetworkManager(P2PSocketDispatcher* socket_dispatcher) 14 : socket_dispatcher_(socket_dispatcher), 15 start_count_(0), 16 network_list_received_(false), 17 weak_factory_(this) { 18 socket_dispatcher_->AddNetworkListObserver(this); 19 } 20 21 IpcNetworkManager::~IpcNetworkManager() { 22 DCHECK(!start_count_); 23 socket_dispatcher_->RemoveNetworkListObserver(this); 24 } 25 26 void IpcNetworkManager::StartUpdating() { 27 if (network_list_received_) { 28 // Post a task to avoid reentrancy. 29 base::MessageLoop::current()->PostTask( 30 FROM_HERE, 31 base::Bind(&IpcNetworkManager::SendNetworksChangedSignal, 32 weak_factory_.GetWeakPtr())); 33 } 34 ++start_count_; 35 } 36 37 void IpcNetworkManager::StopUpdating() { 38 DCHECK_GT(start_count_, 0); 39 --start_count_; 40 } 41 42 void IpcNetworkManager::OnNetworkListChanged( 43 const net::NetworkInterfaceList& list) { 44 45 // Update flag if network list received for the first time. 46 if (!network_list_received_) 47 network_list_received_ = true; 48 49 // Note: 32 and 64 are the arbitrary(kind of) prefix length used to 50 // differentiate IPv4 and IPv6 addresses. 51 // talk_base::Network uses these prefix_length to compare network 52 // interfaces discovered. 53 std::vector<talk_base::Network*> networks; 54 for (net::NetworkInterfaceList::const_iterator it = list.begin(); 55 it != list.end(); it++) { 56 if (it->address.size() == net::kIPv4AddressSize) { 57 uint32 address; 58 memcpy(&address, &it->address[0], sizeof(uint32)); 59 address = talk_base::NetworkToHost32(address); 60 talk_base::Network* network = new talk_base::Network( 61 it->name, it->name, talk_base::IPAddress(address), 32); 62 network->AddIP(talk_base::IPAddress(address)); 63 networks.push_back(network); 64 } else if (it->address.size() == net::kIPv6AddressSize) { 65 in6_addr address; 66 memcpy(&address, &it->address[0], sizeof(in6_addr)); 67 talk_base::IPAddress ip6_addr(address); 68 if (!talk_base::IPIsPrivate(ip6_addr)) { 69 talk_base::Network* network = new talk_base::Network( 70 it->name, it->name, ip6_addr, 64); 71 network->AddIP(ip6_addr); 72 networks.push_back(network); 73 } 74 } 75 } 76 77 bool changed = false; 78 MergeNetworkList(networks, &changed); 79 if (changed) 80 SignalNetworksChanged(); 81 } 82 83 void IpcNetworkManager::SendNetworksChangedSignal() { 84 SignalNetworksChanged(); 85 } 86 87 } // namespace content 88