test_nr_socket.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /*
  6. */
  7. /*
  8. Based partially on original code from nICEr and nrappkit.
  9. nICEr copyright:
  10. Copyright (c) 2007, Adobe Systems, Incorporated
  11. All rights reserved.
  12. Redistribution and use in source and binary forms, with or without
  13. modification, are permitted provided that the following conditions are
  14. met:
  15. * Redistributions of source code must retain the above copyright
  16. notice, this list of conditions and the following disclaimer.
  17. * Redistributions in binary form must reproduce the above copyright
  18. notice, this list of conditions and the following disclaimer in the
  19. documentation and/or other materials provided with the distribution.
  20. * Neither the name of Adobe Systems, Network Resonance nor the names of its
  21. contributors may be used to endorse or promote products derived from
  22. this software without specific prior written permission.
  23. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  29. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. nrappkit copyright:
  35. Copyright (C) 2001-2003, Network Resonance, Inc.
  36. Copyright (C) 2006, Network Resonance, Inc.
  37. All Rights Reserved
  38. Redistribution and use in source and binary forms, with or without
  39. modification, are permitted provided that the following conditions
  40. are met:
  41. 1. Redistributions of source code must retain the above copyright
  42. notice, this list of conditions and the following disclaimer.
  43. 2. Redistributions in binary form must reproduce the above copyright
  44. notice, this list of conditions and the following disclaimer in the
  45. documentation and/or other materials provided with the distribution.
  46. 3. Neither the name of Network Resonance, Inc. nor the name of any
  47. contributors to this software may be used to endorse or promote
  48. products derived from this software without specific prior written
  49. permission.
  50. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  51. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  52. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  53. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  54. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  55. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  56. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  57. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  58. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  59. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  60. POSSIBILITY OF SUCH DAMAGE.
  61. ekr@rtfm.com Thu Dec 20 20:14:49 2001
  62. */
  63. // Original author: bcampen@mozilla.com [:bwc]
  64. extern "C" {
  65. #include "stun_msg.h" // for NR_STUN_MAX_MESSAGE_SIZE
  66. #include "nr_api.h"
  67. #include "async_wait.h"
  68. #include "async_timer.h"
  69. #include "nr_socket.h"
  70. #include "nr_socket_local.h"
  71. #include "stun_hint.h"
  72. #include "transport_addr.h"
  73. }
  74. #include "mozilla/RefPtr.h"
  75. #include "test_nr_socket.h"
  76. #include "runnable_utils.h"
  77. namespace mozilla {
  78. static int test_nat_socket_create(void *obj,
  79. nr_transport_addr *addr,
  80. nr_socket **sockp) {
  81. RefPtr<NrSocketBase> sock = new TestNrSocket(static_cast<TestNat*>(obj));
  82. int r, _status;
  83. r = sock->create(addr);
  84. if (r)
  85. ABORT(r);
  86. r = nr_socket_create_int(static_cast<void *>(sock),
  87. sock->vtbl(), sockp);
  88. if (r)
  89. ABORT(r);
  90. _status = 0;
  91. {
  92. // We will release this reference in destroy(), not exactly the normal
  93. // ownership model, but it is what it is.
  94. NrSocketBase *dummy = sock.forget().take();
  95. (void)dummy;
  96. }
  97. abort:
  98. return _status;
  99. }
  100. static int test_nat_socket_factory_destroy(void **obj) {
  101. TestNat *nat = static_cast<TestNat*>(*obj);
  102. *obj = nullptr;
  103. nat->Release();
  104. return 0;
  105. }
  106. static nr_socket_factory_vtbl test_nat_socket_factory_vtbl = {
  107. test_nat_socket_create,
  108. test_nat_socket_factory_destroy
  109. };
  110. /* static */
  111. TestNat::NatBehavior
  112. TestNat::ToNatBehavior(const std::string& type) {
  113. if (!type.compare("ENDPOINT_INDEPENDENT")) {
  114. return TestNat::ENDPOINT_INDEPENDENT;
  115. } else if (!type.compare("ADDRESS_DEPENDENT")) {
  116. return TestNat::ADDRESS_DEPENDENT;
  117. } else if (!type.compare("PORT_DEPENDENT")) {
  118. return TestNat::PORT_DEPENDENT;
  119. }
  120. MOZ_ASSERT(false, "Invalid NAT behavior");
  121. return TestNat::ENDPOINT_INDEPENDENT;
  122. }
  123. bool TestNat::has_port_mappings() const {
  124. for (TestNrSocket *sock : sockets_) {
  125. if (sock->has_port_mappings()) {
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. bool TestNat::is_my_external_tuple(const nr_transport_addr &addr) const {
  132. for (TestNrSocket *sock : sockets_) {
  133. if (sock->is_my_external_tuple(addr)) {
  134. return true;
  135. }
  136. }
  137. return false;
  138. }
  139. bool TestNat::is_an_internal_tuple(const nr_transport_addr &addr) const {
  140. for (TestNrSocket *sock : sockets_) {
  141. nr_transport_addr addr_behind_nat;
  142. if (sock->getaddr(&addr_behind_nat)) {
  143. MOZ_CRASH("TestNrSocket::getaddr failed!");
  144. }
  145. // TODO(bug 1170299): Remove const_cast when no longer necessary
  146. if (!nr_transport_addr_cmp(const_cast<nr_transport_addr*>(&addr),
  147. &addr_behind_nat,
  148. NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
  149. return true;
  150. }
  151. }
  152. return false;
  153. }
  154. int TestNat::create_socket_factory(nr_socket_factory **factorypp) {
  155. int r = nr_socket_factory_create_int(this,
  156. &test_nat_socket_factory_vtbl,
  157. factorypp);
  158. if (!r) {
  159. AddRef();
  160. }
  161. return r;
  162. }
  163. TestNrSocket::TestNrSocket(TestNat *nat)
  164. : nat_(nat),
  165. timer_handle_(nullptr) {
  166. nat_->insert_socket(this);
  167. }
  168. TestNrSocket::~TestNrSocket() {
  169. nat_->erase_socket(this);
  170. }
  171. RefPtr<NrSocketBase> TestNrSocket::create_external_socket(
  172. const nr_transport_addr &dest_addr) const {
  173. MOZ_ASSERT(nat_->enabled_);
  174. MOZ_ASSERT(!nat_->is_an_internal_tuple(dest_addr));
  175. int r;
  176. nr_transport_addr nat_external_addr;
  177. // Open the socket on an arbitrary port, on the same address.
  178. // TODO(bug 1170299): Remove const_cast when no longer necessary
  179. if ((r = nr_transport_addr_copy(
  180. &nat_external_addr,
  181. const_cast<nr_transport_addr*>(&internal_socket_->my_addr())))) {
  182. r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_copy: %d",
  183. __FUNCTION__, r);
  184. return nullptr;
  185. }
  186. if ((r = nr_transport_addr_set_port(&nat_external_addr, 0))) {
  187. r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in nr_transport_addr_set_port: %d",
  188. __FUNCTION__, r);
  189. return nullptr;
  190. }
  191. RefPtr<NrSocketBase> external_socket;
  192. r = NrSocketBase::CreateSocket(&nat_external_addr, &external_socket);
  193. if (r) {
  194. r_log(LOG_GENERIC,LOG_CRIT, "%s: Failure in NrSocket::create: %d",
  195. __FUNCTION__, r);
  196. return nullptr;
  197. }
  198. return external_socket;
  199. }
  200. int TestNrSocket::create(nr_transport_addr *addr) {
  201. return NrSocketBase::CreateSocket(addr, &internal_socket_);
  202. }
  203. int TestNrSocket::getaddr(nr_transport_addr *addrp) {
  204. return internal_socket_->getaddr(addrp);
  205. }
  206. void TestNrSocket::close() {
  207. if (timer_handle_) {
  208. NR_async_timer_cancel(timer_handle_);
  209. timer_handle_ = 0;
  210. }
  211. internal_socket_->close();
  212. for (RefPtr<PortMapping>& port_mapping : port_mappings_) {
  213. port_mapping->external_socket_->close();
  214. }
  215. }
  216. int TestNrSocket::listen(int backlog) {
  217. MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP);
  218. r_log(LOG_GENERIC, LOG_DEBUG,
  219. "TestNrSocket %s listening",
  220. internal_socket_->my_addr().as_string);
  221. return internal_socket_->listen(backlog);
  222. }
  223. int TestNrSocket::accept(nr_transport_addr *addrp, nr_socket **sockp) {
  224. MOZ_ASSERT(internal_socket_->my_addr().protocol == IPPROTO_TCP);
  225. int r = internal_socket_->accept(addrp, sockp);
  226. if (r) {
  227. return r;
  228. }
  229. if (nat_->enabled_ && !nat_->is_an_internal_tuple(*addrp)) {
  230. nr_socket_destroy(sockp);
  231. return R_IO_ERROR;
  232. }
  233. return 0;
  234. }
  235. void TestNrSocket::process_delayed_cb(NR_SOCKET s, int how, void *cb_arg) {
  236. DeferredPacket *op = static_cast<DeferredPacket *>(cb_arg);
  237. op->socket_->timer_handle_ = nullptr;
  238. r_log(LOG_GENERIC, LOG_DEBUG,
  239. "TestNrSocket %s sending delayed STUN response",
  240. op->internal_socket_->my_addr().as_string);
  241. op->internal_socket_->sendto(op->buffer_.data(), op->buffer_.len(),
  242. op->flags_, &op->to_);
  243. delete op;
  244. }
  245. int TestNrSocket::sendto(const void *msg, size_t len,
  246. int flags, nr_transport_addr *to) {
  247. MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP);
  248. UCHAR *buf = static_cast<UCHAR*>(const_cast<void*>(msg));
  249. if (nat_->block_stun_ &&
  250. nr_is_stun_message(buf, len)) {
  251. return 0;
  252. }
  253. /* TODO: improve the functionality of this in bug 1253657 */
  254. if (!nat_->enabled_ || nat_->is_an_internal_tuple(*to)) {
  255. if (nat_->delay_stun_resp_ms_ &&
  256. nr_is_stun_response_message(buf, len)) {
  257. NR_ASYNC_TIMER_SET(nat_->delay_stun_resp_ms_,
  258. process_delayed_cb,
  259. new DeferredPacket(this, msg, len, flags, to,
  260. internal_socket_),
  261. &timer_handle_);
  262. return 0;
  263. }
  264. return internal_socket_->sendto(msg, len, flags, to);
  265. }
  266. destroy_stale_port_mappings();
  267. if (to->protocol == IPPROTO_UDP && nat_->block_udp_) {
  268. // Silently eat the packet
  269. return 0;
  270. }
  271. // Choose our port mapping based on our most selective criteria
  272. PortMapping *port_mapping = get_port_mapping(*to,
  273. std::max(nat_->filtering_type_,
  274. nat_->mapping_type_));
  275. if (!port_mapping) {
  276. // See if we have already made the external socket we need to use.
  277. PortMapping *similar_port_mapping =
  278. get_port_mapping(*to, nat_->mapping_type_);
  279. RefPtr<NrSocketBase> external_socket;
  280. if (similar_port_mapping) {
  281. external_socket = similar_port_mapping->external_socket_;
  282. } else {
  283. external_socket = create_external_socket(*to);
  284. if (!external_socket) {
  285. MOZ_ASSERT(false);
  286. return R_INTERNAL;
  287. }
  288. }
  289. port_mapping = create_port_mapping(*to, external_socket);
  290. port_mappings_.push_back(port_mapping);
  291. if (poll_flags() & PR_POLL_READ) {
  292. // Make sure the new port mapping is ready to receive traffic if the
  293. // TestNrSocket is already waiting.
  294. port_mapping->async_wait(NR_ASYNC_WAIT_READ,
  295. socket_readable_callback,
  296. this,
  297. (char*)__FUNCTION__,
  298. __LINE__);
  299. }
  300. }
  301. // We probably don't want to propagate the flags, since this is a simulated
  302. // external IP address.
  303. return port_mapping->sendto(msg, len, *to);
  304. }
  305. int TestNrSocket::recvfrom(void *buf, size_t maxlen,
  306. size_t *len, int flags,
  307. nr_transport_addr *from) {
  308. MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP);
  309. int r;
  310. bool ingress_allowed = false;
  311. if (readable_socket_) {
  312. // If any of the external sockets got data, see if it will be passed through
  313. r = readable_socket_->recvfrom(buf, maxlen, len, 0, from);
  314. readable_socket_ = nullptr;
  315. if (!r) {
  316. PortMapping *port_mapping_used;
  317. ingress_allowed = allow_ingress(*from, &port_mapping_used);
  318. if (ingress_allowed) {
  319. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s received from %s via %s",
  320. internal_socket_->my_addr().as_string,
  321. from->as_string,
  322. port_mapping_used->external_socket_->my_addr().as_string);
  323. if (nat_->refresh_on_ingress_) {
  324. port_mapping_used->last_used_ = PR_IntervalNow();
  325. }
  326. }
  327. }
  328. } else {
  329. // If no external socket has data, see if there's any data that was sent
  330. // directly to the TestNrSocket, and eat it if it isn't supposed to get
  331. // through.
  332. r = internal_socket_->recvfrom(buf, maxlen, len, flags, from);
  333. if (!r) {
  334. // We do not use allow_ingress() here because that only handles traffic
  335. // landing on an external port.
  336. ingress_allowed = (!nat_->enabled_ ||
  337. nat_->is_an_internal_tuple(*from));
  338. if (!ingress_allowed) {
  339. r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
  340. "Not behind the same NAT",
  341. internal_socket_->my_addr().as_string,
  342. from->as_string);
  343. } else {
  344. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s received from %s",
  345. internal_socket_->my_addr().as_string,
  346. from->as_string);
  347. }
  348. }
  349. }
  350. // Kinda lame that we are forced to give the app a readable callback and then
  351. // say "Oh, never mind...", but the alternative is to totally decouple the
  352. // callbacks from STS and the callbacks the app sets. On the bright side, this
  353. // speeds up unit tests where we are verifying that ingress is forbidden,
  354. // since they'll get a readable callback and then an error, instead of having
  355. // to wait for a timeout.
  356. if (!ingress_allowed) {
  357. *len = 0;
  358. r = R_WOULDBLOCK;
  359. }
  360. return r;
  361. }
  362. bool TestNrSocket::allow_ingress(const nr_transport_addr &from,
  363. PortMapping **port_mapping_used) const {
  364. // This is only called for traffic arriving at a port mapping
  365. MOZ_ASSERT(nat_->enabled_);
  366. MOZ_ASSERT(!nat_->is_an_internal_tuple(from));
  367. *port_mapping_used = get_port_mapping(from, nat_->filtering_type_);
  368. if (!(*port_mapping_used)) {
  369. r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
  370. "Filtered",
  371. internal_socket_->my_addr().as_string,
  372. from.as_string);
  373. return false;
  374. }
  375. if (is_port_mapping_stale(**port_mapping_used)) {
  376. r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
  377. "Stale port mapping",
  378. internal_socket_->my_addr().as_string,
  379. from.as_string);
  380. return false;
  381. }
  382. if (!nat_->allow_hairpinning_ && nat_->is_my_external_tuple(from)) {
  383. r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s denying ingress from %s: "
  384. "Hairpinning disallowed",
  385. internal_socket_->my_addr().as_string,
  386. from.as_string);
  387. return false;
  388. }
  389. return true;
  390. }
  391. int TestNrSocket::connect(nr_transport_addr *addr) {
  392. if (connect_invoked_ || !port_mappings_.empty()) {
  393. MOZ_CRASH("TestNrSocket::connect() called more than once!");
  394. return R_INTERNAL;
  395. }
  396. if (!nat_->enabled_
  397. || addr->protocol==IPPROTO_UDP // Horrible hack to allow default address
  398. // discovery to work. Only works because
  399. // we don't normally connect on UDP.
  400. || nat_->is_an_internal_tuple(*addr)) {
  401. // This will set connect_invoked_
  402. return internal_socket_->connect(addr);
  403. }
  404. RefPtr<NrSocketBase> external_socket(create_external_socket(*addr));
  405. if (!external_socket) {
  406. return R_INTERNAL;
  407. }
  408. PortMapping *port_mapping = create_port_mapping(*addr, external_socket);
  409. port_mappings_.push_back(port_mapping);
  410. int r = port_mapping->external_socket_->connect(addr);
  411. if (r && r != R_WOULDBLOCK) {
  412. return r;
  413. }
  414. port_mapping->last_used_ = PR_IntervalNow();
  415. if (poll_flags() & PR_POLL_READ) {
  416. port_mapping->async_wait(NR_ASYNC_WAIT_READ,
  417. port_mapping_tcp_passthrough_callback,
  418. this,
  419. (char*)__FUNCTION__,
  420. __LINE__);
  421. }
  422. return r;
  423. }
  424. int TestNrSocket::write(const void *msg, size_t len, size_t *written) {
  425. if (port_mappings_.empty()) {
  426. // The no-nat case, just pass call through.
  427. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s writing",
  428. my_addr().as_string);
  429. return internal_socket_->write(msg, len, written);
  430. } else {
  431. destroy_stale_port_mappings();
  432. if (port_mappings_.empty()) {
  433. return -1;
  434. }
  435. // This is TCP only
  436. MOZ_ASSERT(port_mappings_.size() == 1);
  437. r_log(LOG_GENERIC, LOG_DEBUG,
  438. "PortMapping %s -> %s writing",
  439. port_mappings_.front()->external_socket_->my_addr().as_string,
  440. port_mappings_.front()->remote_address_.as_string);
  441. port_mappings_.front()->last_used_ = PR_IntervalNow();
  442. return port_mappings_.front()->external_socket_->write(msg, len, written);
  443. }
  444. }
  445. int TestNrSocket::read(void *buf, size_t maxlen, size_t *len) {
  446. if (port_mappings_.empty()) {
  447. return internal_socket_->read(buf, maxlen, len);
  448. } else {
  449. MOZ_ASSERT(port_mappings_.size() == 1);
  450. int bytesRead =
  451. port_mappings_.front()->external_socket_->read(buf, maxlen, len);
  452. if (bytesRead > 0 && nat_->refresh_on_ingress_) {
  453. port_mappings_.front()->last_used_ = PR_IntervalNow();
  454. }
  455. return bytesRead;
  456. }
  457. }
  458. int TestNrSocket::async_wait(int how, NR_async_cb cb, void *cb_arg,
  459. char *function, int line) {
  460. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s waiting for %s",
  461. internal_socket_->my_addr().as_string,
  462. how == NR_ASYNC_WAIT_READ ? "read" : "write");
  463. int r;
  464. if (how == NR_ASYNC_WAIT_READ) {
  465. NrSocketBase::async_wait(how, cb, cb_arg, function, line);
  466. // Make sure we're waiting on the socket for the internal address
  467. r = internal_socket_->async_wait(how,
  468. socket_readable_callback,
  469. this,
  470. function,
  471. line);
  472. } else {
  473. // For write, just use the readiness of the internal socket, since we queue
  474. // everything for the port mappings.
  475. r = internal_socket_->async_wait(how,
  476. cb,
  477. cb_arg,
  478. function,
  479. line);
  480. }
  481. if (r) {
  482. r_log(LOG_GENERIC, LOG_ERR, "TestNrSocket %s failed to async_wait for "
  483. "internal socket: %d\n",
  484. internal_socket_->my_addr().as_string,
  485. r);
  486. return r;
  487. }
  488. if (is_tcp_connection_behind_nat()) {
  489. // Bypass all port-mapping related logic
  490. return 0;
  491. }
  492. if (internal_socket_->my_addr().protocol == IPPROTO_TCP) {
  493. // For a TCP connection through a simulated NAT, these signals are
  494. // just passed through.
  495. MOZ_ASSERT(port_mappings_.size() == 1);
  496. return port_mappings_.front()->async_wait(
  497. how,
  498. port_mapping_tcp_passthrough_callback,
  499. this,
  500. function,
  501. line);
  502. } else if (how == NR_ASYNC_WAIT_READ) {
  503. // For UDP port mappings, we decouple the writeable callbacks
  504. for (PortMapping *port_mapping : port_mappings_) {
  505. // Be ready to receive traffic on our port mappings
  506. r = port_mapping->async_wait(how,
  507. socket_readable_callback,
  508. this,
  509. function,
  510. line);
  511. if (r) {
  512. r_log(LOG_GENERIC, LOG_ERR, "TestNrSocket %s failed to async_wait for "
  513. "port mapping: %d\n",
  514. internal_socket_->my_addr().as_string,
  515. r);
  516. return r;
  517. }
  518. }
  519. }
  520. return 0;
  521. }
  522. void TestNrSocket::cancel_port_mapping_async_wait(int how) {
  523. for (PortMapping *port_mapping : port_mappings_) {
  524. port_mapping->cancel(how);
  525. }
  526. }
  527. int TestNrSocket::cancel(int how) {
  528. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s stop waiting for %s",
  529. internal_socket_->my_addr().as_string,
  530. how == NR_ASYNC_WAIT_READ ? "read" : "write");
  531. // Writable callbacks are decoupled except for the TCP case
  532. if (how == NR_ASYNC_WAIT_READ ||
  533. internal_socket_->my_addr().protocol == IPPROTO_TCP) {
  534. cancel_port_mapping_async_wait(how);
  535. }
  536. return internal_socket_->cancel(how);
  537. }
  538. bool TestNrSocket::has_port_mappings() const {
  539. return !port_mappings_.empty();
  540. }
  541. bool TestNrSocket::is_my_external_tuple(const nr_transport_addr &addr) const {
  542. for (PortMapping *port_mapping : port_mappings_) {
  543. nr_transport_addr port_mapping_addr;
  544. if (port_mapping->external_socket_->getaddr(&port_mapping_addr)) {
  545. MOZ_CRASH("NrSocket::getaddr failed!");
  546. }
  547. // TODO(bug 1170299): Remove const_cast when no longer necessary
  548. if (!nr_transport_addr_cmp(const_cast<nr_transport_addr*>(&addr),
  549. &port_mapping_addr,
  550. NR_TRANSPORT_ADDR_CMP_MODE_ALL)) {
  551. return true;
  552. }
  553. }
  554. return false;
  555. }
  556. bool TestNrSocket::is_port_mapping_stale(
  557. const PortMapping &port_mapping) const {
  558. PRIntervalTime now = PR_IntervalNow();
  559. PRIntervalTime elapsed_ticks = now - port_mapping.last_used_;
  560. uint32_t idle_duration = PR_IntervalToMilliseconds(elapsed_ticks);
  561. return idle_duration > nat_->mapping_timeout_;
  562. }
  563. void TestNrSocket::destroy_stale_port_mappings() {
  564. for (auto i = port_mappings_.begin(); i != port_mappings_.end();) {
  565. auto temp = i;
  566. ++i;
  567. if (is_port_mapping_stale(**temp)) {
  568. r_log(LOG_GENERIC, LOG_INFO,
  569. "TestNrSocket %s destroying port mapping %s -> %s",
  570. internal_socket_->my_addr().as_string,
  571. (*temp)->external_socket_->my_addr().as_string,
  572. (*temp)->remote_address_.as_string);
  573. port_mappings_.erase(temp);
  574. }
  575. }
  576. }
  577. void TestNrSocket::socket_readable_callback(void *real_sock_v,
  578. int how,
  579. void *test_sock_v) {
  580. TestNrSocket *test_socket = static_cast<TestNrSocket*>(test_sock_v);
  581. NrSocketBase *real_socket = static_cast<NrSocketBase*>(real_sock_v);
  582. test_socket->on_socket_readable(real_socket);
  583. }
  584. void TestNrSocket::on_socket_readable(NrSocketBase *real_socket) {
  585. if (!readable_socket_ && (real_socket != internal_socket_)) {
  586. readable_socket_ = real_socket;
  587. }
  588. fire_readable_callback();
  589. }
  590. void TestNrSocket::fire_readable_callback() {
  591. MOZ_ASSERT(poll_flags() & PR_POLL_READ);
  592. r_log(LOG_GENERIC, LOG_DEBUG, "TestNrSocket %s ready for read",
  593. internal_socket_->my_addr().as_string);
  594. fire_callback(NR_ASYNC_WAIT_READ);
  595. }
  596. void TestNrSocket::port_mapping_writeable_callback(void *ext_sock_v,
  597. int how,
  598. void *test_sock_v) {
  599. TestNrSocket *test_socket = static_cast<TestNrSocket*>(test_sock_v);
  600. NrSocketBase *external_socket = static_cast<NrSocketBase*>(ext_sock_v);
  601. test_socket->write_to_port_mapping(external_socket);
  602. }
  603. void TestNrSocket::write_to_port_mapping(NrSocketBase *external_socket) {
  604. MOZ_ASSERT(internal_socket_->my_addr().protocol != IPPROTO_TCP);
  605. int r = 0;
  606. for (PortMapping *port_mapping : port_mappings_) {
  607. if (port_mapping->external_socket_ == external_socket) {
  608. // If the send succeeds, or if there was nothing to send, we keep going
  609. r = port_mapping->send_from_queue();
  610. if (r) {
  611. break;
  612. }
  613. }
  614. }
  615. if (r == R_WOULDBLOCK) {
  616. // Re-register for writeable callbacks, since we still have stuff to send
  617. NR_ASYNC_WAIT(external_socket,
  618. NR_ASYNC_WAIT_WRITE,
  619. &TestNrSocket::port_mapping_writeable_callback,
  620. this);
  621. }
  622. }
  623. void TestNrSocket::port_mapping_tcp_passthrough_callback(void *ext_sock_v,
  624. int how,
  625. void *test_sock_v) {
  626. TestNrSocket *test_socket = static_cast<TestNrSocket*>(test_sock_v);
  627. r_log(LOG_GENERIC, LOG_DEBUG,
  628. "TestNrSocket %s firing %s callback",
  629. test_socket->internal_socket_->my_addr().as_string,
  630. how == NR_ASYNC_WAIT_READ ? "readable" : "writeable");
  631. test_socket->internal_socket_->fire_callback(how);
  632. }
  633. bool TestNrSocket::is_tcp_connection_behind_nat() const {
  634. return internal_socket_->my_addr().protocol == IPPROTO_TCP &&
  635. port_mappings_.empty();
  636. }
  637. TestNrSocket::PortMapping* TestNrSocket::get_port_mapping(
  638. const nr_transport_addr &remote_address,
  639. TestNat::NatBehavior filter) const {
  640. int compare_flags;
  641. switch (filter) {
  642. case TestNat::ENDPOINT_INDEPENDENT:
  643. compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_PROTOCOL;
  644. break;
  645. case TestNat::ADDRESS_DEPENDENT:
  646. compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_ADDR;
  647. break;
  648. case TestNat::PORT_DEPENDENT:
  649. compare_flags = NR_TRANSPORT_ADDR_CMP_MODE_ALL;
  650. break;
  651. }
  652. for (PortMapping *port_mapping : port_mappings_) {
  653. // TODO(bug 1170299): Remove const_cast when no longer necessary
  654. if (!nr_transport_addr_cmp(const_cast<nr_transport_addr*>(&remote_address),
  655. &port_mapping->remote_address_,
  656. compare_flags))
  657. return port_mapping;
  658. }
  659. return nullptr;
  660. }
  661. TestNrSocket::PortMapping* TestNrSocket::create_port_mapping(
  662. const nr_transport_addr &remote_address,
  663. const RefPtr<NrSocketBase> &external_socket) const {
  664. r_log(LOG_GENERIC, LOG_INFO, "TestNrSocket %s creating port mapping %s -> %s",
  665. internal_socket_->my_addr().as_string,
  666. external_socket->my_addr().as_string,
  667. remote_address.as_string);
  668. return new PortMapping(remote_address, external_socket);
  669. }
  670. TestNrSocket::PortMapping::PortMapping(
  671. const nr_transport_addr &remote_address,
  672. const RefPtr<NrSocketBase> &external_socket) :
  673. external_socket_(external_socket) {
  674. // TODO(bug 1170299): Remove const_cast when no longer necessary
  675. nr_transport_addr_copy(&remote_address_,
  676. const_cast<nr_transport_addr*>(&remote_address));
  677. }
  678. int TestNrSocket::PortMapping::send_from_queue() {
  679. MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP);
  680. int r = 0;
  681. while (!send_queue_.empty()) {
  682. UdpPacket &packet = *send_queue_.front();
  683. r_log(LOG_GENERIC, LOG_DEBUG,
  684. "PortMapping %s -> %s sending from queue to %s",
  685. external_socket_->my_addr().as_string,
  686. remote_address_.as_string,
  687. packet.remote_address_.as_string);
  688. r = external_socket_->sendto(packet.buffer_->data(),
  689. packet.buffer_->len(),
  690. 0,
  691. &packet.remote_address_);
  692. if (r) {
  693. if (r != R_WOULDBLOCK) {
  694. r_log(LOG_GENERIC, LOG_ERR, "%s: Fatal error %d, stop trying",
  695. __FUNCTION__, r);
  696. send_queue_.clear();
  697. } else {
  698. r_log(LOG_GENERIC, LOG_DEBUG, "Would block, will retry later");
  699. }
  700. break;
  701. }
  702. send_queue_.pop_front();
  703. }
  704. return r;
  705. }
  706. int TestNrSocket::PortMapping::sendto(const void *msg,
  707. size_t len,
  708. const nr_transport_addr &to) {
  709. MOZ_ASSERT(remote_address_.protocol != IPPROTO_TCP);
  710. r_log(LOG_GENERIC, LOG_DEBUG,
  711. "PortMapping %s -> %s sending to %s",
  712. external_socket_->my_addr().as_string,
  713. remote_address_.as_string,
  714. to.as_string);
  715. last_used_ = PR_IntervalNow();
  716. int r = external_socket_->sendto(msg, len, 0,
  717. // TODO(bug 1170299): Remove const_cast when no longer necessary
  718. const_cast<nr_transport_addr*>(&to));
  719. if (r == R_WOULDBLOCK) {
  720. r_log(LOG_GENERIC, LOG_DEBUG, "Enqueueing UDP packet to %s", to.as_string);
  721. send_queue_.push_back(RefPtr<UdpPacket>(new UdpPacket(msg, len, to)));
  722. return 0;
  723. } else if (r) {
  724. r_log(LOG_GENERIC,LOG_ERR, "Error: %d", r);
  725. }
  726. return r;
  727. }
  728. int TestNrSocket::PortMapping::async_wait(int how, NR_async_cb cb, void *cb_arg,
  729. char *function, int line) {
  730. r_log(LOG_GENERIC, LOG_DEBUG,
  731. "PortMapping %s -> %s waiting for %s",
  732. external_socket_->my_addr().as_string,
  733. remote_address_.as_string,
  734. how == NR_ASYNC_WAIT_READ ? "read" : "write");
  735. return external_socket_->async_wait(how, cb, cb_arg, function, line);
  736. }
  737. int TestNrSocket::PortMapping::cancel(int how) {
  738. r_log(LOG_GENERIC, LOG_DEBUG,
  739. "PortMapping %s -> %s stop waiting for %s",
  740. external_socket_->my_addr().as_string,
  741. remote_address_.as_string,
  742. how == NR_ASYNC_WAIT_READ ? "read" : "write");
  743. return external_socket_->cancel(how);
  744. }
  745. } // namespace mozilla