tor-browser

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

nr_socket_prsock.h (11038B)


      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 /* Some source code here from nICEr. Copyright is:
     10 
     11 Copyright (c) 2007, Adobe Systems, Incorporated
     12 All rights reserved.
     13 
     14 Redistribution and use in source and binary forms, with or without
     15 modification, are permitted provided that the following conditions are
     16 met:
     17 
     18 * Redistributions of source code must retain the above copyright
     19  notice, this list of conditions and the following disclaimer.
     20 
     21 * Redistributions in binary form must reproduce the above copyright
     22  notice, this list of conditions and the following disclaimer in the
     23  documentation and/or other materials provided with the distribution.
     24 
     25 * Neither the name of Adobe Systems, Network Resonance nor the names of its
     26  contributors may be used to endorse or promote products derived from
     27  this software without specific prior written permission.
     28 
     29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     32 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     33 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     34 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     35 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     36 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     37 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     38 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     39 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     40 */
     41 
     42 // Implementation of nICEr/nr_socket that is tied to the Gecko
     43 // SocketTransportService.
     44 
     45 #ifndef nr_socket_prsock__
     46 #define nr_socket_prsock__
     47 
     48 #include <memory>
     49 #include <queue>
     50 
     51 #include "m_cpp_utils.h"
     52 #include "mediapacket.h"
     53 #include "mozilla/ClearOnShutdown.h"
     54 #include "mozilla/ReentrantMonitor.h"
     55 #include "mozilla/RefPtr.h"
     56 #include "mozilla/TimeStamp.h"
     57 #include "nsASocketHandler.h"
     58 #include "nsCOMPtr.h"
     59 #include "nsIEventTarget.h"
     60 #include "nsIUDPSocketChild.h"
     61 #include "nsProxyRelease.h"
     62 #include "nsThreadUtils.h"
     63 #include "nsXPCOM.h"
     64 #include "nspr.h"
     65 #include "prio.h"
     66 
     67 // nICEr includes
     68 extern "C" {
     69 #include "async_wait.h"
     70 #include "transport_addr.h"
     71 }
     72 
     73 // Stub declaration for nICEr type
     74 typedef struct nr_socket_vtbl_ nr_socket_vtbl;
     75 typedef struct nr_socket_ nr_socket;
     76 
     77 #if defined(MOZILLA_INTERNAL_API)
     78 namespace mozilla {
     79 class NrSocketProxyConfig;
     80 }  // namespace mozilla
     81 #endif
     82 
     83 namespace mozilla {
     84 
     85 namespace net {
     86 union NetAddr;
     87 }
     88 
     89 namespace dom {
     90 class UDPSocketChild;
     91 }  // namespace dom
     92 
     93 class NrSocketBase {
     94 public:
     95  NrSocketBase() : connect_invoked_(false), poll_flags_(0) {
     96    memset(cbs_, 0, sizeof(cbs_));
     97    memset(cb_args_, 0, sizeof(cb_args_));
     98    memset(&my_addr_, 0, sizeof(my_addr_));
     99  }
    100  virtual ~NrSocketBase() = default;
    101 
    102  // Factory method; will create either an NrSocket, NrUdpSocketIpc, or
    103  // NrTcpSocketIpc as appropriate.
    104  static int CreateSocket(nr_transport_addr* addr, RefPtr<NrSocketBase>* sock,
    105                          const std::shared_ptr<NrSocketProxyConfig>& config);
    106  static bool IsForbiddenAddress(nr_transport_addr* addr);
    107 
    108  // the nr_socket APIs
    109  virtual int create(nr_transport_addr* addr) = 0;
    110  virtual int sendto(const void* msg, size_t len, int flags,
    111                     const nr_transport_addr* to) = 0;
    112  virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags,
    113                       nr_transport_addr* from) = 0;
    114  virtual int getaddr(nr_transport_addr* addrp) = 0;
    115  virtual void close() = 0;
    116  virtual int connect(const nr_transport_addr* addr) = 0;
    117  virtual int write(const void* msg, size_t len, size_t* written) = 0;
    118  virtual int read(void* buf, size_t maxlen, size_t* len) = 0;
    119  virtual int listen(int backlog) = 0;
    120  virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) = 0;
    121 
    122  // Implementations of the async_event APIs
    123  virtual int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function,
    124                         int line);
    125  virtual int cancel(int how);
    126 
    127  // nsISupport reference counted interface
    128  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
    129 
    130  uint32_t poll_flags() { return poll_flags_; }
    131 
    132  virtual nr_socket_vtbl* vtbl();  // To access in test classes.
    133 
    134  static TimeStamp short_term_violation_time();
    135  static TimeStamp long_term_violation_time();
    136  const nr_transport_addr& my_addr() const { return my_addr_; }
    137 
    138  void fire_callback(int how);
    139 
    140 protected:
    141  bool connect_invoked_;
    142  nr_transport_addr my_addr_;
    143 
    144 private:
    145  NR_async_cb cbs_[NR_ASYNC_WAIT_WRITE + 1];
    146  void* cb_args_[NR_ASYNC_WAIT_WRITE + 1];
    147  uint32_t poll_flags_;
    148 };
    149 
    150 class NrSocket : public NrSocketBase, public nsASocketHandler {
    151 public:
    152  NrSocket() : fd_(nullptr) {}
    153 
    154  // Implement nsASocket
    155  virtual void OnSocketReady(PRFileDesc* fd, int16_t outflags) override;
    156  virtual void OnSocketDetached(PRFileDesc* fd) override;
    157  virtual void IsLocal(bool* aIsLocal) override;
    158  virtual uint64_t ByteCountSent() override { return 0; }
    159  virtual uint64_t ByteCountReceived() override { return 0; }
    160 
    161  // nsISupports methods
    162  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
    163  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY(NrSocket, Destroy(),
    164                                                     override);
    165  virtual void Destroy() { delete this; }
    166 
    167  // Implementations of the async_event APIs
    168  virtual int async_wait(int how, NR_async_cb cb, void* cb_arg, char* function,
    169                         int line) override;
    170  virtual int cancel(int how) override;
    171 
    172  // Implementations of the nr_socket APIs
    173  virtual int create(nr_transport_addr* addr)
    174      override;  // (really init, but it's called create)
    175  virtual int sendto(const void* msg, size_t len, int flags,
    176                     const nr_transport_addr* to) override;
    177  virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags,
    178                       nr_transport_addr* from) override;
    179  virtual int getaddr(nr_transport_addr* addrp) override;
    180  virtual void close() override;
    181  virtual int connect(const nr_transport_addr* addr) override;
    182  virtual int write(const void* msg, size_t len, size_t* written) override;
    183  virtual int read(void* buf, size_t maxlen, size_t* len) override;
    184  virtual int listen(int backlog) override;
    185  virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) override;
    186 
    187 protected:
    188  virtual ~NrSocket() {
    189    if (fd_) PR_Close(fd_);
    190  }
    191 
    192  DISALLOW_COPY_ASSIGN(NrSocket);
    193 
    194  PRFileDesc* fd_;
    195  nsCOMPtr<nsIEventTarget> ststhread_;
    196 };
    197 
    198 struct nr_udp_message {
    199  nr_udp_message(const PRNetAddr& from, UniquePtr<MediaPacket>&& data)
    200      : from(from), data(std::move(data)) {}
    201 
    202  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_udp_message);
    203 
    204  PRNetAddr from;
    205  UniquePtr<MediaPacket> data;
    206 
    207 private:
    208  ~nr_udp_message() = default;
    209  DISALLOW_COPY_ASSIGN(nr_udp_message);
    210 };
    211 
    212 class NrSocketIpc : public NrSocketBase {
    213 public:
    214  enum NrSocketIpcState {
    215    NR_INIT,
    216    NR_CONNECTING,
    217    NR_CONNECTED,
    218    NR_CLOSING,
    219    NR_CLOSED,
    220  };
    221 
    222  NrSocketIpc(nsIEventTarget* aThread);
    223 
    224 protected:
    225  nsCOMPtr<nsIEventTarget> sts_thread_;
    226  // Note: for UDP PBackground, this is a thread held by SingletonThreadHolder.
    227  // For TCP PNecko, this is MainThread (and TCPSocket requires MainThread
    228  // currently)
    229  const nsCOMPtr<nsIEventTarget> io_thread_;
    230  virtual ~NrSocketIpc() = default;
    231 
    232 private:
    233  DISALLOW_COPY_ASSIGN(NrSocketIpc);
    234 };
    235 
    236 class NrUdpSocketIpc : public NrSocketIpc {
    237 public:
    238  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override)
    239 
    240  NS_IMETHODIMP CallListenerError(const nsACString& message,
    241                                  const nsACString& filename,
    242                                  uint32_t line_number);
    243  NS_IMETHODIMP CallListenerReceivedData(const nsACString& host, uint16_t port,
    244                                         const nsTArray<uint8_t>& data);
    245  NS_IMETHODIMP CallListenerOpened();
    246  NS_IMETHODIMP CallListenerConnected();
    247  NS_IMETHODIMP CallListenerClosed();
    248 
    249  NrUdpSocketIpc();
    250 
    251  // Implementations of the NrSocketBase APIs
    252  virtual int create(nr_transport_addr* addr) override;
    253  virtual int sendto(const void* msg, size_t len, int flags,
    254                     const nr_transport_addr* to) override;
    255  virtual int recvfrom(void* buf, size_t maxlen, size_t* len, int flags,
    256                       nr_transport_addr* from) override;
    257  virtual int getaddr(nr_transport_addr* addrp) override;
    258  virtual void close() override;
    259  virtual int connect(const nr_transport_addr* addr) override;
    260  virtual int write(const void* msg, size_t len, size_t* written) override;
    261  virtual int read(void* buf, size_t maxlen, size_t* len) override;
    262  virtual int listen(int backlog) override;
    263  virtual int accept(nr_transport_addr* addrp, nr_socket** sockp) override;
    264 
    265 private:
    266  virtual ~NrUdpSocketIpc();
    267  virtual void Destroy();
    268 
    269  DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
    270 
    271  nsresult SetAddress()
    272      MOZ_REQUIRES(monitor_);  // Set the local address from parent info.
    273 
    274  // Main or private thread executors of the NrSocketBase APIs
    275  void create_i(const nsACString& host, const uint16_t port);
    276  void connect_i(const nsACString& host, const uint16_t port);
    277  void sendto_i(const net::NetAddr& addr, UniquePtr<MediaPacket> buf);
    278  void close_i();
    279 #if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
    280  void destroy_i();
    281 #endif
    282  // STS thread executor
    283  void recv_callback_s(RefPtr<nr_udp_message> msg);
    284 
    285  ReentrantMonitor monitor_ MOZ_UNANNOTATED;  // protects err_and state_
    286  bool err_;
    287  NrSocketIpcState state_;
    288 
    289  std::queue<RefPtr<nr_udp_message>> received_msgs_;
    290 
    291  // only accessed from the io_thread
    292  RefPtr<dom::UDPSocketChild> socket_child_;
    293 };
    294 
    295 // The socket child holds onto one of these, which just passes callbacks
    296 // through and makes sure the ref to the NrSocketIpc is released on STS.
    297 class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
    298 public:
    299  NS_DECL_THREADSAFE_ISUPPORTS
    300  NS_DECL_NSIUDPSOCKETINTERNAL
    301 
    302  nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
    303 
    304 private:
    305  virtual ~NrUdpSocketIpcProxy();
    306 
    307  RefPtr<NrUdpSocketIpc> socket_;
    308  nsCOMPtr<nsIEventTarget> sts_thread_;
    309 };
    310 
    311 int nr_netaddr_to_transport_addr(const net::NetAddr* netaddr,
    312                                 nr_transport_addr* addr, int protocol);
    313 int nr_praddr_to_transport_addr(const PRNetAddr* praddr,
    314                                nr_transport_addr* addr, int protocol,
    315                                int keep);
    316 int nr_transport_addr_get_addrstring_and_port(const nr_transport_addr* addr,
    317                                              nsACString* host, int32_t* port);
    318 }  // namespace mozilla
    319 #endif