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 
      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