File: | var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp |
Warning: | line 455, column 7 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
9 | /* | |||
10 | Based partially on original code from nICEr and nrappkit. | |||
11 | ||||
12 | nICEr copyright: | |||
13 | ||||
14 | Copyright (c) 2007, Adobe Systems, Incorporated | |||
15 | All rights reserved. | |||
16 | ||||
17 | Redistribution and use in source and binary forms, with or without | |||
18 | modification, are permitted provided that the following conditions are | |||
19 | met: | |||
20 | ||||
21 | * Redistributions of source code must retain the above copyright | |||
22 | notice, this list of conditions and the following disclaimer. | |||
23 | ||||
24 | * Redistributions in binary form must reproduce the above copyright | |||
25 | notice, this list of conditions and the following disclaimer in the | |||
26 | documentation and/or other materials provided with the distribution. | |||
27 | ||||
28 | * Neither the name of Adobe Systems, Network Resonance nor the names of its | |||
29 | contributors may be used to endorse or promote products derived from | |||
30 | this software without specific prior written permission. | |||
31 | ||||
32 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
33 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
34 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||
35 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||
36 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
37 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
38 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
39 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
40 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
41 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
42 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
43 | ||||
44 | ||||
45 | nrappkit copyright: | |||
46 | ||||
47 | Copyright (C) 2001-2003, Network Resonance, Inc. | |||
48 | Copyright (C) 2006, Network Resonance, Inc. | |||
49 | All Rights Reserved | |||
50 | ||||
51 | Redistribution and use in source and binary forms, with or without | |||
52 | modification, are permitted provided that the following conditions | |||
53 | are met: | |||
54 | ||||
55 | 1. Redistributions of source code must retain the above copyright | |||
56 | notice, this list of conditions and the following disclaimer. | |||
57 | 2. Redistributions in binary form must reproduce the above copyright | |||
58 | notice, this list of conditions and the following disclaimer in the | |||
59 | documentation and/or other materials provided with the distribution. | |||
60 | 3. Neither the name of Network Resonance, Inc. nor the name of any | |||
61 | contributors to this software may be used to endorse or promote | |||
62 | products derived from this software without specific prior written | |||
63 | permission. | |||
64 | ||||
65 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' | |||
66 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
67 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
68 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | |||
69 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
70 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
71 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
72 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
73 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
74 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
75 | POSSIBILITY OF SUCH DAMAGE. | |||
76 | ||||
77 | ||||
78 | ekr@rtfm.com Thu Dec 20 20:14:49 2001 | |||
79 | */ | |||
80 | ||||
81 | // Original author: bcampen@mozilla.com [:bwc] | |||
82 | ||||
83 | extern "C" { | |||
84 | #include "stun_msg.h" // for NR_STUN_MAX_MESSAGE_SIZE | |||
85 | #include "async_wait.h" | |||
86 | #include "async_timer.h" | |||
87 | #include "nr_socket.h" | |||
88 | #include "stun.h" | |||
89 | #include "transport_addr.h" | |||
90 | } | |||
91 | ||||
92 | #include "mozilla/RefPtr.h" | |||
93 | #include "test_nr_socket.h" | |||
94 | ||||
95 | namespace mozilla { | |||
96 | ||||
97 | static int test_nat_socket_create(void* obj, nr_transport_addr* addr, | |||
98 | nr_socket** sockp) { | |||
99 | RefPtr<NrSocketBase> sock = new TestNrSocket(static_cast<TestNat*>(obj)); | |||
100 | ||||
101 | int r, _status; | |||
102 | ||||
103 | r = sock->create(addr); | |||
104 | if (r) ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); | |||
105 | ||||
106 | r = nr_socket_create_int(static_cast<void*>(sock), sock->vtbl(), sockp); | |||
107 | if (r) ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); | |||
108 | ||||
109 | _status = 0; | |||
110 | ||||
111 | { | |||
112 | // We will release this reference in destroy(), not exactly the normal | |||
113 | // ownership model, but it is what it is. | |||
114 | NrSocketBase* dummy = sock.forget().take(); | |||
115 | (void)dummy; | |||
116 | } | |||
117 | ||||
118 | abort: | |||
119 | return _status; | |||
120 | } | |||
121 | ||||
122 | static int test_nat_socket_factory_destroy(void** obj) { | |||
123 | TestNat* nat = static_cast<TestNat*>(*obj); | |||
124 | *obj = nullptr; | |||
125 | nat->Release(); | |||
126 | return 0; | |||
127 | } | |||
128 | ||||
129 | static nr_socket_factory_vtbl test_nat_socket_factory_vtbl = { | |||
130 | test_nat_socket_create, test_nat_socket_factory_destroy}; | |||
131 | ||||
132 | /* static */ | |||
133 | TestNat::NatBehavior TestNat::ToNatBehavior(const std::string& type) { | |||
134 | if (type.empty() || !type.compare("ENDPOINT_INDEPENDENT")) { | |||
135 | return TestNat::ENDPOINT_INDEPENDENT; | |||
136 | } | |||
137 | if (!type.compare("ADDRESS_DEPENDENT")) { | |||
138 | return TestNat::ADDRESS_DEPENDENT; | |||
139 | } | |||
140 | if (!type.compare("PORT_DEPENDENT")) { | |||
141 | return TestNat::PORT_DEPENDENT; | |||
142 | } | |||
143 | ||||
144 | MOZ_ASSERT(false, "Invalid NAT behavior")do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false" " (" "Invalid NAT behavior" ")", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "Invalid NAT behavior" ")"); do { *((volatile int*)__null) = 144; ::abort(); } while (false); } } while (false); | |||
145 | return TestNat::ENDPOINT_INDEPENDENT; | |||
146 | } | |||
147 | ||||
148 | bool TestNat::has_port_mappings() const { | |||
149 | for (TestNrSocket* sock : sockets_) { | |||
150 | if (sock->has_port_mappings()) { | |||
151 | return true; | |||
152 | } | |||
153 | } | |||
154 | return false; | |||
155 | } | |||
156 | ||||
157 | bool TestNat::is_my_external_tuple(const nr_transport_addr& addr) const { | |||
158 | for (TestNrSocket* sock : sockets_) { | |||
159 | if (sock->is_my_external_tuple(addr)) { | |||
160 | return true; | |||
161 | } | |||
162 | } | |||
163 | ||||
164 | return false; | |||
165 | } | |||
166 | ||||
167 | bool TestNat::is_an_internal_tuple(const nr_transport_addr& addr) const { | |||
168 | for (TestNrSocket* sock : sockets_) { | |||
169 | nr_transport_addr addr_behind_nat; | |||
170 | if (sock->getaddr(&addr_behind_nat)) { | |||
171 | MOZ_CRASH("TestNrSocket::getaddr failed!")do { do { } while (false); MOZ_ReportCrash("" "TestNrSocket::getaddr failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 171); AnnotateMozCrashReason("MOZ_CRASH(" "TestNrSocket::getaddr failed!" ")"); do { *((volatile int*)__null) = 171; ::abort(); } while (false); } while (false); | |||
172 | } | |||
173 | ||||
174 | if (!nr_transport_addr_cmp(&addr, &addr_behind_nat, | |||
175 | NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) { | |||
176 | return true; | |||
177 | } | |||
178 | } | |||
179 | return false; | |||
180 | } | |||
181 | ||||
182 | int TestNat::create_socket_factory(nr_socket_factory** factorypp) { | |||
183 | int r = nr_socket_factory_create_int(this, &test_nat_socket_factory_vtbl, | |||
184 | factorypp); | |||
185 | if (!r) { | |||
186 | AddRef(); | |||
187 | } | |||
188 | return r; | |||
189 | } | |||
190 | ||||
191 | void TestNat::set_proxy_config( | |||
192 | std::shared_ptr<NrSocketProxyConfig> aProxyConfig) { | |||
193 | proxy_config_ = std::move(aProxyConfig); | |||
194 | } | |||
195 | ||||
196 | TestNrSocket::TestNrSocket(TestNat* nat) | |||
197 | : nat_(nat), tls_(false), timer_handle_(nullptr) { | |||
198 | nat_->insert_socket(this); | |||
199 | } | |||
200 | ||||
201 | TestNrSocket::~TestNrSocket() { nat_->erase_socket(this); } | |||
202 | ||||
203 | RefPtr<NrSocketBase> TestNrSocket::create_external_socket( | |||
204 | const nr_transport_addr& dest_addr) const { | |||
205 | MOZ_ASSERT(nat_->enabled_)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nat_->enabled_)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nat_->enabled_))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nat_->enabled_" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 205); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nat_->enabled_" ")"); do { *((volatile int*)__null) = 205; ::abort(); } while (false); } } while (false); | |||
206 | MOZ_ASSERT(!nat_->is_an_internal_tuple(dest_addr))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!nat_->is_an_internal_tuple(dest_addr))>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(!nat_->is_an_internal_tuple(dest_addr)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!nat_->is_an_internal_tuple(dest_addr)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nat_->is_an_internal_tuple(dest_addr)" ")"); do { *((volatile int*)__null) = 206; ::abort(); } while (false); } } while (false); | |||
207 | ||||
208 | int r; | |||
209 | nr_transport_addr nat_external_addr; | |||
210 | ||||
211 | // Open the socket on an arbitrary port, on the same address. | |||
212 | if ((r = nr_transport_addr_copy(&nat_external_addr, | |||
213 | &internal_socket_->my_addr()))) { | |||
214 | r_log(LOG_GENERIC0, LOG_CRIT2, "%s: Failure in nr_transport_addr_copy: %d", | |||
215 | __FUNCTION__, r); | |||
216 | return nullptr; | |||
217 | } | |||
218 | ||||
219 | if ((r = nr_transport_addr_set_port(&nat_external_addr, 0))) { | |||
220 | r_log(LOG_GENERIC0, LOG_CRIT2, | |||
221 | "%s: Failure in nr_transport_addr_set_port: %d", __FUNCTION__, r); | |||
222 | return nullptr; | |||
223 | } | |||
224 | ||||
225 | RefPtr<NrSocketBase> external_socket; | |||
226 | r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket, | |||
227 | nat_->proxy_config_); | |||
228 | ||||
229 | if (r) { | |||
230 | r_log(LOG_GENERIC0, LOG_CRIT2, "%s: Failure in NrSocket::create: %d", | |||
231 | __FUNCTION__, r); | |||
232 | return nullptr; | |||
233 | } | |||
234 | ||||
235 | return external_socket; | |||
236 | } | |||
237 | ||||
238 | int TestNrSocket::create(nr_transport_addr* addr) { | |||
239 | tls_ = addr->tls; | |||
240 | ||||
241 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p create %s", this, | |||
242 | addr->as_string); | |||
243 | return NrSocketBase::CreateSocket(addr, &internal_socket_, nullptr); | |||
244 | } | |||
245 | ||||
246 | int TestNrSocket::getaddr(nr_transport_addr* addrp) { | |||
247 | return internal_socket_->getaddr(addrp); | |||
248 | } | |||
249 | ||||
250 | void TestNrSocket::close() { | |||
251 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s closing", this, | |||
252 | internal_socket_->my_addr().as_string); | |||
253 | if (timer_handle_) { | |||
254 | NR_async_timer_cancel(timer_handle_); | |||
255 | timer_handle_ = nullptr; | |||
256 | } | |||
257 | internal_socket_->close(); | |||
258 | for (RefPtr<PortMapping>& port_mapping : port_mappings_) { | |||
259 | port_mapping->external_socket_->close(); | |||
260 | } | |||
261 | } | |||
262 | ||||
263 | int TestNrSocket::listen(int backlog) { | |||
264 | MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(internal_socket_->my_addr().protocol == IPPROTO_TCP )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(internal_socket_->my_addr().protocol == IPPROTO_TCP ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "internal_socket_->my_addr().protocol == IPPROTO_TCP", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 264); AnnotateMozCrashReason("MOZ_ASSERT" "(" "internal_socket_->my_addr().protocol == IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 264; ::abort(); } while (false); } } while (false); | |||
265 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s listening", this, | |||
266 | internal_socket_->my_addr().as_string); | |||
267 | ||||
268 | return internal_socket_->listen(backlog); | |||
269 | } | |||
270 | ||||
271 | int TestNrSocket::accept(nr_transport_addr* addrp, nr_socket** sockp) { | |||
272 | MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(internal_socket_->my_addr().protocol == IPPROTO_TCP )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(internal_socket_->my_addr().protocol == IPPROTO_TCP ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "internal_socket_->my_addr().protocol == IPPROTO_TCP", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 272); AnnotateMozCrashReason("MOZ_ASSERT" "(" "internal_socket_->my_addr().protocol == IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 272; ::abort(); } while (false); } } while (false); | |||
273 | int r = internal_socket_->accept(addrp, sockp); | |||
274 | if (r) { | |||
275 | return r; | |||
276 | } | |||
277 | ||||
278 | if (nat_->enabled_ && !nat_->is_an_internal_tuple(*addrp)) { | |||
279 | nr_socket_destroy(sockp); | |||
280 | return R_IO_ERROR13; | |||
281 | } | |||
282 | ||||
283 | return 0; | |||
284 | } | |||
285 | ||||
286 | void TestNrSocket::process_delayed_cb(NR_SOCKET s, int how, void* cb_arg) { | |||
287 | DeferredPacket* op = static_cast<DeferredPacket*>(cb_arg); | |||
288 | op->socket_->timer_handle_ = nullptr; | |||
289 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s sending delayed STUN response", | |||
290 | op->internal_socket_->my_addr().as_string); | |||
291 | op->internal_socket_->sendto(op->buffer_.data(), op->buffer_.len(), | |||
292 | op->flags_, &op->to_); | |||
293 | ||||
294 | delete op; | |||
295 | } | |||
296 | ||||
297 | int TestNrSocket::sendto(const void* msg, size_t len, int flags, | |||
298 | const nr_transport_addr* to) { | |||
299 | MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(internal_socket_->my_addr().protocol != IPPROTO_TCP )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(internal_socket_->my_addr().protocol != IPPROTO_TCP ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "internal_socket_->my_addr().protocol != IPPROTO_TCP", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 299); AnnotateMozCrashReason("MOZ_ASSERT" "(" "internal_socket_->my_addr().protocol != IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 299; ::abort(); } while (false); } } while (false); | |||
300 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s %s", this, __FUNCTION__, | |||
301 | to->as_string); | |||
302 | ||||
303 | if (nat_->nat_delegate_ && | |||
304 | nat_->nat_delegate_->on_sendto(nat_, msg, len, flags, to)) { | |||
305 | return nat_->error_code_for_drop_; | |||
306 | } | |||
307 | ||||
308 | UCHAR* buf = static_cast<UCHAR*>(const_cast<void*>(msg)); | |||
309 | if (nat_->block_stun_ && nr_is_stun_message(buf, len)) { | |||
310 | return nat_->error_code_for_drop_; | |||
311 | } | |||
312 | ||||
313 | if (nr_is_stun_request_message(buf, len) && | |||
314 | maybe_send_fake_response(buf, len, to)) { | |||
315 | return 0; | |||
316 | } | |||
317 | ||||
318 | /* TODO: improve the functionality of this in bug 1253657 */ | |||
319 | if (!nat_->enabled_ || nat_->is_an_internal_tuple(*to)) { | |||
320 | if (nat_->delay_stun_resp_ms_ && nr_is_stun_response_message(buf, len)) { | |||
321 | NR_ASYNC_TIMER_SET(NR_async_timer_set(nat_->delay_stun_resp_ms_,process_delayed_cb ,new DeferredPacket(this, msg, len, flags, to, internal_socket_ ),(char *)__FUNCTION__,324,&timer_handle_) | |||
322 | nat_->delay_stun_resp_ms_, process_delayed_cb,NR_async_timer_set(nat_->delay_stun_resp_ms_,process_delayed_cb ,new DeferredPacket(this, msg, len, flags, to, internal_socket_ ),(char *)__FUNCTION__,324,&timer_handle_) | |||
323 | new DeferredPacket(this, msg, len, flags, to, internal_socket_),NR_async_timer_set(nat_->delay_stun_resp_ms_,process_delayed_cb ,new DeferredPacket(this, msg, len, flags, to, internal_socket_ ),(char *)__FUNCTION__,324,&timer_handle_) | |||
324 | &timer_handle_)NR_async_timer_set(nat_->delay_stun_resp_ms_,process_delayed_cb ,new DeferredPacket(this, msg, len, flags, to, internal_socket_ ),(char *)__FUNCTION__,324,&timer_handle_); | |||
325 | return 0; | |||
326 | } | |||
327 | return internal_socket_->sendto(msg, len, flags, to); | |||
328 | } | |||
329 | ||||
330 | destroy_stale_port_mappings(); | |||
331 | ||||
332 | if (to->protocol == IPPROTO_UDPIPPROTO_UDP && nat_->block_udp_) { | |||
333 | return nat_->error_code_for_drop_; | |||
334 | } | |||
335 | ||||
336 | // Choose our port mapping based on our most selective criteria | |||
337 | PortMapping* port_mapping = get_port_mapping( | |||
338 | *to, std::max(nat_->filtering_type_, nat_->mapping_type_)); | |||
339 | ||||
340 | if (!port_mapping) { | |||
341 | // See if we have already made the external socket we need to use. | |||
342 | PortMapping* similar_port_mapping = | |||
343 | get_port_mapping(*to, nat_->mapping_type_); | |||
344 | RefPtr<NrSocketBase> external_socket; | |||
345 | ||||
346 | if (similar_port_mapping) { | |||
347 | external_socket = similar_port_mapping->external_socket_; | |||
348 | } else { | |||
349 | external_socket = create_external_socket(*to); | |||
350 | if (!external_socket) { | |||
351 | MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"); do { *((volatile int*)__null) = 351; ::abort(); } while (false ); } } while (false); | |||
352 | return R_INTERNAL3; | |||
353 | } | |||
354 | } | |||
355 | ||||
356 | port_mapping = create_port_mapping(*to, external_socket); | |||
357 | port_mappings_.push_back(port_mapping); | |||
358 | ||||
359 | if (poll_flags() & PR_POLL_READ0x1) { | |||
360 | // Make sure the new port mapping is ready to receive traffic if the | |||
361 | // TestNrSocket is already waiting. | |||
362 | port_mapping->async_wait(NR_ASYNC_WAIT_READ0, socket_readable_callback, | |||
363 | this, (char*)__FUNCTION__, __LINE__363); | |||
364 | } | |||
365 | } | |||
366 | ||||
367 | // We probably don't want to propagate the flags, since this is a simulated | |||
368 | // external IP address. | |||
369 | return port_mapping->sendto(msg, len, *to); | |||
370 | } | |||
371 | ||||
372 | int TestNrSocket::recvfrom(void* buf, size_t maxlen, size_t* len, int flags, | |||
373 | nr_transport_addr* from) { | |||
374 | MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(internal_socket_->my_addr().protocol != IPPROTO_TCP )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(internal_socket_->my_addr().protocol != IPPROTO_TCP ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "internal_socket_->my_addr().protocol != IPPROTO_TCP", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 374); AnnotateMozCrashReason("MOZ_ASSERT" "(" "internal_socket_->my_addr().protocol != IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 374; ::abort(); } while (false); } } while (false); | |||
| ||||
375 | ||||
376 | if (!read_buffer_.empty()) { | |||
377 | UdpPacket& packet = read_buffer_.front(); | |||
378 | *len = std::min(maxlen, packet.buffer_->len()); | |||
379 | memcpy(buf, packet.buffer_->data(), *len); | |||
380 | nr_transport_addr_copy(from, &packet.remote_address_); | |||
381 | read_buffer_.pop_front(); | |||
382 | return 0; | |||
383 | } | |||
384 | ||||
385 | int r; | |||
386 | bool ingress_allowed = false; | |||
387 | ||||
388 | if (readable_socket_) { | |||
389 | // If any of the external sockets got data, see if it will be passed through | |||
390 | r = readable_socket_->recvfrom(buf, maxlen, len, 0, from); | |||
391 | const nr_transport_addr to = readable_socket_->my_addr(); | |||
392 | readable_socket_ = nullptr; | |||
393 | if (!r) { | |||
394 | PortMapping* port_mapping_used; | |||
395 | ingress_allowed = allow_ingress(to, *from, &port_mapping_used); | |||
396 | if (ingress_allowed) { | |||
397 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s received from %s via %s", | |||
398 | internal_socket_->my_addr().as_string, from->as_string, | |||
399 | port_mapping_used->external_socket_->my_addr().as_string); | |||
400 | if (nat_->refresh_on_ingress_) { | |||
401 | port_mapping_used->last_used_ = PR_IntervalNow(); | |||
402 | } | |||
403 | } | |||
404 | } | |||
405 | } else { | |||
406 | // If no external socket has data, see if there's any data that was sent | |||
407 | // directly to the TestNrSocket, and eat it if it isn't supposed to get | |||
408 | // through. | |||
409 | r = internal_socket_->recvfrom(buf, maxlen, len, flags, from); | |||
410 | if (!r) { | |||
411 | // We do not use allow_ingress() here because that only handles traffic | |||
412 | // landing on an external port. | |||
413 | ingress_allowed = (!nat_->enabled_ || nat_->is_an_internal_tuple(*from)); | |||
414 | if (!ingress_allowed) { | |||
415 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
416 | "TestNrSocket %s denying ingress from %s: " | |||
417 | "Not behind the same NAT", | |||
418 | internal_socket_->my_addr().as_string, from->as_string); | |||
419 | } else { | |||
420 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s received from %s", | |||
421 | internal_socket_->my_addr().as_string, from->as_string); | |||
422 | } | |||
423 | } | |||
424 | } | |||
425 | ||||
426 | // Kinda bad that we are forced to give the app a readable callback and then | |||
427 | // say "Oh, never mind...", but the alternative is to totally decouple the | |||
428 | // callbacks from STS and the callbacks the app sets. On the bright side, this | |||
429 | // speeds up unit tests where we are verifying that ingress is forbidden, | |||
430 | // since they'll get a readable callback and then an error, instead of having | |||
431 | // to wait for a timeout. | |||
432 | if (!ingress_allowed) { | |||
433 | *len = 0; | |||
434 | r = R_WOULDBLOCK8; | |||
435 | } | |||
436 | ||||
437 | return r; | |||
438 | } | |||
439 | ||||
440 | bool TestNrSocket::allow_ingress(const nr_transport_addr& to, | |||
441 | const nr_transport_addr& from, | |||
442 | PortMapping** port_mapping_used) const { | |||
443 | // This is only called for traffic arriving at a port mapping | |||
444 | MOZ_ASSERT(nat_->enabled_)do { static_assert( mozilla::detail::AssertionConditionType< decltype(nat_->enabled_)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(nat_->enabled_))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("nat_->enabled_" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 444); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nat_->enabled_" ")"); do { *((volatile int*)__null) = 444; ::abort(); } while (false); } } while (false); | |||
445 | MOZ_ASSERT(!nat_->is_an_internal_tuple(from))do { static_assert( mozilla::detail::AssertionConditionType< decltype(!nat_->is_an_internal_tuple(from))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!nat_->is_an_internal_tuple (from)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("!nat_->is_an_internal_tuple(from)", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!nat_->is_an_internal_tuple(from)" ")"); do { *((volatile int*)__null) = 445; ::abort(); } while (false); } } while (false); | |||
446 | ||||
447 | // Find the port mapping (if any) that this packet landed on | |||
448 | for (PortMapping* port_mapping : port_mappings_) { | |||
449 | if (!nr_transport_addr_cmp(&to, &port_mapping->external_socket_->my_addr(), | |||
450 | NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) { | |||
451 | *port_mapping_used = port_mapping; | |||
452 | } | |||
453 | } | |||
454 | ||||
455 | if (NS_WARN_IF(!(*port_mapping_used))NS_warn_if_impl(!(*port_mapping_used), "!(*port_mapping_used)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 455)) { | |||
| ||||
456 | MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType< decltype(false)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while ( false); MOZ_ReportAssertionFailure("false", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"); do { *((volatile int*)__null) = 456; ::abort(); } while (false ); } } while (false); | |||
457 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
458 | "TestNrSocket %s denying ingress from %s: " | |||
459 | "No port mapping for this local port! What?", | |||
460 | internal_socket_->my_addr().as_string, from.as_string); | |||
461 | return false; | |||
462 | } | |||
463 | ||||
464 | if (!port_mapping_matches(**port_mapping_used, from, nat_->filtering_type_)) { | |||
465 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
466 | "TestNrSocket %s denying ingress from %s: " | |||
467 | "Filtered (no port mapping for source)", | |||
468 | internal_socket_->my_addr().as_string, from.as_string); | |||
469 | return false; | |||
470 | } | |||
471 | ||||
472 | if (is_port_mapping_stale(**port_mapping_used)) { | |||
473 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
474 | "TestNrSocket %s denying ingress from %s: " | |||
475 | "Stale port mapping", | |||
476 | internal_socket_->my_addr().as_string, from.as_string); | |||
477 | return false; | |||
478 | } | |||
479 | ||||
480 | if (!nat_->allow_hairpinning_ && nat_->is_my_external_tuple(from)) { | |||
481 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
482 | "TestNrSocket %s denying ingress from %s: " | |||
483 | "Hairpinning disallowed", | |||
484 | internal_socket_->my_addr().as_string, from.as_string); | |||
485 | return false; | |||
486 | } | |||
487 | ||||
488 | return true; | |||
489 | } | |||
490 | ||||
491 | int TestNrSocket::connect(const nr_transport_addr* addr) { | |||
492 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s connecting to %s", this, | |||
493 | internal_socket_->my_addr().as_string, addr->as_string); | |||
494 | ||||
495 | if (connect_invoked_ || !port_mappings_.empty()) { | |||
496 | MOZ_CRASH("TestNrSocket::connect() called more than once!")do { do { } while (false); MOZ_ReportCrash("" "TestNrSocket::connect() called more than once!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 496); AnnotateMozCrashReason("MOZ_CRASH(" "TestNrSocket::connect() called more than once!" ")"); do { *((volatile int*)__null) = 496; ::abort(); } while (false); } while (false); | |||
497 | return R_INTERNAL3; | |||
498 | } | |||
499 | ||||
500 | if (maybe_get_redirect_targets(addr).isSome()) { | |||
501 | // If we are simulating STUN redirects for |addr|, we need to pretend that | |||
502 | // the TCP connection worked, since |addr| probably does not actually point | |||
503 | // at something that exists. | |||
504 | connect_fake_stun_address_.reset(new nr_transport_addr); | |||
505 | nr_transport_addr_copy(connect_fake_stun_address_.get(), addr); | |||
506 | ||||
507 | // We dispatch this, otherwise nICEr can trip over its shoelaces | |||
508 | GetCurrentSerialEventTarget()->Dispatch( | |||
509 | NS_NewRunnableFunction("Async writeable callback for TestNrSocket", | |||
510 | [this, self = RefPtr<TestNrSocket>(this)] { | |||
511 | if (poll_flags() & PR_POLL_WRITE0x2) { | |||
512 | fire_callback(NR_ASYNC_WAIT_WRITE1); | |||
513 | } | |||
514 | })); | |||
515 | ||||
516 | return R_WOULDBLOCK8; | |||
517 | } | |||
518 | ||||
519 | if (!nat_->enabled_ || | |||
520 | addr->protocol == IPPROTO_UDPIPPROTO_UDP // Horrible hack to allow default address | |||
521 | // discovery to work. Only works because | |||
522 | // we don't normally connect on UDP. | |||
523 | || nat_->is_an_internal_tuple(*addr)) { | |||
524 | // This will set connect_invoked_ | |||
525 | return internal_socket_->connect(addr); | |||
526 | } | |||
527 | ||||
528 | RefPtr<NrSocketBase> external_socket(create_external_socket(*addr)); | |||
529 | if (!external_socket) { | |||
530 | return R_INTERNAL3; | |||
531 | } | |||
532 | ||||
533 | PortMapping* port_mapping = create_port_mapping(*addr, external_socket); | |||
534 | port_mappings_.push_back(port_mapping); | |||
535 | int r = port_mapping->external_socket_->connect(addr); | |||
536 | if (r && r != R_WOULDBLOCK8) { | |||
537 | return r; | |||
538 | } | |||
539 | ||||
540 | port_mapping->last_used_ = PR_IntervalNow(); | |||
541 | ||||
542 | if (poll_flags() & PR_POLL_READ0x1) { | |||
543 | port_mapping->async_wait(NR_ASYNC_WAIT_READ0, | |||
544 | port_mapping_tcp_passthrough_callback, this, | |||
545 | (char*)__FUNCTION__, __LINE__545); | |||
546 | } | |||
547 | ||||
548 | return r; | |||
549 | } | |||
550 | ||||
551 | int TestNrSocket::write(const void* msg, size_t len, size_t* written) { | |||
552 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s writing", this, | |||
553 | internal_socket_->my_addr().as_string); | |||
554 | ||||
555 | UCHAR* buf = static_cast<UCHAR*>(const_cast<void*>(msg)); | |||
556 | ||||
557 | if (nat_->nat_delegate_ && | |||
558 | nat_->nat_delegate_->on_write(nat_, msg, len, written)) { | |||
559 | return R_INTERNAL3; | |||
560 | } | |||
561 | ||||
562 | if (nat_->block_stun_ && nr_is_stun_message(buf, len)) { | |||
563 | // Should cause this socket to be abandoned | |||
564 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
565 | "TestNrSocket %s dropping outgoing TCP " | |||
566 | "because it is configured to drop STUN", | |||
567 | my_addr().as_string); | |||
568 | return R_INTERNAL3; | |||
569 | } | |||
570 | ||||
571 | if (nr_is_stun_request_message(buf, len) && connect_fake_stun_address_ && | |||
572 | maybe_send_fake_response(buf, len, connect_fake_stun_address_.get())) { | |||
573 | return 0; | |||
574 | } | |||
575 | ||||
576 | if (nat_->block_tcp_ && !tls_) { | |||
577 | // Should cause this socket to be abandoned | |||
578 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
579 | "TestNrSocket %s dropping outgoing TCP " | |||
580 | "because it is configured to drop TCP", | |||
581 | my_addr().as_string); | |||
582 | return R_INTERNAL3; | |||
583 | } | |||
584 | ||||
585 | if (nat_->block_tls_ && tls_) { | |||
586 | // Should cause this socket to be abandoned | |||
587 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
588 | "TestNrSocket %s dropping outgoing TLS " | |||
589 | "because it is configured to drop TLS", | |||
590 | my_addr().as_string); | |||
591 | return R_INTERNAL3; | |||
592 | } | |||
593 | ||||
594 | if (port_mappings_.empty()) { | |||
595 | // The no-nat case, just pass call through. | |||
596 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s writing", | |||
597 | my_addr().as_string); | |||
598 | ||||
599 | return internal_socket_->write(msg, len, written); | |||
600 | } | |||
601 | destroy_stale_port_mappings(); | |||
602 | if (port_mappings_.empty()) { | |||
603 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
604 | "TestNrSocket %s dropping outgoing TCP " | |||
605 | "because the port mapping was stale", | |||
606 | my_addr().as_string); | |||
607 | return R_INTERNAL3; | |||
608 | } | |||
609 | // This is TCP only | |||
610 | MOZ_ASSERT(port_mappings_.size() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(port_mappings_.size() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(port_mappings_.size() == 1)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("port_mappings_.size() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "port_mappings_.size() == 1" ")"); do { *((volatile int*)__null) = 610; ::abort(); } while (false); } } while (false); | |||
611 | r_log(LOG_GENERIC0, LOG_DEBUG7, "PortMapping %s -> %s writing", | |||
612 | port_mappings_.front()->external_socket_->my_addr().as_string, | |||
613 | port_mappings_.front()->remote_address_.as_string); | |||
614 | port_mappings_.front()->last_used_ = PR_IntervalNow(); | |||
615 | return port_mappings_.front()->external_socket_->write(msg, len, written); | |||
616 | } | |||
617 | ||||
618 | int TestNrSocket::read(void* buf, size_t maxlen, size_t* len) { | |||
619 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s reading", this, | |||
620 | internal_socket_->my_addr().as_string); | |||
621 | ||||
622 | if (!read_buffer_.empty()) { | |||
623 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
624 | "TestNrSocket %p %s has stuff in read_buffer_", this, | |||
625 | internal_socket_->my_addr().as_string); | |||
626 | UdpPacket packet(std::move(read_buffer_.front())); | |||
627 | read_buffer_.pop_front(); | |||
628 | *len = std::min(maxlen, packet.buffer_->len()); | |||
629 | memcpy(buf, packet.buffer_->data(), *len); | |||
630 | if (*len != packet.buffer_->len()) { | |||
631 | // Put remaining bytes in new packet, at the front. | |||
632 | read_buffer_.emplace_front(packet.buffer_->data() + *len, | |||
633 | packet.buffer_->len() - *len, | |||
634 | packet.remote_address_); | |||
635 | } | |||
636 | return 0; | |||
637 | } | |||
638 | ||||
639 | if (connect_fake_stun_address_) { | |||
640 | return R_WOULDBLOCK8; | |||
641 | } | |||
642 | ||||
643 | int r; | |||
644 | ||||
645 | if (port_mappings_.empty()) { | |||
646 | r = internal_socket_->read(buf, maxlen, len); | |||
647 | } else { | |||
648 | MOZ_ASSERT(port_mappings_.size() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(port_mappings_.size() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(port_mappings_.size() == 1)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("port_mappings_.size() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "port_mappings_.size() == 1" ")"); do { *((volatile int*)__null) = 648; ::abort(); } while (false); } } while (false); | |||
649 | r = port_mappings_.front()->external_socket_->read(buf, maxlen, len); | |||
650 | if (!r && nat_->refresh_on_ingress_) { | |||
651 | port_mappings_.front()->last_used_ = PR_IntervalNow(); | |||
652 | } | |||
653 | } | |||
654 | ||||
655 | if (r) { | |||
656 | return r; | |||
657 | } | |||
658 | ||||
659 | if (nat_->nat_delegate_ && | |||
660 | nat_->nat_delegate_->on_read(nat_, buf, maxlen, len)) { | |||
661 | return R_INTERNAL3; | |||
662 | } | |||
663 | ||||
664 | if (nat_->block_tcp_ && !tls_) { | |||
665 | // Should cause this socket to be abandoned | |||
666 | return R_INTERNAL3; | |||
667 | } | |||
668 | ||||
669 | if (nat_->block_tls_ && tls_) { | |||
670 | // Should cause this socket to be abandoned | |||
671 | return R_INTERNAL3; | |||
672 | } | |||
673 | ||||
674 | UCHAR* cbuf = static_cast<UCHAR*>(const_cast<void*>(buf)); | |||
675 | if (nat_->block_stun_ && nr_is_stun_message(cbuf, *len)) { | |||
676 | // Should cause this socket to be abandoned | |||
677 | return R_INTERNAL3; | |||
678 | } | |||
679 | ||||
680 | return r; | |||
681 | } | |||
682 | ||||
683 | int TestNrSocket::async_wait(int how, NR_async_cb cb, void* cb_arg, | |||
684 | char* function, int line) { | |||
685 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s waiting for %s", | |||
686 | internal_socket_->my_addr().as_string, | |||
687 | how == NR_ASYNC_WAIT_READ0 ? "read" : "write"); | |||
688 | ||||
689 | int r; | |||
690 | ||||
691 | if (how == NR_ASYNC_WAIT_READ0) { | |||
692 | NrSocketBase::async_wait(how, cb, cb_arg, function, line); | |||
693 | if (!read_buffer_.empty()) { | |||
694 | fire_readable_callback(); | |||
695 | return 0; | |||
696 | } | |||
697 | ||||
698 | // Make sure we're waiting on the socket for the internal address | |||
699 | r = internal_socket_->async_wait(how, socket_readable_callback, this, | |||
700 | function, line); | |||
701 | } else { | |||
702 | if (connect_fake_stun_address_) { | |||
703 | // Fake TCP connection case; register the callback on this socket, not | |||
704 | // a real one. | |||
705 | return NrSocketBase::async_wait(how, cb, cb_arg, function, line); | |||
706 | } | |||
707 | ||||
708 | // For write, just use the readiness of the internal socket, since we queue | |||
709 | // everything for the port mappings. | |||
710 | r = internal_socket_->async_wait(how, cb, cb_arg, function, line); | |||
711 | } | |||
712 | ||||
713 | if (r) { | |||
714 | r_log(LOG_GENERIC0, LOG_ERR3, | |||
715 | "TestNrSocket %s failed to async_wait for " | |||
716 | "internal socket: %d\n", | |||
717 | internal_socket_->my_addr().as_string, r); | |||
718 | return r; | |||
719 | } | |||
720 | ||||
721 | if (is_tcp_connection_behind_nat()) { | |||
722 | // Bypass all port-mapping related logic | |||
723 | return 0; | |||
724 | } | |||
725 | ||||
726 | if (internal_socket_->my_addr().protocol == IPPROTO_TCPIPPROTO_TCP) { | |||
727 | // For a TCP connection through a simulated NAT, these signals are | |||
728 | // just passed through. | |||
729 | MOZ_ASSERT(port_mappings_.size() == 1)do { static_assert( mozilla::detail::AssertionConditionType< decltype(port_mappings_.size() == 1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(port_mappings_.size() == 1)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("port_mappings_.size() == 1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "port_mappings_.size() == 1" ")"); do { *((volatile int*)__null) = 729; ::abort(); } while (false); } } while (false); | |||
730 | ||||
731 | return port_mappings_.front()->async_wait( | |||
732 | how, port_mapping_tcp_passthrough_callback, this, function, line); | |||
733 | } | |||
734 | if (how == NR_ASYNC_WAIT_READ0) { | |||
735 | // For UDP port mappings, we decouple the writeable callbacks | |||
736 | for (PortMapping* port_mapping : port_mappings_) { | |||
737 | // Be ready to receive traffic on our port mappings | |||
738 | r = port_mapping->async_wait(how, socket_readable_callback, this, | |||
739 | function, line); | |||
740 | if (r) { | |||
741 | r_log(LOG_GENERIC0, LOG_ERR3, | |||
742 | "TestNrSocket %s failed to async_wait for " | |||
743 | "port mapping: %d\n", | |||
744 | internal_socket_->my_addr().as_string, r); | |||
745 | return r; | |||
746 | } | |||
747 | } | |||
748 | } | |||
749 | ||||
750 | return 0; | |||
751 | } | |||
752 | ||||
753 | void TestNrSocket::cancel_port_mapping_async_wait(int how) { | |||
754 | for (PortMapping* port_mapping : port_mappings_) { | |||
755 | port_mapping->cancel(how); | |||
756 | } | |||
757 | } | |||
758 | ||||
759 | int TestNrSocket::cancel(int how) { | |||
760 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s stop waiting for %s", | |||
761 | internal_socket_->my_addr().as_string, | |||
762 | how == NR_ASYNC_WAIT_READ0 ? "read" : "write"); | |||
763 | ||||
764 | if (connect_fake_stun_address_) { | |||
765 | return NrSocketBase::cancel(how); | |||
766 | } | |||
767 | ||||
768 | // Writable callbacks are decoupled except for the TCP case | |||
769 | if (how == NR_ASYNC_WAIT_READ0 || | |||
770 | internal_socket_->my_addr().protocol == IPPROTO_TCPIPPROTO_TCP) { | |||
771 | cancel_port_mapping_async_wait(how); | |||
772 | } | |||
773 | ||||
774 | return internal_socket_->cancel(how); | |||
775 | } | |||
776 | ||||
777 | bool TestNrSocket::has_port_mappings() const { return !port_mappings_.empty(); } | |||
778 | ||||
779 | bool TestNrSocket::is_my_external_tuple(const nr_transport_addr& addr) const { | |||
780 | for (PortMapping* port_mapping : port_mappings_) { | |||
781 | nr_transport_addr port_mapping_addr; | |||
782 | if (port_mapping->external_socket_->getaddr(&port_mapping_addr)) { | |||
783 | MOZ_CRASH("NrSocket::getaddr failed!")do { do { } while (false); MOZ_ReportCrash("" "NrSocket::getaddr failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 783); AnnotateMozCrashReason("MOZ_CRASH(" "NrSocket::getaddr failed!" ")"); do { *((volatile int*)__null) = 783; ::abort(); } while (false); } while (false); | |||
784 | } | |||
785 | ||||
786 | if (!nr_transport_addr_cmp(&addr, &port_mapping_addr, | |||
787 | NR_TRANSPORT_ADDR_CMP_MODE_ALL4)) { | |||
788 | return true; | |||
789 | } | |||
790 | } | |||
791 | return false; | |||
792 | } | |||
793 | ||||
794 | bool TestNrSocket::is_port_mapping_stale( | |||
795 | const PortMapping& port_mapping) const { | |||
796 | PRIntervalTime now = PR_IntervalNow(); | |||
797 | PRIntervalTime elapsed_ticks = now - port_mapping.last_used_; | |||
798 | uint32_t idle_duration = PR_IntervalToMilliseconds(elapsed_ticks); | |||
799 | return idle_duration > nat_->mapping_timeout_; | |||
800 | } | |||
801 | ||||
802 | void TestNrSocket::destroy_stale_port_mappings() { | |||
803 | for (auto i = port_mappings_.begin(); i != port_mappings_.end();) { | |||
804 | auto temp = i; | |||
805 | ++i; | |||
806 | if (is_port_mapping_stale(**temp)) { | |||
807 | r_log(LOG_GENERIC0, LOG_INFO6, | |||
808 | "TestNrSocket %s destroying port mapping %s -> %s", | |||
809 | internal_socket_->my_addr().as_string, | |||
810 | (*temp)->external_socket_->my_addr().as_string, | |||
811 | (*temp)->remote_address_.as_string); | |||
812 | ||||
813 | port_mappings_.erase(temp); | |||
814 | } | |||
815 | } | |||
816 | } | |||
817 | ||||
818 | void TestNrSocket::socket_readable_callback(void* real_sock_v, int how, | |||
819 | void* test_sock_v) { | |||
820 | TestNrSocket* test_socket = static_cast<TestNrSocket*>(test_sock_v); | |||
821 | NrSocketBase* real_socket = static_cast<NrSocketBase*>(real_sock_v); | |||
822 | ||||
823 | test_socket->on_socket_readable(real_socket); | |||
824 | } | |||
825 | ||||
826 | void TestNrSocket::on_socket_readable(NrSocketBase* real_socket) { | |||
827 | if (!readable_socket_ && (real_socket != internal_socket_)) { | |||
828 | readable_socket_ = real_socket; | |||
829 | } | |||
830 | ||||
831 | fire_readable_callback(); | |||
832 | } | |||
833 | ||||
834 | void TestNrSocket::fire_readable_callback() { | |||
835 | MOZ_ASSERT(poll_flags() & PR_POLL_READ)do { static_assert( mozilla::detail::AssertionConditionType< decltype(poll_flags() & 0x1)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(poll_flags() & 0x1))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("poll_flags() & 0x1" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "poll_flags() & 0x1" ")"); do { *((volatile int*)__null) = 835; ::abort(); } while (false); } } while (false); | |||
836 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %p %s ready for read", this, | |||
837 | internal_socket_->my_addr().as_string); | |||
838 | fire_callback(NR_ASYNC_WAIT_READ0); | |||
839 | } | |||
840 | ||||
841 | void TestNrSocket::port_mapping_writeable_callback(void* ext_sock_v, int how, | |||
842 | void* test_sock_v) { | |||
843 | TestNrSocket* test_socket = static_cast<TestNrSocket*>(test_sock_v); | |||
844 | NrSocketBase* external_socket = static_cast<NrSocketBase*>(ext_sock_v); | |||
845 | ||||
846 | test_socket->write_to_port_mapping(external_socket); | |||
847 | } | |||
848 | ||||
849 | void TestNrSocket::write_to_port_mapping(NrSocketBase* external_socket) { | |||
850 | MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(internal_socket_->my_addr().protocol != IPPROTO_TCP )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(internal_socket_->my_addr().protocol != IPPROTO_TCP ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "internal_socket_->my_addr().protocol != IPPROTO_TCP", "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "internal_socket_->my_addr().protocol != IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 850; ::abort(); } while (false); } } while (false); | |||
851 | ||||
852 | int r = 0; | |||
853 | for (PortMapping* port_mapping : port_mappings_) { | |||
854 | if (port_mapping->external_socket_ == external_socket) { | |||
855 | // If the send succeeds, or if there was nothing to send, we keep going | |||
856 | r = port_mapping->send_from_queue(); | |||
857 | if (r) { | |||
858 | break; | |||
859 | } | |||
860 | } | |||
861 | } | |||
862 | ||||
863 | if (r == R_WOULDBLOCK8) { | |||
864 | // Re-register for writeable callbacks, since we still have stuff to send | |||
865 | NR_ASYNC_WAIT(external_socket, NR_ASYNC_WAIT_WRITE,NR_async_wait(external_socket,1,&TestNrSocket::port_mapping_writeable_callback ,this,(char *)__FUNCTION__,866) | |||
866 | &TestNrSocket::port_mapping_writeable_callback, this)NR_async_wait(external_socket,1,&TestNrSocket::port_mapping_writeable_callback ,this,(char *)__FUNCTION__,866); | |||
867 | } | |||
868 | } | |||
869 | ||||
870 | void TestNrSocket::port_mapping_tcp_passthrough_callback(void* ext_sock_v, | |||
871 | int how, | |||
872 | void* test_sock_v) { | |||
873 | TestNrSocket* test_socket = static_cast<TestNrSocket*>(test_sock_v); | |||
874 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket %s firing %s callback", | |||
875 | test_socket->internal_socket_->my_addr().as_string, | |||
876 | how == NR_ASYNC_WAIT_READ0 ? "readable" : "writeable"); | |||
877 | ||||
878 | test_socket->internal_socket_->fire_callback(how); | |||
879 | } | |||
880 | ||||
881 | bool TestNrSocket::is_tcp_connection_behind_nat() const { | |||
882 | return internal_socket_->my_addr().protocol == IPPROTO_TCPIPPROTO_TCP && | |||
883 | port_mappings_.empty(); | |||
884 | } | |||
885 | ||||
886 | TestNrSocket::PortMapping* TestNrSocket::get_port_mapping( | |||
887 | const nr_transport_addr& remote_address, | |||
888 | TestNat::NatBehavior filter) const { | |||
889 | for (PortMapping* port_mapping : port_mappings_) { | |||
890 | if (port_mapping_matches(*port_mapping, remote_address, filter)) { | |||
891 | return port_mapping; | |||
892 | } | |||
893 | } | |||
894 | return nullptr; | |||
895 | } | |||
896 | ||||
897 | /* static */ | |||
898 | bool TestNrSocket::port_mapping_matches(const PortMapping& port_mapping, | |||
899 | const nr_transport_addr& remote_addr, | |||
900 | TestNat::NatBehavior filter) { | |||
901 | int compare_flags; | |||
902 | switch (filter) { | |||
903 | case TestNat::ENDPOINT_INDEPENDENT: | |||
904 | compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL2; | |||
905 | break; | |||
906 | case TestNat::ADDRESS_DEPENDENT: | |||
907 | compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_ADDR3; | |||
908 | break; | |||
909 | case TestNat::PORT_DEPENDENT: | |||
910 | compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_ALL4; | |||
911 | break; | |||
912 | } | |||
913 | ||||
914 | return !nr_transport_addr_cmp(&remote_addr, &port_mapping.remote_address_, | |||
915 | compare_flags); | |||
916 | } | |||
917 | ||||
918 | TestNrSocket::PortMapping* TestNrSocket::create_port_mapping( | |||
919 | const nr_transport_addr& remote_address, | |||
920 | const RefPtr<NrSocketBase>& external_socket) const { | |||
921 | r_log(LOG_GENERIC0, LOG_INFO6, "TestNrSocket %s creating port mapping %s -> %s", | |||
922 | internal_socket_->my_addr().as_string, | |||
923 | external_socket->my_addr().as_string, remote_address.as_string); | |||
924 | ||||
925 | return new PortMapping(remote_address, external_socket); | |||
926 | } | |||
927 | ||||
928 | TestNrSocket::PortMapping::PortMapping( | |||
929 | const nr_transport_addr& remote_address, | |||
930 | const RefPtr<NrSocketBase>& external_socket) | |||
931 | : external_socket_(external_socket) { | |||
932 | nr_transport_addr_copy(&remote_address_, &remote_address); | |||
933 | } | |||
934 | ||||
935 | int TestNrSocket::PortMapping::send_from_queue() { | |||
936 | MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(remote_address_.protocol != IPPROTO_TCP)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(remote_address_.protocol != IPPROTO_TCP))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("remote_address_.protocol != IPPROTO_TCP" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 936); AnnotateMozCrashReason("MOZ_ASSERT" "(" "remote_address_.protocol != IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 936; ::abort(); } while (false); } } while (false); | |||
937 | int r = 0; | |||
938 | ||||
939 | while (!send_queue_.empty()) { | |||
940 | UdpPacket& packet = send_queue_.front(); | |||
941 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
942 | "PortMapping %s -> %s sending from queue to %s", | |||
943 | external_socket_->my_addr().as_string, remote_address_.as_string, | |||
944 | packet.remote_address_.as_string); | |||
945 | ||||
946 | r = external_socket_->sendto(packet.buffer_->data(), packet.buffer_->len(), | |||
947 | 0, &packet.remote_address_); | |||
948 | ||||
949 | if (r) { | |||
950 | if (r != R_WOULDBLOCK8) { | |||
951 | r_log(LOG_GENERIC0, LOG_ERR3, "%s: Fatal error %d, stop trying", | |||
952 | __FUNCTION__, r); | |||
953 | send_queue_.clear(); | |||
954 | } else { | |||
955 | r_log(LOG_GENERIC0, LOG_DEBUG7, "Would block, will retry later"); | |||
956 | } | |||
957 | break; | |||
958 | } | |||
959 | ||||
960 | send_queue_.pop_front(); | |||
961 | } | |||
962 | ||||
963 | return r; | |||
964 | } | |||
965 | ||||
966 | int TestNrSocket::PortMapping::sendto(const void* msg, size_t len, | |||
967 | const nr_transport_addr& to) { | |||
968 | MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP)do { static_assert( mozilla::detail::AssertionConditionType< decltype(remote_address_.protocol != IPPROTO_TCP)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(remote_address_.protocol != IPPROTO_TCP))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("remote_address_.protocol != IPPROTO_TCP" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "remote_address_.protocol != IPPROTO_TCP" ")"); do { *((volatile int*)__null) = 968; ::abort(); } while (false); } } while (false); | |||
969 | r_log(LOG_GENERIC0, LOG_DEBUG7, "PortMapping %s -> %s sending to %s", | |||
970 | external_socket_->my_addr().as_string, remote_address_.as_string, | |||
971 | to.as_string); | |||
972 | ||||
973 | last_used_ = PR_IntervalNow(); | |||
974 | int r = external_socket_->sendto(msg, len, 0, &to); | |||
975 | ||||
976 | if (r == R_WOULDBLOCK8) { | |||
977 | r_log(LOG_GENERIC0, LOG_DEBUG7, "Enqueueing UDP packet to %s", to.as_string); | |||
978 | send_queue_.emplace_back(msg, len, to); | |||
979 | return 0; | |||
980 | } | |||
981 | if (r) { | |||
982 | r_log(LOG_GENERIC0, LOG_ERR3, "Error: %d", r); | |||
983 | } | |||
984 | ||||
985 | return r; | |||
986 | } | |||
987 | ||||
988 | int TestNrSocket::PortMapping::async_wait(int how, NR_async_cb cb, void* cb_arg, | |||
989 | char* function, int line) { | |||
990 | r_log(LOG_GENERIC0, LOG_DEBUG7, "PortMapping %s -> %s waiting for %s", | |||
991 | external_socket_->my_addr().as_string, remote_address_.as_string, | |||
992 | how == NR_ASYNC_WAIT_READ0 ? "read" : "write"); | |||
993 | ||||
994 | return external_socket_->async_wait(how, cb, cb_arg, function, line); | |||
995 | } | |||
996 | ||||
997 | int TestNrSocket::PortMapping::cancel(int how) { | |||
998 | r_log(LOG_GENERIC0, LOG_DEBUG7, "PortMapping %s -> %s stop waiting for %s", | |||
999 | external_socket_->my_addr().as_string, remote_address_.as_string, | |||
1000 | how == NR_ASYNC_WAIT_READ0 ? "read" : "write"); | |||
1001 | ||||
1002 | return external_socket_->cancel(how); | |||
1003 | } | |||
1004 | ||||
1005 | class nr_stun_message_deleter { | |||
1006 | public: | |||
1007 | nr_stun_message_deleter() = default; | |||
1008 | void operator()(nr_stun_message* msg) const { nr_stun_message_destroy(&msg); } | |||
1009 | }; | |||
1010 | ||||
1011 | bool TestNrSocket::maybe_send_fake_response(const void* msg, size_t len, | |||
1012 | const nr_transport_addr* to) { | |||
1013 | Maybe<nsTArray<nsCString>> redirect_targets = maybe_get_redirect_targets(to); | |||
1014 | if (!redirect_targets.isSome()) { | |||
1015 | return false; | |||
1016 | } | |||
1017 | ||||
1018 | std::unique_ptr<nr_stun_message, nr_stun_message_deleter> request; | |||
1019 | { | |||
1020 | nr_stun_message* temp = nullptr; | |||
1021 | if (NS_WARN_IF(nr_stun_message_create2(&temp, (unsigned char*)msg, len))NS_warn_if_impl(nr_stun_message_create2(&temp, (unsigned char *)msg, len), "nr_stun_message_create2(&temp, (unsigned char*)msg, len)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1021)) { | |||
1022 | return false; | |||
1023 | } | |||
1024 | request.reset(temp); | |||
1025 | } | |||
1026 | ||||
1027 | if (NS_WARN_IF(nr_stun_decode_message(request.get(), nullptr, nullptr))NS_warn_if_impl(nr_stun_decode_message(request.get(), nullptr , nullptr), "nr_stun_decode_message(request.get(), nullptr, nullptr)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1027)) { | |||
1028 | return false; | |||
1029 | } | |||
1030 | ||||
1031 | std::unique_ptr<nr_stun_message, nr_stun_message_deleter> response; | |||
1032 | { | |||
1033 | nr_stun_message* temp = nullptr; | |||
1034 | if (nr_stun_message_create(&temp)) { | |||
1035 | MOZ_CRASH("nr_stun_message_create failed!")do { do { } while (false); MOZ_ReportCrash("" "nr_stun_message_create failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1035); AnnotateMozCrashReason("MOZ_CRASH(" "nr_stun_message_create failed!" ")"); do { *((volatile int*)__null) = 1035; ::abort(); } while (false); } while (false); | |||
1036 | } | |||
1037 | response.reset(temp); | |||
1038 | } | |||
1039 | ||||
1040 | nr_stun_form_error_response(request.get(), response.get(), 300, | |||
1041 | (char*)"Try alternate"); | |||
1042 | ||||
1043 | int port = 0; | |||
1044 | if (nr_transport_addr_get_port(to, &port)) { | |||
1045 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1045); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 1045; ::abort(); } while (false); } while (false ); | |||
1046 | } | |||
1047 | ||||
1048 | for (const nsCString& address : *redirect_targets) { | |||
1049 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
1050 | "TestNrSocket attempting to add alternate server %s", address.Data()); | |||
1051 | nr_transport_addr addr; | |||
1052 | if (NS_WARN_IF(nr_str_port_to_transport_addr(address.Data(), port,NS_warn_if_impl(nr_str_port_to_transport_addr(address.Data(), port, IPPROTO_UDP, &addr), "nr_str_port_to_transport_addr(address.Data(), port, IPPROTO_UDP, &addr)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1053) | |||
1053 | IPPROTO_UDP, &addr))NS_warn_if_impl(nr_str_port_to_transport_addr(address.Data(), port, IPPROTO_UDP, &addr), "nr_str_port_to_transport_addr(address.Data(), port, IPPROTO_UDP, &addr)" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1053)) { | |||
1054 | continue; | |||
1055 | } | |||
1056 | if (nr_stun_message_add_alternate_server_attribute(response.get(), &addr)) { | |||
1057 | MOZ_CRASH("nr_stun_message_add_alternate_server_attribute failed!")do { do { } while (false); MOZ_ReportCrash("" "nr_stun_message_add_alternate_server_attribute failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1057); AnnotateMozCrashReason("MOZ_CRASH(" "nr_stun_message_add_alternate_server_attribute failed!" ")"); do { *((volatile int*)__null) = 1057; ::abort(); } while (false); } while (false); | |||
1058 | } | |||
1059 | } | |||
1060 | ||||
1061 | if (nr_stun_encode_message(response.get())) { | |||
1062 | MOZ_CRASH("nr_stun_encode_message failed!")do { do { } while (false); MOZ_ReportCrash("" "nr_stun_encode_message failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1062); AnnotateMozCrashReason("MOZ_CRASH(" "nr_stun_encode_message failed!" ")"); do { *((volatile int*)__null) = 1062; ::abort(); } while (false); } while (false); | |||
1063 | } | |||
1064 | ||||
1065 | nr_transport_addr response_from; | |||
1066 | if (nr_transport_addr_is_wildcard(to)) { | |||
1067 | // |to| points to an FQDN, and nICEr is delegating DNS lookup to us; we | |||
1068 | // aren't _actually_ going to do that though, so we select a bogus address | |||
1069 | // for the response to come from. TEST-NET is a fairly reasonable thing to | |||
1070 | // use for this. | |||
1071 | int port = 0; | |||
1072 | if (nr_transport_addr_get_port(to, &port)) { | |||
1073 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1073); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 1073; ::abort(); } while (false); } while (false ); | |||
1074 | } | |||
1075 | switch (to->ip_version) { | |||
1076 | case NR_IPV44: | |||
1077 | if (nr_str_port_to_transport_addr("198.51.100.1", port, to->protocol, | |||
1078 | &response_from)) { | |||
1079 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1079); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 1079; ::abort(); } while (false); } while (false ); | |||
1080 | } | |||
1081 | break; | |||
1082 | case NR_IPV66: | |||
1083 | if (nr_str_port_to_transport_addr("::ffff:198.51.100.1", port, | |||
1084 | to->protocol, &response_from)) { | |||
1085 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1085); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 1085; ::abort(); } while (false); } while (false ); | |||
1086 | } | |||
1087 | break; | |||
1088 | default: | |||
1089 | MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1089); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile int*)__null) = 1089; ::abort(); } while (false); } while (false ); | |||
1090 | } | |||
1091 | } else { | |||
1092 | nr_transport_addr_copy(&response_from, to); | |||
1093 | } | |||
1094 | ||||
1095 | read_buffer_.emplace_back(response->buffer, response->length, response_from); | |||
1096 | ||||
1097 | // We dispatch this, otherwise nICEr can trip over its shoelaces | |||
1098 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
1099 | "TestNrSocket %p scheduling callback for redirect response", this); | |||
1100 | GetCurrentSerialEventTarget()->Dispatch(NS_NewRunnableFunction( | |||
1101 | "Async readable callback for TestNrSocket", | |||
1102 | [this, self = RefPtr<TestNrSocket>(this)] { | |||
1103 | if (poll_flags() & PR_POLL_READ0x1) { | |||
1104 | fire_readable_callback(); | |||
1105 | } else { | |||
1106 | r_log(LOG_GENERIC0, LOG_DEBUG7, | |||
1107 | "TestNrSocket %p deferring callback for redirect response", | |||
1108 | this); | |||
1109 | } | |||
1110 | })); | |||
1111 | ||||
1112 | return true; | |||
1113 | } | |||
1114 | ||||
1115 | Maybe<nsTArray<nsCString>> TestNrSocket::maybe_get_redirect_targets( | |||
1116 | const nr_transport_addr* to) const { | |||
1117 | Maybe<nsTArray<nsCString>> result; | |||
1118 | ||||
1119 | // 256 is overkill, but it hardly matters | |||
1120 | char addrstring[256]; | |||
1121 | if (nr_transport_addr_get_addrstring(to, addrstring, 256)) { | |||
1122 | MOZ_CRASH("nr_transport_addr_get_addrstring failed!")do { do { } while (false); MOZ_ReportCrash("" "nr_transport_addr_get_addrstring failed!" , "/var/lib/jenkins/workspace/firefox-scan-build/dom/media/webrtc/transport/test_nr_socket.cpp" , 1122); AnnotateMozCrashReason("MOZ_CRASH(" "nr_transport_addr_get_addrstring failed!" ")"); do { *((volatile int*)__null) = 1122; ::abort(); } while (false); } while (false); | |||
1123 | } | |||
1124 | ||||
1125 | r_log(LOG_GENERIC0, LOG_DEBUG7, "TestNrSocket checking redirect rules for %s", | |||
1126 | addrstring); | |||
1127 | auto it = nat_->stun_redirect_map_.find(nsCString(addrstring)); | |||
1128 | if (it != nat_->stun_redirect_map_.end()) { | |||
1129 | result = Some(it->second); | |||
1130 | } | |||
1131 | ||||
1132 | return result; | |||
1133 | } | |||
1134 | ||||
1135 | } // namespace mozilla |