media/mtransport/nriceresolver.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7
michael@0 8 // Original authors: jib@mozilla.com, ekr@rtfm.com
michael@0 9
michael@0 10 // Some of this code is cut-and-pasted from nICEr. Copyright is:
michael@0 11
michael@0 12 /*
michael@0 13 Copyright (c) 2007, Adobe Systems, Incorporated
michael@0 14 All rights reserved.
michael@0 15
michael@0 16 Redistribution and use in source and binary forms, with or without
michael@0 17 modification, are permitted provided that the following conditions are
michael@0 18 met:
michael@0 19
michael@0 20 * Redistributions of source code must retain the above copyright
michael@0 21 notice, this list of conditions and the following disclaimer.
michael@0 22
michael@0 23 * Redistributions in binary form must reproduce the above copyright
michael@0 24 notice, this list of conditions and the following disclaimer in the
michael@0 25 documentation and/or other materials provided with the distribution.
michael@0 26
michael@0 27 * Neither the name of Adobe Systems, Network Resonance nor the names of its
michael@0 28 contributors may be used to endorse or promote products derived from
michael@0 29 this software without specific prior written permission.
michael@0 30
michael@0 31 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 32 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 33 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 34 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 35 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 36 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 37 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 38 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 39 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 40 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 41 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 42 */
michael@0 43
michael@0 44 #include "logging.h"
michael@0 45 #include "nspr.h"
michael@0 46 #include "prnetdb.h"
michael@0 47
michael@0 48 #include "mozilla/Assertions.h"
michael@0 49
michael@0 50 extern "C" {
michael@0 51 #include "nr_api.h"
michael@0 52 #include "async_timer.h"
michael@0 53 #include "nr_resolver.h"
michael@0 54 #include "transport_addr.h"
michael@0 55 }
michael@0 56
michael@0 57 #include "mozilla/net/DNS.h" // TODO(jib@mozilla.com) down here because bug 848578
michael@0 58 #include "nsThreadUtils.h"
michael@0 59 #include "nsServiceManagerUtils.h"
michael@0 60 #include "nsIDNSService.h"
michael@0 61 #include "nsIDNSListener.h"
michael@0 62 #include "nsIDNSRecord.h"
michael@0 63 #include "nsNetCID.h"
michael@0 64 #include "nsCOMPtr.h"
michael@0 65 #include "nriceresolver.h"
michael@0 66 #include "nr_socket_prsock.h"
michael@0 67 #include "mtransport/runnable_utils.h"
michael@0 68
michael@0 69 namespace mozilla {
michael@0 70
michael@0 71 MOZ_MTLOG_MODULE("mtransport")
michael@0 72
michael@0 73 NrIceResolver::NrIceResolver() :
michael@0 74 vtbl_(new nr_resolver_vtbl())
michael@0 75 #ifdef DEBUG
michael@0 76 , allocated_resolvers_(0)
michael@0 77 #endif
michael@0 78 {
michael@0 79 vtbl_->destroy = &NrIceResolver::destroy;
michael@0 80 vtbl_->resolve = &NrIceResolver::resolve;
michael@0 81 vtbl_->cancel = &NrIceResolver::cancel;
michael@0 82 }
michael@0 83
michael@0 84 NrIceResolver::~NrIceResolver() {
michael@0 85 MOZ_ASSERT(!allocated_resolvers_);
michael@0 86 delete vtbl_;
michael@0 87 }
michael@0 88
michael@0 89 nsresult NrIceResolver::Init() {
michael@0 90 nsresult rv;
michael@0 91
michael@0 92 sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
michael@0 93 MOZ_ASSERT(NS_SUCCEEDED(rv));
michael@0 94 dns_ = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
michael@0 95 if (NS_FAILED(rv)) {
michael@0 96 MOZ_MTLOG(ML_ERROR, "Could not acquire DNS service");
michael@0 97 }
michael@0 98 return rv;
michael@0 99 }
michael@0 100
michael@0 101 nr_resolver *NrIceResolver::AllocateResolver() {
michael@0 102 nr_resolver *resolver;
michael@0 103
michael@0 104 int r = nr_resolver_create_int((void *)this, vtbl_, &resolver);
michael@0 105 MOZ_ASSERT(!r);
michael@0 106 if(r) {
michael@0 107 MOZ_MTLOG(ML_ERROR, "nr_resolver_create_int failed");
michael@0 108 return nullptr;
michael@0 109 }
michael@0 110 // We must be available to allocators until they all call DestroyResolver,
michael@0 111 // because allocators may (and do) outlive the originator of NrIceResolver.
michael@0 112 AddRef();
michael@0 113 #ifdef DEBUG
michael@0 114 ++allocated_resolvers_;
michael@0 115 #endif
michael@0 116 return resolver;
michael@0 117 }
michael@0 118
michael@0 119 void NrIceResolver::DestroyResolver() {
michael@0 120 #ifdef DEBUG
michael@0 121 --allocated_resolvers_;
michael@0 122 #endif
michael@0 123 // Undoes Addref in AllocateResolver so the NrIceResolver can be freed.
michael@0 124 Release();
michael@0 125 }
michael@0 126
michael@0 127 int NrIceResolver::destroy(void **objp) {
michael@0 128 if (!objp || !*objp)
michael@0 129 return 0;
michael@0 130 NrIceResolver *resolver = static_cast<NrIceResolver *>(*objp);
michael@0 131 *objp = 0;
michael@0 132 resolver->DestroyResolver();
michael@0 133 return 0;
michael@0 134 }
michael@0 135
michael@0 136 int NrIceResolver::resolve(void *obj,
michael@0 137 nr_resolver_resource *resource,
michael@0 138 int (*cb)(void *cb_arg, nr_transport_addr *addr),
michael@0 139 void *cb_arg,
michael@0 140 void **handle) {
michael@0 141 MOZ_ASSERT(obj);
michael@0 142 return static_cast<NrIceResolver *>(obj)->resolve(resource, cb, cb_arg, handle);
michael@0 143 }
michael@0 144
michael@0 145 int NrIceResolver::resolve(nr_resolver_resource *resource,
michael@0 146 int (*cb)(void *cb_arg, nr_transport_addr *addr),
michael@0 147 void *cb_arg,
michael@0 148 void **handle) {
michael@0 149 int _status;
michael@0 150 MOZ_ASSERT(allocated_resolvers_ > 0);
michael@0 151 ASSERT_ON_THREAD(sts_thread_);
michael@0 152 nsRefPtr<PendingResolution> pr;
michael@0 153
michael@0 154 if (resource->transport_protocol != IPPROTO_UDP &&
michael@0 155 resource->transport_protocol != IPPROTO_TCP) {
michael@0 156 MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are is supported.");
michael@0 157 ABORT(R_NOT_FOUND);
michael@0 158 }
michael@0 159 pr = new PendingResolution(sts_thread_,
michael@0 160 resource->port? resource->port : 3478,
michael@0 161 resource->transport_protocol ?
michael@0 162 resource->transport_protocol :
michael@0 163 IPPROTO_UDP,
michael@0 164 cb, cb_arg);
michael@0 165 if (NS_FAILED(dns_->AsyncResolve(nsAutoCString(resource->domain_name),
michael@0 166 nsIDNSService::RESOLVE_DISABLE_IPV6, pr,
michael@0 167 sts_thread_, getter_AddRefs(pr->request_)))) {
michael@0 168 MOZ_MTLOG(ML_ERROR, "AsyncResolve failed.");
michael@0 169 ABORT(R_NOT_FOUND);
michael@0 170 }
michael@0 171 // Because the C API offers no "finished" method to release the handle we
michael@0 172 // return, we cannot return the request we got from AsyncResolve directly.
michael@0 173 //
michael@0 174 // Instead, we return an addref'ed reference to PendingResolution itself,
michael@0 175 // which in turn holds the request and coordinates between cancel and
michael@0 176 // OnLookupComplete to release it only once.
michael@0 177 pr.forget(handle);
michael@0 178
michael@0 179 _status=0;
michael@0 180 abort:
michael@0 181 return _status;
michael@0 182 }
michael@0 183
michael@0 184 nsresult NrIceResolver::PendingResolution::OnLookupComplete(
michael@0 185 nsICancelable *request, nsIDNSRecord *record, nsresult status) {
michael@0 186 ASSERT_ON_THREAD(thread_);
michael@0 187 // First check if we've been canceled. This is single-threaded on the STS
michael@0 188 // thread, but cancel() cannot guarantee this event isn't on the queue.
michael@0 189 if (!canceled_) {
michael@0 190 nr_transport_addr *cb_addr = nullptr;
michael@0 191 nr_transport_addr ta;
michael@0 192 // TODO(jib@mozilla.com): Revisit when we do TURN.
michael@0 193 if (NS_SUCCEEDED(status)) {
michael@0 194 net::NetAddr na;
michael@0 195 if (NS_SUCCEEDED(record->GetNextAddr(port_, &na))) {
michael@0 196 MOZ_ALWAYS_TRUE (nr_netaddr_to_transport_addr(&na, &ta,
michael@0 197 transport_) == 0);
michael@0 198 cb_addr = &ta;
michael@0 199 }
michael@0 200 }
michael@0 201 cb_(cb_arg_, cb_addr);
michael@0 202 Release();
michael@0 203 }
michael@0 204 return NS_OK;
michael@0 205 }
michael@0 206
michael@0 207 int NrIceResolver::cancel(void *obj, void *handle) {
michael@0 208 MOZ_ALWAYS_TRUE(obj);
michael@0 209 MOZ_ASSERT(handle);
michael@0 210 ASSERT_ON_THREAD(static_cast<NrIceResolver *>(obj)->sts_thread_);
michael@0 211 return static_cast<PendingResolution *>(handle)->cancel();
michael@0 212 }
michael@0 213
michael@0 214 int NrIceResolver::PendingResolution::cancel() {
michael@0 215 request_->Cancel (NS_ERROR_ABORT);
michael@0 216 canceled_ = true; // in case OnLookupComplete is already on event queue.
michael@0 217 Release();
michael@0 218 return 0;
michael@0 219 }
michael@0 220
michael@0 221 NS_IMPL_ISUPPORTS(NrIceResolver::PendingResolution, nsIDNSListener);
michael@0 222 } // End of namespace mozilla

mercurial