diff options
Diffstat (limited to 'remoting/protocol/pepper_network_manager.cc')
-rw-r--r-- | remoting/protocol/pepper_network_manager.cc | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/remoting/protocol/pepper_network_manager.cc b/remoting/protocol/pepper_network_manager.cc new file mode 100644 index 0000000..f7b754f --- /dev/null +++ b/remoting/protocol/pepper_network_manager.cc @@ -0,0 +1,114 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/protocol/pepper_network_manager.h" + +#include "base/bind.h" +#include "base/message_loop.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/private/network_list_private.h" +#include "ppapi/cpp/private/net_address_private.h" + +namespace remoting { +namespace protocol { + +PepperNetworkManager::PepperNetworkManager(const pp::InstanceHandle& instance) + : monitor_(instance, &PepperNetworkManager::OnNetworkListCallbackHandler, + this), + start_count_(0), + network_list_received_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { +} + +PepperNetworkManager::~PepperNetworkManager() { + DCHECK(!start_count_); +} + +void PepperNetworkManager::StartUpdating() { + if (network_list_received_) { + // Post a task to avoid reentrancy. + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&PepperNetworkManager::SendNetworksChangedSignal, + weak_factory_.GetWeakPtr())); + } + ++start_count_; +} + +void PepperNetworkManager::StopUpdating() { + DCHECK_GT(start_count_, 0); + --start_count_; +} + +// static +void PepperNetworkManager::OnNetworkListCallbackHandler( + void* user_data, + PP_Resource list_resource) { + PepperNetworkManager* object = static_cast<PepperNetworkManager*>(user_data); + pp::NetworkListPrivate list(list_resource); + object->OnNetworkList(list); + pp::Module::Get()->core()->ReleaseResource(list_resource); +} + +void PepperNetworkManager::OnNetworkList(const pp::NetworkListPrivate& list) { + network_list_received_ = true; + + std::vector<talk_base::Network*> networks; + size_t count = list.GetCount(); + for (size_t i = 0; i < count; i++) { + std::vector<PP_NetAddress_Private> addresses; + list.GetIpAddresses(i, &addresses); + + if (addresses.size() == 0) + continue; + + char address_bytes[sizeof(in6_addr)]; + if (!pp::NetAddressPrivate::GetAddress( + addresses[0], &address_bytes, sizeof(address_bytes))) { + LOG(ERROR) << "Failed to get address for network interface."; + continue; + } + + int prefix_length; + + // TODO(sergeyu): Copy all addresses, not only the first one. + talk_base::IPAddress address; + switch (pp::NetAddressPrivate::GetFamily(addresses[0])) { + case PP_NETADDRESSFAMILY_IPV4: { + in_addr* address_ipv4 = reinterpret_cast<in_addr*>(address_bytes); + address = talk_base::IPAddress(*address_ipv4); + prefix_length = sizeof(in_addr) * 8; + break; + } + + case PP_NETADDRESSFAMILY_IPV6: { + in6_addr* address_ipv6 = reinterpret_cast<in6_addr*>(address_bytes); + address = talk_base::IPAddress(*address_ipv6); + prefix_length = sizeof(in6_addr) * 8; + break; + } + + default: + LOG(WARNING) << "Skipping address with unknown family: " + << pp::NetAddressPrivate::GetFamily(addresses[0]); + continue; + } + + talk_base::Network* network = new talk_base::Network( + list.GetName(i), list.GetDisplayName(i), address, prefix_length); + network->AddIP(address); + networks.push_back(network); + } + + bool changed = false; + MergeNetworkList(networks, &changed); + if (changed) + SignalNetworksChanged(); +} + +void PepperNetworkManager::SendNetworksChangedSignal() { + SignalNetworksChanged(); +} + +} // namespace protocol +} // namespace remoting |