media/mtransport/gonk_addrs.cpp

changeset 0
6474c204b198
     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 +}

mercurial