tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

stunserver.cpp (19692B)


      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 // Original author: ekr@rtfm.com
      8 
      9 /*
     10 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 #include "logging.h"
     81 #include "mediapacket.h"
     82 #include "mozilla/UniquePtr.h"
     83 
     84 // mozilla/utils.h defines this as well
     85 #ifdef UNIMPLEMENTED
     86 #  undef UNIMPLEMENTED
     87 #endif
     88 
     89 extern "C" {
     90 // clang-format off
     91 #include "nr_api.h"
     92 #include "async_wait.h"
     93 #include "async_timer.h"
     94 #include "nr_socket.h"
     95 #include "nr_socket_local.h"
     96 #include "transport_addr.h"
     97 #include "stun_util.h"
     98 #include "registry.h"
     99 #include "nr_socket_buffered_stun.h"
    100 #include "addrs.h"
    101 // clang-format on
    102 }
    103 
    104 #include <string>
    105 
    106 #include "stunserver.h"
    107 
    108 MOZ_MTLOG_MODULE("stunserver");
    109 
    110 namespace mozilla {
    111 
    112 // Wrapper nr_socket which allows us to lie to the stun server about the
    113 // IP address.
    114 struct nr_socket_wrapped {
    115  nr_socket* sock_;
    116  nr_transport_addr addr_;
    117 };
    118 
    119 static int nr_socket_wrapped_destroy(void** objp) {
    120  if (!objp || !*objp) return 0;
    121 
    122  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(*objp);
    123  *objp = nullptr;
    124 
    125  delete wrapped;
    126 
    127  return 0;
    128 }
    129 
    130 static int nr_socket_wrapped_sendto(void* obj, const void* msg, size_t len,
    131                                    int flags, const nr_transport_addr* addr) {
    132  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(obj);
    133 
    134  return nr_socket_sendto(wrapped->sock_, msg, len, flags, &wrapped->addr_);
    135 }
    136 
    137 static int nr_socket_wrapped_recvfrom(void* obj, void* restrict buf,
    138                                      size_t maxlen, size_t* len, int flags,
    139                                      nr_transport_addr* addr) {
    140  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(obj);
    141 
    142  return nr_socket_recvfrom(wrapped->sock_, buf, maxlen, len, flags, addr);
    143 }
    144 
    145 static int nr_socket_wrapped_getfd(void* obj, NR_SOCKET* fd) {
    146  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(obj);
    147 
    148  return nr_socket_getfd(wrapped->sock_, fd);
    149 }
    150 
    151 static int nr_socket_wrapped_getaddr(void* obj, nr_transport_addr* addrp) {
    152  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(obj);
    153 
    154  return nr_socket_getaddr(wrapped->sock_, addrp);
    155 }
    156 
    157 static int nr_socket_wrapped_close(void* obj) { MOZ_CRASH(); }
    158 
    159 static int nr_socket_wrapped_set_send_addr(nr_socket* sock,
    160                                           nr_transport_addr* addr) {
    161  nr_socket_wrapped* wrapped = static_cast<nr_socket_wrapped*>(sock->obj);
    162 
    163  return nr_transport_addr_copy(&wrapped->addr_, addr);
    164 }
    165 
    166 static nr_socket_vtbl nr_socket_wrapped_vtbl = {2,
    167                                                nr_socket_wrapped_destroy,
    168                                                nr_socket_wrapped_sendto,
    169                                                nr_socket_wrapped_recvfrom,
    170                                                nr_socket_wrapped_getfd,
    171                                                nr_socket_wrapped_getaddr,
    172                                                nullptr,
    173                                                nullptr,
    174                                                nullptr,
    175                                                nr_socket_wrapped_close,
    176                                                nullptr,
    177                                                nullptr};
    178 
    179 int nr_socket_wrapped_create(nr_socket* inner, nr_socket** outp) {
    180  auto wrapped = MakeUnique<nr_socket_wrapped>();
    181 
    182  wrapped->sock_ = inner;
    183 
    184  int r = nr_socket_create_int(wrapped.get(), &nr_socket_wrapped_vtbl, outp);
    185  if (r) return r;
    186 
    187  (void)wrapped.release();
    188  return 0;
    189 }
    190 
    191 // Instance static.
    192 // Note: Calling Create() at static init time is not going to be safe, since
    193 // we have no reason to expect this will be initted to a nullptr yet.
    194 TestStunServer* TestStunServer::instance;
    195 TestStunTcpServer* TestStunTcpServer::instance;
    196 TestStunServer* TestStunServer::instance6;
    197 TestStunTcpServer* TestStunTcpServer::instance6;
    198 uint16_t TestStunServer::instance_port = 3478;
    199 uint16_t TestStunTcpServer::instance_port = 3478;
    200 
    201 TestStunServer::~TestStunServer() {
    202  // TODO(ekr@rtfm.com): Put this on the right thread.
    203 
    204  // Unhook callback from our listen socket.
    205  if (listen_sock_) {
    206    NR_SOCKET fd;
    207    if (!nr_socket_getfd(listen_sock_, &fd)) {
    208      NR_ASYNC_CANCEL(fd, NR_ASYNC_WAIT_READ);
    209    }
    210  }
    211 
    212  // Free up stun context and network resources
    213  nr_stun_server_ctx_destroy(&stun_server_);
    214  nr_socket_destroy(&listen_sock_);
    215  nr_socket_destroy(&send_sock_);
    216 
    217  // Make sure we aren't still waiting on a deferred response timer to pop
    218  if (timer_handle_) NR_async_timer_cancel(timer_handle_);
    219 
    220  delete response_addr_;
    221 }
    222 
    223 int TestStunServer::SetInternalPort(nr_local_addr* addr, uint16_t port) {
    224  if (nr_transport_addr_set_port(&addr->addr, port)) {
    225    MOZ_MTLOG(ML_ERROR, "Couldn't set port");
    226    return R_INTERNAL;
    227  }
    228 
    229  if (nr_transport_addr_fmt_addr_string(&addr->addr)) {
    230    MOZ_MTLOG(ML_ERROR, "Couldn't re-set addr string");
    231    return R_INTERNAL;
    232  }
    233 
    234  return 0;
    235 }
    236 
    237 int TestStunServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) {
    238  int r = SetInternalPort(addr, port);
    239 
    240  if (r) return r;
    241 
    242  if (nr_socket_local_create(nullptr, &addr->addr, &listen_sock_)) {
    243    MOZ_MTLOG(ML_ERROR, "Couldn't create listen socket");
    244    return R_ALREADY;
    245  }
    246 
    247  return 0;
    248 }
    249 
    250 static int addressFamilyToIpVersion(int address_family) {
    251  switch (address_family) {
    252    case AF_INET:
    253      return NR_IPV4;
    254    case AF_INET6:
    255      return NR_IPV6;
    256    default:
    257      MOZ_CRASH();
    258  }
    259  return NR_IPV4;
    260 }
    261 
    262 int TestStunServer::Initialize(int address_family) {
    263  static const size_t max_addrs = 100;
    264  nr_local_addr addrs[max_addrs];
    265  int addr_ct;
    266  int r;
    267  int i;
    268 
    269  r = nr_stun_get_addrs(addrs, max_addrs, &addr_ct);
    270  if (r) {
    271    MOZ_MTLOG(ML_ERROR, "Couldn't retrieve addresses");
    272    return R_INTERNAL;
    273  }
    274 
    275  // removes duplicate, loopback, and link_local addrs
    276  r = nr_stun_filter_addrs(addrs, true, true, &addr_ct);
    277  if (r) {
    278    MOZ_MTLOG(ML_ERROR, "Couldn't filter addresses");
    279    return R_INTERNAL;
    280  }
    281 
    282  if (addr_ct < 1) {
    283    MOZ_MTLOG(ML_ERROR, "No local addresses");
    284    return R_INTERNAL;
    285  }
    286 
    287  for (i = 0; i < addr_ct; ++i) {
    288    if (addrs[i].addr.ip_version == addressFamilyToIpVersion(address_family)) {
    289      break;
    290    }
    291  }
    292 
    293  if (i == addr_ct) {
    294    MOZ_MTLOG(ML_ERROR, "No local addresses of the configured IP version");
    295    return R_INTERNAL;
    296  }
    297 
    298  int tries = 100;
    299  while (tries--) {
    300    // Bind on configured port (default 3478)
    301    r = TryOpenListenSocket(&addrs[i], instance_port);
    302    // We interpret R_ALREADY to mean the addr is probably in use. Try another.
    303    // Otherwise, it either worked or it didn't, and we check below.
    304    if (r != R_ALREADY) {
    305      break;
    306    }
    307    ++instance_port;
    308  }
    309 
    310  if (r) {
    311    return R_INTERNAL;
    312  }
    313 
    314  r = nr_socket_wrapped_create(listen_sock_, &send_sock_);
    315  if (r) {
    316    MOZ_MTLOG(ML_ERROR, "Couldn't create send socket");
    317    return R_INTERNAL;
    318  }
    319 
    320  r = nr_stun_server_ctx_create(const_cast<char*>("Test STUN server"),
    321                                &stun_server_);
    322  if (r) {
    323    MOZ_MTLOG(ML_ERROR, "Couldn't create STUN server");
    324    return R_INTERNAL;
    325  }
    326 
    327  // Cache the address and port.
    328  char addr_string[INET6_ADDRSTRLEN];
    329  r = nr_transport_addr_get_addrstring(&addrs[i].addr, addr_string,
    330                                       sizeof(addr_string));
    331  if (r) {
    332    MOZ_MTLOG(ML_ERROR,
    333              "Failed to convert listen addr to a string representation");
    334    return R_INTERNAL;
    335  }
    336 
    337  listen_addr_ = addr_string;
    338  listen_port_ = instance_port;
    339 
    340  return 0;
    341 }
    342 
    343 UniquePtr<TestStunServer> TestStunServer::Create(int address_family) {
    344  NR_reg_init();
    345 
    346  UniquePtr<TestStunServer> server(new TestStunServer());
    347 
    348  if (server->Initialize(address_family)) return nullptr;
    349 
    350  NR_SOCKET fd;
    351  int r = nr_socket_getfd(server->listen_sock_, &fd);
    352  if (r) {
    353    MOZ_MTLOG(ML_ERROR, "Couldn't get fd");
    354    return nullptr;
    355  }
    356 
    357  NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, &TestStunServer::readable_cb,
    358                server.get());
    359 
    360  return server;
    361 }
    362 
    363 void TestStunServer::ConfigurePort(uint16_t port) { instance_port = port; }
    364 
    365 TestStunServer* TestStunServer::GetInstance(int address_family) {
    366  switch (address_family) {
    367    case AF_INET:
    368      if (!instance) instance = Create(address_family).release();
    369 
    370      MOZ_ASSERT(instance);
    371      return instance;
    372    case AF_INET6:
    373      if (!instance6) instance6 = Create(address_family).release();
    374 
    375      return instance6;
    376    default:
    377      MOZ_CRASH();
    378  }
    379 }
    380 
    381 void TestStunServer::ShutdownInstance() {
    382  delete instance;
    383  instance = nullptr;
    384  delete instance6;
    385  instance6 = nullptr;
    386 }
    387 
    388 struct DeferredStunOperation {
    389  DeferredStunOperation(TestStunServer* server, const char* data, size_t len,
    390                        nr_transport_addr* addr, nr_socket* sock)
    391      : server_(server), sock_(sock) {
    392    buffer_.Copy(reinterpret_cast<const uint8_t*>(data), len);
    393    nr_transport_addr_copy(&addr_, addr);
    394  }
    395 
    396  TestStunServer* server_;
    397  MediaPacket buffer_;
    398  nr_transport_addr addr_;
    399  nr_socket* sock_;
    400 };
    401 
    402 void TestStunServer::Process(const uint8_t* msg, size_t len,
    403                             nr_transport_addr* addr, nr_socket* sock) {
    404  if (!sock) {
    405    sock = send_sock_;
    406  }
    407 
    408  // Set the wrapped address so that the response goes to the right place.
    409  nr_socket_wrapped_set_send_addr(sock, addr);
    410 
    411  nr_stun_server_process_request(
    412      stun_server_, sock, const_cast<char*>(reinterpret_cast<const char*>(msg)),
    413      len, response_addr_ ? response_addr_ : addr, NR_STUN_AUTH_RULE_OPTIONAL);
    414 }
    415 
    416 void TestStunServer::process_cb(NR_SOCKET s, int how, void* cb_arg) {
    417  DeferredStunOperation* op = static_cast<DeferredStunOperation*>(cb_arg);
    418  op->server_->timer_handle_ = nullptr;
    419  op->server_->Process(op->buffer_.data(), op->buffer_.len(), &op->addr_,
    420                       op->sock_);
    421 
    422  delete op;
    423 }
    424 
    425 nr_socket* TestStunServer::GetReceivingSocket(NR_SOCKET s) {
    426  return listen_sock_;
    427 }
    428 
    429 nr_socket* TestStunServer::GetSendingSocket(nr_socket* sock) {
    430  return send_sock_;
    431 }
    432 
    433 void TestStunServer::readable_cb(NR_SOCKET s, int how, void* cb_arg) {
    434  TestStunServer* server = static_cast<TestStunServer*>(cb_arg);
    435 
    436  char message[max_stun_message_size];
    437  size_t message_len;
    438  nr_transport_addr addr;
    439  nr_socket* recv_sock = server->GetReceivingSocket(s);
    440  if (!recv_sock) {
    441    MOZ_MTLOG(ML_ERROR, "Failed to lookup receiving socket");
    442    return;
    443  }
    444  nr_socket* send_sock = server->GetSendingSocket(recv_sock);
    445 
    446  /* Re-arm. */
    447  NR_ASYNC_WAIT(s, NR_ASYNC_WAIT_READ, &TestStunServer::readable_cb, server);
    448 
    449  if (nr_socket_recvfrom(recv_sock, message, sizeof(message), &message_len, 0,
    450                         &addr)) {
    451    MOZ_MTLOG(ML_ERROR, "Couldn't read STUN message");
    452    return;
    453  }
    454 
    455  MOZ_MTLOG(ML_DEBUG, "Received data of length " << message_len);
    456 
    457  // If we have initial dropping set, check at this point.
    458  std::string key(addr.as_string);
    459 
    460  if (server->received_ct_.count(key) == 0) {
    461    server->received_ct_[key] = 0;
    462  }
    463 
    464  ++server->received_ct_[key];
    465 
    466  if (!server->active_ || (server->received_ct_[key] <= server->initial_ct_)) {
    467    MOZ_MTLOG(ML_DEBUG, "Dropping message #" << server->received_ct_[key]
    468                                             << " from " << key);
    469    return;
    470  }
    471 
    472  if (server->delay_ms_) {
    473    NR_ASYNC_TIMER_SET(server->delay_ms_, process_cb,
    474                       new DeferredStunOperation(server, message, message_len,
    475                                                 &addr, send_sock),
    476                       &server->timer_handle_);
    477  } else {
    478    server->Process(reinterpret_cast<const uint8_t*>(message), message_len,
    479                    &addr, send_sock);
    480  }
    481 }
    482 
    483 void TestStunServer::SetActive(bool active) { active_ = active; }
    484 
    485 void TestStunServer::SetDelay(uint32_t delay_ms) { delay_ms_ = delay_ms; }
    486 
    487 void TestStunServer::SetDropInitialPackets(uint32_t count) {
    488  initial_ct_ = count;
    489 }
    490 
    491 nsresult TestStunServer::SetResponseAddr(nr_transport_addr* addr) {
    492  delete response_addr_;
    493 
    494  response_addr_ = new nr_transport_addr();
    495 
    496  int r = nr_transport_addr_copy(response_addr_, addr);
    497  if (r) return NS_ERROR_FAILURE;
    498 
    499  return NS_OK;
    500 }
    501 
    502 nsresult TestStunServer::SetResponseAddr(const std::string& addr,
    503                                         uint16_t port) {
    504  nr_transport_addr addr2;
    505 
    506  int r =
    507      nr_str_port_to_transport_addr(addr.c_str(), port, IPPROTO_UDP, &addr2);
    508  if (r) return NS_ERROR_FAILURE;
    509 
    510  return SetResponseAddr(&addr2);
    511 }
    512 
    513 void TestStunServer::Reset() {
    514  delay_ms_ = 0;
    515  if (timer_handle_) {
    516    NR_async_timer_cancel(timer_handle_);
    517    timer_handle_ = nullptr;
    518  }
    519  delete response_addr_;
    520  response_addr_ = nullptr;
    521  received_ct_.clear();
    522 }
    523 
    524 // TestStunTcpServer
    525 
    526 void TestStunTcpServer::ConfigurePort(uint16_t port) { instance_port = port; }
    527 
    528 TestStunTcpServer* TestStunTcpServer::GetInstance(int address_family) {
    529  switch (address_family) {
    530    case AF_INET:
    531      if (!instance) instance = Create(address_family).release();
    532 
    533      MOZ_ASSERT(instance);
    534      return instance;
    535    case AF_INET6:
    536      if (!instance6) instance6 = Create(address_family).release();
    537 
    538      return instance6;
    539    default:
    540      MOZ_CRASH();
    541  }
    542 }
    543 
    544 void TestStunTcpServer::ShutdownInstance() {
    545  delete instance;
    546  instance = nullptr;
    547  delete instance6;
    548  instance6 = nullptr;
    549 }
    550 
    551 int TestStunTcpServer::TryOpenListenSocket(nr_local_addr* addr, uint16_t port) {
    552  addr->addr.protocol = IPPROTO_TCP;
    553 
    554  int r = SetInternalPort(addr, port);
    555 
    556  if (r) return r;
    557 
    558  nr_socket* sock;
    559  if (nr_socket_local_create(nullptr, &addr->addr, &sock)) {
    560    MOZ_MTLOG(ML_ERROR, "Couldn't create listen tcp socket");
    561    return R_ALREADY;
    562  }
    563 
    564  if (nr_socket_buffered_stun_create(sock, 2048, TURN_TCP_FRAMING,
    565                                     &listen_sock_)) {
    566    MOZ_MTLOG(ML_ERROR, "Couldn't create listen tcp socket");
    567    return R_ALREADY;
    568  }
    569 
    570  if (nr_socket_listen(listen_sock_, 10)) {
    571    MOZ_MTLOG(ML_ERROR, "Couldn't listen on socket");
    572    return R_ALREADY;
    573  }
    574 
    575  return 0;
    576 }
    577 
    578 nr_socket* TestStunTcpServer::GetReceivingSocket(NR_SOCKET s) {
    579  return connections_[s];
    580 }
    581 
    582 nr_socket* TestStunTcpServer::GetSendingSocket(nr_socket* sock) { return sock; }
    583 
    584 void TestStunTcpServer::accept_cb(NR_SOCKET s, int how, void* cb_arg) {
    585  TestStunTcpServer* server = static_cast<TestStunTcpServer*>(cb_arg);
    586  nr_socket *newsock, *bufsock, *wrapsock;
    587  nr_transport_addr remote_addr;
    588  NR_SOCKET fd;
    589 
    590  /* rearm */
    591  NR_ASYNC_WAIT(s, NR_ASYNC_WAIT_READ, &TestStunTcpServer::accept_cb, cb_arg);
    592 
    593  /* accept */
    594  if (nr_socket_accept(server->listen_sock_, &remote_addr, &newsock)) {
    595    MOZ_MTLOG(ML_ERROR, "Couldn't accept incoming tcp connection");
    596    return;
    597  }
    598 
    599  if (nr_socket_buffered_stun_create(newsock, 2048, TURN_TCP_FRAMING,
    600                                     &bufsock)) {
    601    MOZ_MTLOG(ML_ERROR, "Couldn't create connected tcp socket");
    602    nr_socket_destroy(&newsock);
    603    return;
    604  }
    605 
    606  nr_socket_buffered_set_connected_to(bufsock, &remote_addr);
    607 
    608  if (nr_socket_wrapped_create(bufsock, &wrapsock)) {
    609    MOZ_MTLOG(ML_ERROR, "Couldn't wrap connected tcp socket");
    610    nr_socket_destroy(&bufsock);
    611    return;
    612  }
    613 
    614  if (nr_socket_getfd(wrapsock, &fd)) {
    615    MOZ_MTLOG(ML_ERROR, "Couldn't get fd from connected tcp socket");
    616    nr_socket_destroy(&wrapsock);
    617    return;
    618  }
    619 
    620  server->connections_[fd] = wrapsock;
    621 
    622  NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, &TestStunServer::readable_cb, server);
    623 }
    624 
    625 UniquePtr<TestStunTcpServer> TestStunTcpServer::Create(int address_family) {
    626  NR_reg_init();
    627 
    628  UniquePtr<TestStunTcpServer> server(new TestStunTcpServer());
    629 
    630  if (server->Initialize(address_family)) {
    631    return nullptr;
    632  }
    633 
    634  NR_SOCKET fd;
    635  if (nr_socket_getfd(server->listen_sock_, &fd)) {
    636    MOZ_MTLOG(ML_ERROR, "Couldn't get tcp fd");
    637    return nullptr;
    638  }
    639 
    640  NR_ASYNC_WAIT(fd, NR_ASYNC_WAIT_READ, &TestStunTcpServer::accept_cb,
    641                server.get());
    642 
    643  return server;
    644 }
    645 
    646 TestStunTcpServer::~TestStunTcpServer() {
    647  for (auto it = connections_.begin(); it != connections_.end();) {
    648    NR_ASYNC_CANCEL(it->first, NR_ASYNC_WAIT_READ);
    649    nr_socket_destroy(&it->second);
    650    connections_.erase(it++);
    651  }
    652 }
    653 
    654 }  // namespace mozilla