tor-browser

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

nricectx.h (13256B)


      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 of this code is cut-and-pasted from nICEr. Copyright is:
     10 
     11 /*
     12 Copyright (c) 2007, Adobe Systems, Incorporated
     13 All rights reserved.
     14 
     15 Redistribution and use in source and binary forms, with or without
     16 modification, are permitted provided that the following conditions are
     17 met:
     18 
     19 * Redistributions of source code must retain the above copyright
     20  notice, this list of conditions and the following disclaimer.
     21 
     22 * Redistributions in binary form must reproduce the above copyright
     23  notice, this list of conditions and the following disclaimer in the
     24  documentation and/or other materials provided with the distribution.
     25 
     26 * Neither the name of Adobe Systems, Network Resonance nor the names of its
     27  contributors may be used to endorse or promote products derived from
     28  this software without specific prior written permission.
     29 
     30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     33 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     34 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     35 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     36 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     37 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     38 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     39 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     40 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     41 */
     42 
     43 /* This Source Code Form is subject to the terms of the Mozilla Public
     44 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     45 * You can obtain one at http://mozilla.org/MPL/2.0/. */
     46 
     47 // Original author: ekr@rtfm.com
     48 
     49 // This is a wrapper around the nICEr ICE stack
     50 #ifndef nricectx_h__
     51 #define nricectx_h__
     52 
     53 #include <map>
     54 #include <memory>
     55 #include <string>
     56 #include <vector>
     57 
     58 #include "m_cpp_utils.h"
     59 #include "mozilla/Maybe.h"
     60 #include "mozilla/RefPtr.h"
     61 #include "mozilla/UniquePtr.h"
     62 #include "nricemediastream.h"
     63 #include "nricestunaddr.h"
     64 #include "nsIEventTarget.h"
     65 #include "nsTArray.h"
     66 #include "prnetdb.h"
     67 #include "sigslot.h"
     68 
     69 typedef struct nr_ice_ctx_ nr_ice_ctx;
     70 typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
     71 typedef struct nr_ice_media_stream_ nr_ice_media_stream;
     72 typedef struct nr_ice_handler_ nr_ice_handler;
     73 typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl;
     74 typedef struct nr_ice_gather_handler_ nr_ice_gather_handler;
     75 typedef struct nr_ice_gather_handler_vtbl_ nr_ice_gather_handler_vtbl;
     76 typedef struct nr_ice_candidate_ nr_ice_candidate;
     77 typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
     78 typedef struct nr_ice_stun_server_ nr_ice_stun_server;
     79 typedef struct nr_ice_turn_server_ nr_ice_turn_server;
     80 typedef struct nr_resolver_ nr_resolver;
     81 typedef struct nr_proxy_tunnel_config_ nr_proxy_tunnel_config;
     82 
     83 typedef void* NR_SOCKET;
     84 
     85 namespace mozilla {
     86 
     87 class NrSocketProxyConfig;
     88 
     89 class NrIceMediaStream;
     90 
     91 extern const char kNrIceTransportUdp[];
     92 extern const char kNrIceTransportTcp[];
     93 extern const char kNrIceTransportTls[];
     94 
     95 class NrIceStunServer {
     96 public:
     97  explicit NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) {
     98    memcpy(&addr_, &addr, sizeof(addr));
     99  }
    100 
    101  // The main function to use. Will take either an address or a hostname.
    102  static UniquePtr<NrIceStunServer> Create(
    103      const std::string& addr, uint16_t port,
    104      const char* transport = kNrIceTransportUdp) {
    105    UniquePtr<NrIceStunServer> server(new NrIceStunServer(transport));
    106 
    107    nsresult rv = server->Init(addr, port);
    108    if (NS_FAILED(rv)) return nullptr;
    109 
    110    return server;
    111  }
    112 
    113  nsresult ToNicerStunStruct(nr_ice_stun_server* server) const;
    114 
    115  bool HasFqdn() const { return !has_addr_; }
    116 
    117  void SetUseIPv6IfFqdn() {
    118    MOZ_ASSERT(HasFqdn());
    119    use_ipv6_if_fqdn_ = true;
    120  }
    121 
    122 protected:
    123  explicit NrIceStunServer(const char* transport)
    124      : addr_(), transport_(transport) {}
    125 
    126  nsresult Init(const std::string& addr, uint16_t port) {
    127    PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_);
    128    if (status == PR_SUCCESS) {
    129      // Parseable as an address
    130      addr_.inet.port = PR_htons(port);
    131      port_ = port;
    132      has_addr_ = true;
    133      return NS_OK;
    134    } else if (addr.size() < 256) {
    135      // Apparently this is a hostname.
    136      host_ = addr;
    137      port_ = port;
    138      has_addr_ = false;
    139      return NS_OK;
    140    }
    141 
    142    return NS_ERROR_FAILURE;
    143  }
    144 
    145  bool has_addr_;
    146  std::string host_;
    147  uint16_t port_;
    148  PRNetAddr addr_;
    149  std::string transport_;
    150  bool use_ipv6_if_fqdn_ = false;
    151 };
    152 
    153 class NrIceTurnServer : public NrIceStunServer {
    154 public:
    155  static UniquePtr<NrIceTurnServer> Create(
    156      const std::string& addr, uint16_t port, const std::string& username,
    157      const std::vector<unsigned char>& password,
    158      const char* transport = kNrIceTransportUdp) {
    159    UniquePtr<NrIceTurnServer> server(
    160        new NrIceTurnServer(username, password, transport));
    161 
    162    nsresult rv = server->Init(addr, port);
    163    if (NS_FAILED(rv)) return nullptr;
    164 
    165    return server;
    166  }
    167 
    168  nsresult ToNicerTurnStruct(nr_ice_turn_server* server) const;
    169 
    170 private:
    171  NrIceTurnServer(const std::string& username,
    172                  const std::vector<unsigned char>& password,
    173                  const char* transport)
    174      : NrIceStunServer(transport), username_(username), password_(password) {}
    175 
    176  std::string username_;
    177  std::vector<unsigned char> password_;
    178 };
    179 
    180 class TestNat;
    181 
    182 class NrIceStats {
    183 public:
    184  uint16_t stun_retransmits = 0;
    185  uint16_t turn_401s = 0;
    186  uint16_t turn_403s = 0;
    187  uint16_t turn_438s = 0;
    188 };
    189 
    190 class NrIceCtx {
    191 public:
    192  enum ConnectionState {
    193    ICE_CTX_INIT,
    194    ICE_CTX_CHECKING,
    195    ICE_CTX_CONNECTED,
    196    ICE_CTX_COMPLETED,
    197    ICE_CTX_FAILED,
    198    ICE_CTX_DISCONNECTED,
    199    ICE_CTX_CLOSED
    200  };
    201 
    202  enum Controlling { ICE_CONTROLLING, ICE_CONTROLLED };
    203 
    204  enum Policy { ICE_POLICY_RELAY, ICE_POLICY_NO_HOST, ICE_POLICY_ALL };
    205 
    206  struct NatSimulatorConfig {
    207    bool mBlockTcp = false;
    208    bool mBlockUdp = false;
    209    bool mBlockTls = false;
    210    int mErrorCodeForDrop = 0;
    211    nsCString mMappingType = "ENDPOINT_INDEPENDENT"_ns;
    212    nsCString mFilteringType = "ENDPOINT_INDEPENDENT"_ns;
    213    nsCString mRedirectAddress;
    214    CopyableTArray<nsCString> mRedirectTargets;
    215    unsigned int mNetworkDelayMs = 0;
    216  };
    217 
    218  struct Config {
    219    NrIceCtx::Policy mPolicy = NrIceCtx::ICE_POLICY_ALL;
    220    bool mAllowLinkLocal = false;
    221    bool mAllowLoopback = false;
    222    Maybe<NatSimulatorConfig> mNatSimulatorConfig;
    223  };
    224 
    225  static RefPtr<NrIceCtx> Create(const std::string& aName);
    226 
    227  nsresult SetIceConfig(const Config& aConfig);
    228 
    229  RefPtr<NrIceMediaStream> CreateStream(const std::string& id,
    230                                        const std::string& name,
    231                                        int components);
    232  void DestroyStream(const std::string& id);
    233 
    234  struct GlobalConfig {
    235    bool mTcpEnabled = true;
    236    int mStunClientMaxTransmits = 7;
    237    int mTrickleIceGracePeriod = 5000;
    238    int mIceTcpSoSockCount = 3;
    239    int mIceTcpListenBacklog = 10;
    240    nsCString mForceNetInterface;
    241  };
    242 
    243  // initialize ICE globals, crypto, and logging
    244  static void InitializeGlobals(const GlobalConfig& aConfig);
    245 
    246  void SetTargetForDefaultLocalAddressLookup(const std::string& target_ip,
    247                                             uint16_t target_port);
    248 
    249  // static GetStunAddrs for use in parent process to support
    250  // sandboxing restrictions
    251  static nsTArray<NrIceStunAddr> GetStunAddrs();
    252  void SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs);
    253 
    254  bool Initialize();
    255 
    256  int SetNat(const RefPtr<TestNat>& aNat);
    257 
    258  // Deinitialize all ICE global state. Used only for testing.
    259  static void internal_DeinitializeGlobal();
    260 
    261  // Divide some timers to faster testing. Used only for testing.
    262  void internal_SetTimerAccelarator(int divider);
    263 
    264  nr_ice_ctx* ctx() { return ctx_; }
    265  nr_ice_peer_ctx* peer() { return peer_; }
    266 
    267  // Testing only.
    268  void destroy_peer_ctx();
    269 
    270  RefPtr<NrIceMediaStream> GetStream(const std::string& id) {
    271    auto it = streams_.find(id);
    272    if (it != streams_.end()) {
    273      return it->second;
    274    }
    275    return nullptr;
    276  }
    277 
    278  std::vector<RefPtr<NrIceMediaStream>> GetStreams() const {
    279    std::vector<RefPtr<NrIceMediaStream>> result;
    280    for (auto& idAndStream : streams_) {
    281      result.push_back(idAndStream.second);
    282    }
    283    return result;
    284  }
    285 
    286  bool HasStreamsToConnect() const;
    287 
    288  // The name of the ctx
    289  const std::string& name() const { return name_; }
    290 
    291  // Get the global attributes
    292  std::vector<std::string> GetGlobalAttributes();
    293 
    294  // Set the other side's global attributes
    295  nsresult ParseGlobalAttributes(std::vector<std::string> attrs);
    296 
    297  // Set whether we are controlling or not.
    298  nsresult SetControlling(Controlling controlling);
    299 
    300  Controlling GetControlling();
    301 
    302  // Set the STUN servers. Must be called before StartGathering
    303  // (if at all).
    304  nsresult SetStunServers(const std::vector<NrIceStunServer>& stun_servers);
    305 
    306  // Set the TURN servers. Must be called before StartGathering
    307  // (if at all).
    308  nsresult SetTurnServers(const std::vector<NrIceTurnServer>& turn_servers);
    309 
    310  // Provide the resolution provider. Must be called before
    311  // StartGathering.
    312  nsresult SetResolver(nr_resolver* resolver);
    313 
    314  // Provide the proxy address. Must be called before
    315  // StartGathering.
    316  nsresult SetProxyConfig(NrSocketProxyConfig&& config);
    317 
    318  const std::shared_ptr<NrSocketProxyConfig>& GetProxyConfig() {
    319    return proxy_config_;
    320  }
    321 
    322  void SetCtxFlags(bool default_route_only);
    323 
    324  // Start ICE gathering
    325  nsresult StartGathering(bool default_route_only,
    326                          bool obfuscate_host_addresses);
    327 
    328  // Start checking
    329  nsresult StartChecks();
    330 
    331  // Notify that the network has gone online/offline
    332  void UpdateNetworkState(bool online);
    333 
    334  void AccumulateStats(const NrIceStats& stats);
    335  NrIceStats Destroy();
    336 
    337  // Are we trickling?
    338  bool generating_trickle() const { return trickle_; }
    339 
    340  // Signals to indicate events. API users can (and should)
    341  // register for these.
    342  sigslot::signal2<NrIceMediaStream*, NrIceCtx::ConnectionState>
    343      SignalConnectionStateChange;
    344 
    345  // The thread to direct method calls to
    346  nsCOMPtr<nsIEventTarget> thread() { return sts_target_; }
    347 
    348  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx)
    349 
    350 private:
    351  explicit NrIceCtx(const std::string& name);
    352 
    353  virtual ~NrIceCtx();
    354 
    355  DISALLOW_COPY_ASSIGN(NrIceCtx);
    356 
    357  // Callbacks for nICEr
    358  static void gather_cb(NR_SOCKET s, int h, void* arg);  // ICE gather complete
    359 
    360  // Handler implementation
    361  static int select_pair(void* obj, nr_ice_media_stream* stream,
    362                         int component_id, nr_ice_cand_pair** potentials,
    363                         int potential_ct);
    364  static int stream_gathering(void* obj, nr_ice_media_stream* stream);
    365  static int stream_gathered(void* obj, nr_ice_media_stream* stream);
    366  static int stream_checking(void* obj, nr_ice_media_stream* stream);
    367  static int stream_ready(void* obj, nr_ice_media_stream* stream);
    368  static int stream_disconnected(void* obj, nr_ice_media_stream* stream);
    369  static int stream_failed(void* obj, nr_ice_media_stream* stream);
    370  static int ice_checking(void* obj, nr_ice_peer_ctx* pctx);
    371  static int ice_connected(void* obj, nr_ice_peer_ctx* pctx);
    372  static int ice_disconnected(void* obj, nr_ice_peer_ctx* pctx);
    373  static int msg_recvd(void* obj, nr_ice_peer_ctx* pctx,
    374                       nr_ice_media_stream* stream, int component_id,
    375                       unsigned char* msg, int len);
    376  static void trickle_cb(void* arg, nr_ice_ctx* ctx,
    377                         nr_ice_media_stream* stream, int component_id,
    378                         nr_ice_candidate* candidate);
    379 
    380  void SignalAllStreamsFailed();
    381 
    382  // Find a media stream by stream ptr. Gross
    383  RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream* stream);
    384 
    385  void GenerateObfuscatedAddress(nr_ice_candidate* candidate,
    386                                 std::string* mdns_address,
    387                                 std::string* actual_address);
    388 
    389  bool dumped_rlog_ = false;
    390  const std::string name_;
    391  bool ice_controlling_set_;
    392  std::map<std::string, RefPtr<NrIceMediaStream>> streams_;
    393  nr_ice_ctx* ctx_;
    394  nr_ice_peer_ctx* peer_;
    395  nr_ice_handler_vtbl* ice_handler_vtbl_;                // Must be pointer
    396  nr_ice_handler* ice_handler_;                          // Must be pointer
    397  nr_ice_gather_handler_vtbl* ice_gather_handler_vtbl_;  // Must be pointer
    398  nr_ice_gather_handler* ice_gather_handler_;            // Must be pointer
    399  bool trickle_;
    400  nsCOMPtr<nsIEventTarget> sts_target_;  // The thread to run on
    401  Config config_;
    402  RefPtr<TestNat> nat_;
    403  std::shared_ptr<NrSocketProxyConfig> proxy_config_;
    404  std::map<std::string, std::string> obfuscated_host_addresses_;
    405 };
    406 
    407 }  // namespace mozilla
    408 #endif