1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/gonk_addrs.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,170 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +extern "C" { 1.10 +#include <arpa/inet.h> 1.11 +#include "r_types.h" 1.12 +#include "stun.h" 1.13 +#include "addrs.h" 1.14 +} 1.15 + 1.16 +#include <vector> 1.17 +#include <string> 1.18 +#include "nsINetworkManager.h" 1.19 +#include "nsINetworkInterfaceListService.h" 1.20 +#include "runnable_utils.h" 1.21 +#include "nsCOMPtr.h" 1.22 +#include "nsMemory.h" 1.23 +#include "nsThreadUtils.h" 1.24 +#include "nsServiceManagerUtils.h" 1.25 +#include "mozilla/SyncRunnable.h" 1.26 + 1.27 +namespace { 1.28 +struct NetworkInterface { 1.29 + struct sockaddr_in addr; 1.30 + std::string name; 1.31 + // See NR_INTERFACE_TYPE_* in nICEr/src/net/local_addrs.h 1.32 + int type; 1.33 +}; 1.34 + 1.35 +nsresult 1.36 +GetInterfaces(std::vector<NetworkInterface>* aInterfaces) 1.37 +{ 1.38 + MOZ_ASSERT(aInterfaces); 1.39 + 1.40 + // Obtain network interfaces from network manager. 1.41 + nsresult rv; 1.42 + nsCOMPtr<nsINetworkInterfaceListService> listService = 1.43 + do_GetService("@mozilla.org/network/interface-list-service;1", &rv); 1.44 + NS_ENSURE_SUCCESS(rv, rv); 1.45 + 1.46 + int32_t flags = 1.47 + nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES | 1.48 + nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES | 1.49 + nsINetworkInterfaceListService::LIST_NOT_INCLUDE_IMS_INTERFACES | 1.50 + nsINetworkInterfaceListService::LIST_NOT_INCLUDE_DUN_INTERFACES; 1.51 + nsCOMPtr<nsINetworkInterfaceList> networkList; 1.52 + NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags, 1.53 + getter_AddRefs(networkList)), 1.54 + NS_ERROR_FAILURE); 1.55 + 1.56 + // Translate nsINetworkInterfaceList to NetworkInterface. 1.57 + int32_t listLength; 1.58 + NS_ENSURE_SUCCESS(networkList->GetNumberOfInterface(&listLength), 1.59 + NS_ERROR_FAILURE); 1.60 + aInterfaces->clear(); 1.61 + 1.62 + for (int32_t i = 0; i < listLength; i++) { 1.63 + nsCOMPtr<nsINetworkInterface> iface; 1.64 + if (NS_FAILED(networkList->GetInterface(i, getter_AddRefs(iface)))) { 1.65 + continue; 1.66 + } 1.67 + 1.68 + char16_t **ips = nullptr; 1.69 + uint32_t *prefixs = nullptr; 1.70 + uint32_t count = 0; 1.71 + bool isAddressGot = false; 1.72 + NetworkInterface interface; 1.73 + memset(&(interface.addr), 0, sizeof(interface.addr)); 1.74 + interface.addr.sin_family = AF_INET; 1.75 + 1.76 + if (NS_FAILED(iface->GetAddresses(&ips, &prefixs, &count))) { 1.77 + continue; 1.78 + } 1.79 + 1.80 + for (uint32_t j = 0; j < count; j++) { 1.81 + nsAutoString ip; 1.82 + 1.83 + ip.Assign(ips[j]); 1.84 + if (inet_pton(AF_INET, NS_ConvertUTF16toUTF8(ip).get(), 1.85 + &(interface.addr.sin_addr.s_addr)) == 1) { 1.86 + isAddressGot = true; 1.87 + break; 1.88 + } 1.89 + } 1.90 + 1.91 + nsMemory::Free(prefixs); 1.92 + NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, ips); 1.93 + 1.94 + if (!isAddressGot) { 1.95 + continue; 1.96 + } 1.97 + 1.98 + nsAutoString ifaceName; 1.99 + if (NS_FAILED(iface->GetName(ifaceName))) { 1.100 + continue; 1.101 + } 1.102 + interface.name = NS_ConvertUTF16toUTF8(ifaceName).get(); 1.103 + 1.104 + int32_t type; 1.105 + if (NS_FAILED(iface->GetType(&type))) { 1.106 + continue; 1.107 + } 1.108 + switch (type) { 1.109 + case nsINetworkInterface::NETWORK_TYPE_WIFI: 1.110 + interface.type = NR_INTERFACE_TYPE_WIFI; 1.111 + break; 1.112 + case nsINetworkInterface::NETWORK_TYPE_MOBILE: 1.113 + interface.type = NR_INTERFACE_TYPE_MOBILE; 1.114 + break; 1.115 + } 1.116 + 1.117 + aInterfaces->push_back(interface); 1.118 + } 1.119 + return NS_OK; 1.120 +} 1.121 +} // anonymous namespace 1.122 + 1.123 +int 1.124 +nr_stun_get_addrs(nr_local_addr aAddrs[], int aMaxAddrs, 1.125 + int aDropLoopback, int* aCount) 1.126 +{ 1.127 + nsresult rv; 1.128 + int r; 1.129 + 1.130 + // Get network interface list. 1.131 + std::vector<NetworkInterface> interfaces; 1.132 + nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); 1.133 + mozilla::SyncRunnable::DispatchToThread( 1.134 + mainThread.get(), 1.135 + mozilla::WrapRunnableNMRet(&GetInterfaces, &interfaces, &rv), 1.136 + false); 1.137 + if (NS_FAILED(rv)) { 1.138 + return R_FAILED; 1.139 + } 1.140 + 1.141 + // Translate to nr_transport_addr. 1.142 + int32_t n = 0; 1.143 + size_t num_interface = std::min(interfaces.size(), (size_t)aMaxAddrs); 1.144 + for (size_t i = 0; i < num_interface; ++i) { 1.145 + NetworkInterface &interface = interfaces[i]; 1.146 + if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr), 1.147 + sizeof(struct sockaddr_in), 1.148 + IPPROTO_UDP, 0, &(aAddrs[n].addr))) { 1.149 + r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address"); 1.150 + return R_FAILED; 1.151 + } 1.152 + strlcpy(aAddrs[n].addr.ifname, interface.name.c_str(), 1.153 + sizeof(aAddrs[n].addr.ifname)); 1.154 + aAddrs[n].interface.type = interface.type; 1.155 + aAddrs[n].interface.estimated_speed = 0; 1.156 + n++; 1.157 + } 1.158 + 1.159 + *aCount = n; 1.160 + r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount); 1.161 + if (r != 0) { 1.162 + return r; 1.163 + } 1.164 + 1.165 + for (int i = 0; i < *aCount; ++i) { 1.166 + char typestr[100]; 1.167 + nr_local_addr_fmt_info_string(aAddrs + i, typestr, sizeof(typestr)); 1.168 + r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s, type: %s\n", 1.169 + i, aAddrs[i].addr.as_string, aAddrs[i].addr.ifname, typestr); 1.170 + } 1.171 + 1.172 + return 0; 1.173 +}