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