media/mtransport/nriceresolver.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/mtransport/nriceresolver.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,222 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; 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 +
    1.10 +
    1.11 +// Original authors: jib@mozilla.com, ekr@rtfm.com
    1.12 +
    1.13 +// Some of this code is cut-and-pasted from nICEr. Copyright is:
    1.14 +
    1.15 +/*
    1.16 +Copyright (c) 2007, Adobe Systems, Incorporated
    1.17 +All rights reserved.
    1.18 +
    1.19 +Redistribution and use in source and binary forms, with or without
    1.20 +modification, are permitted provided that the following conditions are
    1.21 +met:
    1.22 +
    1.23 +* Redistributions of source code must retain the above copyright
    1.24 +  notice, this list of conditions and the following disclaimer.
    1.25 +
    1.26 +* Redistributions in binary form must reproduce the above copyright
    1.27 +  notice, this list of conditions and the following disclaimer in the
    1.28 +  documentation and/or other materials provided with the distribution.
    1.29 +
    1.30 +* Neither the name of Adobe Systems, Network Resonance nor the names of its
    1.31 +  contributors may be used to endorse or promote products derived from
    1.32 +  this software without specific prior written permission.
    1.33 +
    1.34 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    1.35 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.36 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    1.37 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    1.38 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.39 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    1.40 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.41 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.42 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.43 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    1.44 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.45 +*/
    1.46 +
    1.47 +#include "logging.h"
    1.48 +#include "nspr.h"
    1.49 +#include "prnetdb.h"
    1.50 +
    1.51 +#include "mozilla/Assertions.h"
    1.52 +
    1.53 +extern "C" {
    1.54 +#include "nr_api.h"
    1.55 +#include "async_timer.h"
    1.56 +#include "nr_resolver.h"
    1.57 +#include "transport_addr.h"
    1.58 +}
    1.59 +
    1.60 +#include "mozilla/net/DNS.h" // TODO(jib@mozilla.com) down here because bug 848578
    1.61 +#include "nsThreadUtils.h"
    1.62 +#include "nsServiceManagerUtils.h"
    1.63 +#include "nsIDNSService.h"
    1.64 +#include "nsIDNSListener.h"
    1.65 +#include "nsIDNSRecord.h"
    1.66 +#include "nsNetCID.h"
    1.67 +#include "nsCOMPtr.h"
    1.68 +#include "nriceresolver.h"
    1.69 +#include "nr_socket_prsock.h"
    1.70 +#include "mtransport/runnable_utils.h"
    1.71 +
    1.72 +namespace mozilla {
    1.73 +
    1.74 +MOZ_MTLOG_MODULE("mtransport")
    1.75 +
    1.76 +NrIceResolver::NrIceResolver() :
    1.77 +    vtbl_(new nr_resolver_vtbl())
    1.78 +#ifdef DEBUG
    1.79 +    , allocated_resolvers_(0)
    1.80 +#endif
    1.81 +{
    1.82 +  vtbl_->destroy = &NrIceResolver::destroy;
    1.83 +  vtbl_->resolve = &NrIceResolver::resolve;
    1.84 +  vtbl_->cancel = &NrIceResolver::cancel;
    1.85 +}
    1.86 +
    1.87 +NrIceResolver::~NrIceResolver() {
    1.88 +  MOZ_ASSERT(!allocated_resolvers_);
    1.89 +  delete vtbl_;
    1.90 +}
    1.91 +
    1.92 +nsresult NrIceResolver::Init() {
    1.93 +  nsresult rv;
    1.94 +
    1.95 +  sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
    1.96 +  MOZ_ASSERT(NS_SUCCEEDED(rv));
    1.97 +  dns_ = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
    1.98 +  if (NS_FAILED(rv)) {
    1.99 +    MOZ_MTLOG(ML_ERROR, "Could not acquire DNS service");
   1.100 +  }
   1.101 +  return rv;
   1.102 +}
   1.103 +
   1.104 +nr_resolver *NrIceResolver::AllocateResolver() {
   1.105 +  nr_resolver *resolver;
   1.106 +
   1.107 +  int r = nr_resolver_create_int((void *)this, vtbl_, &resolver);
   1.108 +  MOZ_ASSERT(!r);
   1.109 +  if(r) {
   1.110 +    MOZ_MTLOG(ML_ERROR, "nr_resolver_create_int failed");
   1.111 +    return nullptr;
   1.112 +  }
   1.113 +  // We must be available to allocators until they all call DestroyResolver,
   1.114 +  // because allocators may (and do) outlive the originator of NrIceResolver.
   1.115 +  AddRef();
   1.116 +#ifdef DEBUG
   1.117 +  ++allocated_resolvers_;
   1.118 +#endif
   1.119 +  return resolver;
   1.120 +}
   1.121 +
   1.122 +void NrIceResolver::DestroyResolver() {
   1.123 +#ifdef DEBUG
   1.124 +  --allocated_resolvers_;
   1.125 +#endif
   1.126 +  // Undoes Addref in AllocateResolver so the NrIceResolver can be freed.
   1.127 +  Release();
   1.128 +}
   1.129 +
   1.130 +int NrIceResolver::destroy(void **objp) {
   1.131 +  if (!objp || !*objp)
   1.132 +    return 0;
   1.133 +  NrIceResolver *resolver = static_cast<NrIceResolver *>(*objp);
   1.134 +  *objp = 0;
   1.135 +  resolver->DestroyResolver();
   1.136 +  return 0;
   1.137 +}
   1.138 +
   1.139 +int NrIceResolver::resolve(void *obj,
   1.140 +                           nr_resolver_resource *resource,
   1.141 +                           int (*cb)(void *cb_arg, nr_transport_addr *addr),
   1.142 +                           void *cb_arg,
   1.143 +                           void **handle) {
   1.144 +  MOZ_ASSERT(obj);
   1.145 +  return static_cast<NrIceResolver *>(obj)->resolve(resource, cb, cb_arg, handle);
   1.146 +}
   1.147 +
   1.148 +int NrIceResolver::resolve(nr_resolver_resource *resource,
   1.149 +                           int (*cb)(void *cb_arg, nr_transport_addr *addr),
   1.150 +                           void *cb_arg,
   1.151 +                           void **handle) {
   1.152 +  int _status;
   1.153 +  MOZ_ASSERT(allocated_resolvers_ > 0);
   1.154 +  ASSERT_ON_THREAD(sts_thread_);
   1.155 +  nsRefPtr<PendingResolution> pr;
   1.156 +
   1.157 +  if (resource->transport_protocol != IPPROTO_UDP &&
   1.158 +      resource->transport_protocol != IPPROTO_TCP) {
   1.159 +    MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are is supported.");
   1.160 +    ABORT(R_NOT_FOUND);
   1.161 +  }
   1.162 +  pr = new PendingResolution(sts_thread_,
   1.163 +                             resource->port? resource->port : 3478,
   1.164 +                             resource->transport_protocol ?
   1.165 +                             resource->transport_protocol :
   1.166 +                             IPPROTO_UDP,
   1.167 +                             cb, cb_arg);
   1.168 +  if (NS_FAILED(dns_->AsyncResolve(nsAutoCString(resource->domain_name),
   1.169 +                                   nsIDNSService::RESOLVE_DISABLE_IPV6, pr,
   1.170 +                                   sts_thread_, getter_AddRefs(pr->request_)))) {
   1.171 +    MOZ_MTLOG(ML_ERROR, "AsyncResolve failed.");
   1.172 +    ABORT(R_NOT_FOUND);
   1.173 +  }
   1.174 +  // Because the C API offers no "finished" method to release the handle we
   1.175 +  // return, we cannot return the request we got from AsyncResolve directly.
   1.176 +  //
   1.177 +  // Instead, we return an addref'ed reference to PendingResolution itself,
   1.178 +  // which in turn holds the request and coordinates between cancel and
   1.179 +  // OnLookupComplete to release it only once.
   1.180 +  pr.forget(handle);
   1.181 +
   1.182 +  _status=0;
   1.183 +abort:
   1.184 +  return _status;
   1.185 +}
   1.186 +
   1.187 +nsresult NrIceResolver::PendingResolution::OnLookupComplete(
   1.188 +    nsICancelable *request, nsIDNSRecord *record, nsresult status) {
   1.189 +  ASSERT_ON_THREAD(thread_);
   1.190 +  // First check if we've been canceled. This is single-threaded on the STS
   1.191 +  // thread, but cancel() cannot guarantee this event isn't on the queue.
   1.192 +  if (!canceled_) {
   1.193 +    nr_transport_addr *cb_addr = nullptr;
   1.194 +    nr_transport_addr ta;
   1.195 +    // TODO(jib@mozilla.com): Revisit when we do TURN.
   1.196 +    if (NS_SUCCEEDED(status)) {
   1.197 +      net::NetAddr na;
   1.198 +      if (NS_SUCCEEDED(record->GetNextAddr(port_, &na))) {
   1.199 +        MOZ_ALWAYS_TRUE (nr_netaddr_to_transport_addr(&na, &ta,
   1.200 +                                                      transport_) == 0);
   1.201 +        cb_addr = &ta;
   1.202 +      }
   1.203 +    }
   1.204 +    cb_(cb_arg_, cb_addr);
   1.205 +    Release();
   1.206 +  }
   1.207 +  return NS_OK;
   1.208 +}
   1.209 +
   1.210 +int NrIceResolver::cancel(void *obj, void *handle) {
   1.211 +  MOZ_ALWAYS_TRUE(obj);
   1.212 +  MOZ_ASSERT(handle);
   1.213 +  ASSERT_ON_THREAD(static_cast<NrIceResolver *>(obj)->sts_thread_);
   1.214 +  return static_cast<PendingResolution *>(handle)->cancel();
   1.215 +}
   1.216 +
   1.217 +int NrIceResolver::PendingResolution::cancel() {
   1.218 +  request_->Cancel (NS_ERROR_ABORT);
   1.219 +  canceled_ = true; // in case OnLookupComplete is already on event queue.
   1.220 +  Release();
   1.221 +  return 0;
   1.222 +}
   1.223 +
   1.224 +NS_IMPL_ISUPPORTS(NrIceResolver::PendingResolution, nsIDNSListener);
   1.225 +}  // End of namespace mozilla

mercurial