123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
- // Original authors: jib@mozilla.com, ekr@rtfm.com
- // Some of this code is cut-and-pasted from nICEr. Copyright is:
- /*
- Copyright (c) 2007, Adobe Systems, Incorporated
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of Adobe Systems, Network Resonance nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "logging.h"
- #include "nspr.h"
- #include "prnetdb.h"
- #include "mozilla/Assertions.h"
- extern "C" {
- #include "nr_api.h"
- #include "async_timer.h"
- #include "nr_resolver.h"
- #include "transport_addr.h"
- }
- #include "mozilla/net/DNS.h" // TODO(jib@mozilla.com) down here because bug 848578
- #include "nsThreadUtils.h"
- #include "nsServiceManagerUtils.h"
- #include "nsIDNSService.h"
- #include "nsIDNSListener.h"
- #include "nsIDNSRecord.h"
- #include "nsNetCID.h"
- #include "nsCOMPtr.h"
- #include "nriceresolver.h"
- #include "nr_socket_prsock.h"
- #include "mtransport/runnable_utils.h"
- namespace mozilla {
- MOZ_MTLOG_MODULE("mtransport")
- NrIceResolver::NrIceResolver() :
- vtbl_(new nr_resolver_vtbl())
- #ifdef DEBUG
- , allocated_resolvers_(0)
- #endif
- {
- vtbl_->destroy = &NrIceResolver::destroy;
- vtbl_->resolve = &NrIceResolver::resolve;
- vtbl_->cancel = &NrIceResolver::cancel;
- }
- NrIceResolver::~NrIceResolver() {
- MOZ_ASSERT(!allocated_resolvers_);
- delete vtbl_;
- }
- nsresult NrIceResolver::Init() {
- nsresult rv;
- sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
- MOZ_ASSERT(NS_SUCCEEDED(rv));
- dns_ = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
- if (NS_FAILED(rv)) {
- MOZ_MTLOG(ML_ERROR, "Could not acquire DNS service");
- }
- return rv;
- }
- nr_resolver *NrIceResolver::AllocateResolver() {
- nr_resolver *resolver;
- int r = nr_resolver_create_int((void *)this, vtbl_, &resolver);
- MOZ_ASSERT(!r);
- if(r) {
- MOZ_MTLOG(ML_ERROR, "nr_resolver_create_int failed");
- return nullptr;
- }
- // We must be available to allocators until they all call DestroyResolver,
- // because allocators may (and do) outlive the originator of NrIceResolver.
- AddRef();
- #ifdef DEBUG
- ++allocated_resolvers_;
- #endif
- return resolver;
- }
- void NrIceResolver::DestroyResolver() {
- #ifdef DEBUG
- --allocated_resolvers_;
- #endif
- // Undoes Addref in AllocateResolver so the NrIceResolver can be freed.
- Release();
- }
- int NrIceResolver::destroy(void **objp) {
- if (!objp || !*objp)
- return 0;
- NrIceResolver *resolver = static_cast<NrIceResolver *>(*objp);
- *objp = 0;
- resolver->DestroyResolver();
- return 0;
- }
- int NrIceResolver::resolve(void *obj,
- nr_resolver_resource *resource,
- int (*cb)(void *cb_arg, nr_transport_addr *addr),
- void *cb_arg,
- void **handle) {
- MOZ_ASSERT(obj);
- return static_cast<NrIceResolver *>(obj)->resolve(resource, cb, cb_arg, handle);
- }
- int NrIceResolver::resolve(nr_resolver_resource *resource,
- int (*cb)(void *cb_arg, nr_transport_addr *addr),
- void *cb_arg,
- void **handle) {
- int _status;
- MOZ_ASSERT(allocated_resolvers_ > 0);
- ASSERT_ON_THREAD(sts_thread_);
- RefPtr<PendingResolution> pr;
- uint32_t resolve_flags = 0;
- if (resource->transport_protocol != IPPROTO_UDP &&
- resource->transport_protocol != IPPROTO_TCP) {
- MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are supported.");
- ABORT(R_NOT_FOUND);
- }
- pr = new PendingResolution(sts_thread_,
- resource->port? resource->port : 3478,
- resource->transport_protocol ?
- resource->transport_protocol :
- IPPROTO_UDP,
- cb, cb_arg);
- switch(resource->address_family) {
- case AF_INET:
- resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
- break;
- case AF_INET6:
- resolve_flags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
- break;
- default:
- ABORT(R_BAD_ARGS);
- }
- if (NS_FAILED(dns_->AsyncResolve(nsAutoCString(resource->domain_name),
- resolve_flags, pr,
- sts_thread_, getter_AddRefs(pr->request_)))) {
- MOZ_MTLOG(ML_ERROR, "AsyncResolve failed.");
- ABORT(R_NOT_FOUND);
- }
- // Because the C API offers no "finished" method to release the handle we
- // return, we cannot return the request we got from AsyncResolve directly.
- //
- // Instead, we return an addref'ed reference to PendingResolution itself,
- // which in turn holds the request and coordinates between cancel and
- // OnLookupComplete to release it only once.
- pr.forget(handle);
- _status=0;
- abort:
- return _status;
- }
- nsresult NrIceResolver::PendingResolution::OnLookupComplete(
- nsICancelable *request, nsIDNSRecord *record, nsresult status) {
- ASSERT_ON_THREAD(thread_);
- // First check if we've been canceled. This is single-threaded on the STS
- // thread, but cancel() cannot guarantee this event isn't on the queue.
- if (request_) {
- nr_transport_addr *cb_addr = nullptr;
- nr_transport_addr ta;
- // TODO(jib@mozilla.com): Revisit when we do TURN.
- if (NS_SUCCEEDED(status)) {
- net::NetAddr na;
- if (NS_SUCCEEDED(record->GetNextAddr(port_, &na))) {
- MOZ_ALWAYS_TRUE (nr_netaddr_to_transport_addr(&na, &ta,
- transport_) == 0);
- cb_addr = &ta;
- }
- }
- cb_(cb_arg_, cb_addr);
- request_ = nullptr;
- Release();
- }
- return NS_OK;
- }
- int NrIceResolver::cancel(void *obj, void *handle) {
- MOZ_ALWAYS_TRUE(obj);
- MOZ_ASSERT(handle);
- ASSERT_ON_THREAD(static_cast<NrIceResolver *>(obj)->sts_thread_);
- return static_cast<PendingResolution *>(handle)->cancel();
- }
- int NrIceResolver::PendingResolution::cancel() {
- request_->Cancel (NS_ERROR_ABORT);
- request_ = nullptr;
- Release();
- return 0;
- }
- NS_IMPL_ISUPPORTS(NrIceResolver::PendingResolution, nsIDNSListener);
- } // End of namespace mozilla
|