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
IpcNetworkManager(P2PSocketDispatcher * socket_dispatcher)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
~IpcNetworkManager()21 IpcNetworkManager::~IpcNetworkManager() {
22 DCHECK(!start_count_);
23 socket_dispatcher_->RemoveNetworkListObserver(this);
24 }
25
StartUpdating()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
StopUpdating()37 void IpcNetworkManager::StopUpdating() {
38 DCHECK_GT(start_count_, 0);
39 --start_count_;
40 }
41
OnNetworkListChanged(const net::NetworkInterfaceList & list)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
SendNetworksChangedSignal()83 void IpcNetworkManager::SendNetworksChangedSignal() {
84 SignalNetworksChanged();
85 }
86
87 } // namespace content
88