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 author: 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 "nspr.h"
45 #include "prnetdb.h"
46 
47 #include "mozilla/Assertions.h"
48 
49 extern "C" {
50 #include "nr_api.h"
51 #include "async_timer.h"
52 #include "nr_resolver.h"
53 #include "transport_addr.h"
54 }
55 
56 #include "nriceresolverfake.h"
57 #include "nr_socket_prsock.h"
58 
59 namespace mozilla {
60 
NrIceResolverFake()61 NrIceResolverFake::NrIceResolverFake() :
62     vtbl_(new nr_resolver_vtbl), addrs_(), delay_ms_(100),
63     allocated_resolvers_(0) {
64   vtbl_->destroy = &NrIceResolverFake::destroy;
65   vtbl_->resolve = &NrIceResolverFake::resolve;
66   vtbl_->cancel = &NrIceResolverFake::cancel;
67 }
68 
~NrIceResolverFake()69 NrIceResolverFake::~NrIceResolverFake() {
70   MOZ_ASSERT(allocated_resolvers_ == 0);
71   delete vtbl_;
72 }
73 
74 
AllocateResolver()75 nr_resolver *NrIceResolverFake::AllocateResolver() {
76   nr_resolver *resolver;
77 
78   int r = nr_resolver_create_int((void *)this,
79                                  vtbl_, &resolver);
80   MOZ_ASSERT(!r);
81   if(r)
82     return nullptr;
83 
84   ++allocated_resolvers_;
85 
86   return resolver;
87 }
88 
DestroyResolver()89 void NrIceResolverFake::DestroyResolver() {
90   --allocated_resolvers_;
91 }
92 
destroy(void ** objp)93 int NrIceResolverFake::destroy(void **objp) {
94   if (!objp || !*objp)
95     return 0;
96 
97   NrIceResolverFake *fake = static_cast<NrIceResolverFake *>(*objp);
98   *objp = 0;
99 
100   fake->DestroyResolver();
101 
102   return 0;
103 }
104 
resolve(void * obj,nr_resolver_resource * resource,int (* cb)(void * cb_arg,nr_transport_addr * addr),void * cb_arg,void ** handle)105 int NrIceResolverFake::resolve(void *obj,
106                                nr_resolver_resource *resource,
107                                int (*cb)(void *cb_arg,
108                                          nr_transport_addr *addr),
109                                void *cb_arg,
110                                void **handle) {
111   int r,_status;
112 
113   MOZ_ASSERT(obj);
114   NrIceResolverFake *fake = static_cast<NrIceResolverFake *>(obj);
115 
116   MOZ_ASSERT(fake->allocated_resolvers_ > 0);
117 
118   PendingResolution *pending =
119       new PendingResolution(fake,
120                             resource->domain_name,
121                             resource->port ? resource->port : 3478,
122                             resource->transport_protocol ?
123                             resource->transport_protocol :
124                             IPPROTO_UDP,
125                             resource->address_family,
126                             cb, cb_arg);
127 
128   if ((r=NR_ASYNC_TIMER_SET(fake->delay_ms_,NrIceResolverFake::resolve_cb,
129                             (void *)pending, &pending->timer_handle_))) {
130     delete pending;
131     ABORT(r);
132   }
133   *handle = pending;
134 
135   _status=0;
136 abort:
137   return(_status);
138 }
139 
resolve_cb(NR_SOCKET s,int how,void * cb_arg)140 void NrIceResolverFake::resolve_cb(NR_SOCKET s, int how, void *cb_arg) {
141   MOZ_ASSERT(cb_arg);
142   PendingResolution *pending = static_cast<PendingResolution *>(cb_arg);
143 
144   const PRNetAddr *addr=pending->resolver_->Resolve(pending->hostname_,
145                                                     pending->address_family_);
146 
147   if (addr) {
148     nr_transport_addr transport_addr;
149 
150     int r = nr_praddr_to_transport_addr(addr, &transport_addr,
151                                         pending->transport_, 0);
152     MOZ_ASSERT(!r);
153     if (r)
154       goto abort;
155 
156     r=nr_transport_addr_set_port(&transport_addr, pending->port_);
157     MOZ_ASSERT(!r);
158     if (r)
159       goto abort;
160 
161     /* Fill in the address string */
162     r=nr_transport_addr_fmt_addr_string(&transport_addr);
163     MOZ_ASSERT(!r);
164     if (r)
165       goto abort;
166 
167     pending->cb_(pending->cb_arg_, &transport_addr);
168     delete pending;
169     return;
170   }
171 
172 abort:
173   // Resolution failed.
174   pending->cb_(pending->cb_arg_, nullptr);
175 
176   delete pending;
177 }
178 
cancel(void * obj,void * handle)179 int NrIceResolverFake::cancel(void *obj, void *handle) {
180   MOZ_ASSERT(obj);
181   MOZ_ASSERT(static_cast<NrIceResolverFake *>(obj)->allocated_resolvers_ > 0);
182 
183   PendingResolution *pending = static_cast<PendingResolution *>(handle);
184 
185   NR_async_timer_cancel(pending->timer_handle_);
186   delete pending;
187 
188   return(0);
189 }
190 
191 
192 }  // End of namespace mozilla
193