summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/transport/nricectx.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/webrtc/transport/nricectx.h421
1 files changed, 421 insertions, 0 deletions
diff --git a/dom/media/webrtc/transport/nricectx.h b/dom/media/webrtc/transport/nricectx.h
new file mode 100644
index 0000000000..a0a0b5b772
--- /dev/null
+++ b/dom/media/webrtc/transport/nricectx.h
@@ -0,0 +1,421 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Original author: ekr@rtfm.com
+
+// Some of this code is cut-and-pasted from nICEr. Copyright is:
+
+/*
+Copyright (c) 2007, Adobe Systems, Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems, Network Resonance nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Original author: ekr@rtfm.com
+
+// This is a wrapper around the nICEr ICE stack
+#ifndef nricectx_h__
+#define nricectx_h__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <map>
+
+#include "sigslot.h"
+
+#include "prnetdb.h"
+
+#include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "nsIEventTarget.h"
+#include "nsTArray.h"
+#include "mozilla/Maybe.h"
+
+#include "m_cpp_utils.h"
+#include "nricestunaddr.h"
+#include "nricemediastream.h"
+
+typedef struct nr_ice_ctx_ nr_ice_ctx;
+typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
+typedef struct nr_ice_media_stream_ nr_ice_media_stream;
+typedef struct nr_ice_handler_ nr_ice_handler;
+typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl;
+typedef struct nr_ice_candidate_ nr_ice_candidate;
+typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
+typedef struct nr_ice_stun_server_ nr_ice_stun_server;
+typedef struct nr_ice_turn_server_ nr_ice_turn_server;
+typedef struct nr_resolver_ nr_resolver;
+typedef struct nr_proxy_tunnel_config_ nr_proxy_tunnel_config;
+
+typedef void* NR_SOCKET;
+
+namespace mozilla {
+
+class NrSocketProxyConfig;
+
+class NrIceMediaStream;
+
+extern const char kNrIceTransportUdp[];
+extern const char kNrIceTransportTcp[];
+extern const char kNrIceTransportTls[];
+
+class NrIceStunServer {
+ public:
+ explicit NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) {
+ memcpy(&addr_, &addr, sizeof(addr));
+ }
+
+ // The main function to use. Will take either an address or a hostname.
+ static UniquePtr<NrIceStunServer> Create(
+ const std::string& addr, uint16_t port,
+ const char* transport = kNrIceTransportUdp) {
+ UniquePtr<NrIceStunServer> server(new NrIceStunServer(transport));
+
+ nsresult rv = server->Init(addr, port);
+ if (NS_FAILED(rv)) return nullptr;
+
+ return server;
+ }
+
+ nsresult ToNicerStunStruct(nr_ice_stun_server* server) const;
+
+ bool HasFqdn() const { return !has_addr_; }
+
+ void SetUseIPv6IfFqdn() {
+ MOZ_ASSERT(HasFqdn());
+ use_ipv6_if_fqdn_ = true;
+ }
+
+ protected:
+ explicit NrIceStunServer(const char* transport)
+ : addr_(), transport_(transport) {}
+
+ nsresult Init(const std::string& addr, uint16_t port) {
+ PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_);
+ if (status == PR_SUCCESS) {
+ // Parseable as an address
+ addr_.inet.port = PR_htons(port);
+ port_ = port;
+ has_addr_ = true;
+ return NS_OK;
+ } else if (addr.size() < 256) {
+ // Apparently this is a hostname.
+ host_ = addr;
+ port_ = port;
+ has_addr_ = false;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+ }
+
+ bool has_addr_;
+ std::string host_;
+ uint16_t port_;
+ PRNetAddr addr_;
+ std::string transport_;
+ bool use_ipv6_if_fqdn_ = false;
+};
+
+class NrIceTurnServer : public NrIceStunServer {
+ public:
+ static UniquePtr<NrIceTurnServer> Create(
+ const std::string& addr, uint16_t port, const std::string& username,
+ const std::vector<unsigned char>& password,
+ const char* transport = kNrIceTransportUdp) {
+ UniquePtr<NrIceTurnServer> server(
+ new NrIceTurnServer(username, password, transport));
+
+ nsresult rv = server->Init(addr, port);
+ if (NS_FAILED(rv)) return nullptr;
+
+ return server;
+ }
+
+ nsresult ToNicerTurnStruct(nr_ice_turn_server* server) const;
+
+ private:
+ NrIceTurnServer(const std::string& username,
+ const std::vector<unsigned char>& password,
+ const char* transport)
+ : NrIceStunServer(transport), username_(username), password_(password) {}
+
+ std::string username_;
+ std::vector<unsigned char> password_;
+};
+
+class TestNat;
+
+class NrIceStats {
+ public:
+ uint16_t stun_retransmits = 0;
+ uint16_t turn_401s = 0;
+ uint16_t turn_403s = 0;
+ uint16_t turn_438s = 0;
+};
+
+class NrIceCtx {
+ public:
+ enum ConnectionState {
+ ICE_CTX_INIT,
+ ICE_CTX_CHECKING,
+ ICE_CTX_CONNECTED,
+ ICE_CTX_COMPLETED,
+ ICE_CTX_FAILED,
+ ICE_CTX_DISCONNECTED,
+ ICE_CTX_CLOSED
+ };
+
+ enum GatheringState {
+ ICE_CTX_GATHER_INIT,
+ ICE_CTX_GATHER_STARTED,
+ ICE_CTX_GATHER_COMPLETE
+ };
+
+ enum Controlling { ICE_CONTROLLING, ICE_CONTROLLED };
+
+ enum Policy { ICE_POLICY_RELAY, ICE_POLICY_NO_HOST, ICE_POLICY_ALL };
+
+ struct NatSimulatorConfig {
+ bool mBlockTcp = false;
+ bool mBlockUdp = false;
+ bool mBlockTls = false;
+ int mErrorCodeForDrop = 0;
+ nsCString mMappingType = "ENDPOINT_INDEPENDENT"_ns;
+ nsCString mFilteringType = "ENDPOINT_INDEPENDENT"_ns;
+ nsCString mRedirectAddress;
+ CopyableTArray<nsCString> mRedirectTargets;
+ };
+
+ struct Config {
+ NrIceCtx::Policy mPolicy = NrIceCtx::ICE_POLICY_ALL;
+ Maybe<NatSimulatorConfig> mNatSimulatorConfig;
+ };
+
+ static RefPtr<NrIceCtx> Create(const std::string& aName);
+
+ nsresult SetIceConfig(const Config& aConfig);
+
+ RefPtr<NrIceMediaStream> CreateStream(const std::string& id,
+ const std::string& name,
+ int components);
+ void DestroyStream(const std::string& id);
+
+ struct GlobalConfig {
+ bool mAllowLinkLocal = false;
+ bool mAllowLoopback = false;
+ bool mTcpEnabled = true;
+ int mStunClientMaxTransmits = 7;
+ int mTrickleIceGracePeriod = 5000;
+ int mIceTcpSoSockCount = 3;
+ int mIceTcpListenBacklog = 10;
+ nsCString mForceNetInterface;
+ };
+
+ // initialize ICE globals, crypto, and logging
+ static void InitializeGlobals(const GlobalConfig& aConfig);
+
+ void SetTargetForDefaultLocalAddressLookup(const std::string& target_ip,
+ uint16_t target_port);
+
+ // static GetStunAddrs for use in parent process to support
+ // sandboxing restrictions
+ static nsTArray<NrIceStunAddr> GetStunAddrs();
+ void SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs);
+
+ bool Initialize();
+
+ int SetNat(const RefPtr<TestNat>& aNat);
+
+ // Deinitialize all ICE global state. Used only for testing.
+ static void internal_DeinitializeGlobal();
+
+ // Divide some timers to faster testing. Used only for testing.
+ void internal_SetTimerAccelarator(int divider);
+
+ nr_ice_ctx* ctx() { return ctx_; }
+ nr_ice_peer_ctx* peer() { return peer_; }
+
+ // Testing only.
+ void destroy_peer_ctx();
+
+ RefPtr<NrIceMediaStream> GetStream(const std::string& id) {
+ auto it = streams_.find(id);
+ if (it != streams_.end()) {
+ return it->second;
+ }
+ return nullptr;
+ }
+
+ std::vector<RefPtr<NrIceMediaStream>> GetStreams() const {
+ std::vector<RefPtr<NrIceMediaStream>> result;
+ for (auto& idAndStream : streams_) {
+ result.push_back(idAndStream.second);
+ }
+ return result;
+ }
+
+ bool HasStreamsToConnect() const;
+
+ // The name of the ctx
+ const std::string& name() const { return name_; }
+
+ // Current state
+ ConnectionState connection_state() const { return connection_state_; }
+
+ // Current state
+ GatheringState gathering_state() const { return gathering_state_; }
+
+ // Get the global attributes
+ std::vector<std::string> GetGlobalAttributes();
+
+ // Set the other side's global attributes
+ nsresult ParseGlobalAttributes(std::vector<std::string> attrs);
+
+ // Set whether we are controlling or not.
+ nsresult SetControlling(Controlling controlling);
+
+ Controlling GetControlling();
+
+ // Set the STUN servers. Must be called before StartGathering
+ // (if at all).
+ nsresult SetStunServers(const std::vector<NrIceStunServer>& stun_servers);
+
+ // Set the TURN servers. Must be called before StartGathering
+ // (if at all).
+ nsresult SetTurnServers(const std::vector<NrIceTurnServer>& turn_servers);
+
+ // Provide the resolution provider. Must be called before
+ // StartGathering.
+ nsresult SetResolver(nr_resolver* resolver);
+
+ // Provide the proxy address. Must be called before
+ // StartGathering.
+ nsresult SetProxyConfig(NrSocketProxyConfig&& config);
+
+ const std::shared_ptr<NrSocketProxyConfig>& GetProxyConfig() {
+ return proxy_config_;
+ }
+
+ void SetCtxFlags(bool default_route_only);
+
+ // Start ICE gathering
+ nsresult StartGathering(bool default_route_only,
+ bool obfuscate_host_addresses);
+
+ // Start checking
+ nsresult StartChecks();
+
+ // Notify that the network has gone online/offline
+ void UpdateNetworkState(bool online);
+
+ void AccumulateStats(const NrIceStats& stats);
+ NrIceStats Destroy();
+
+ // Are we trickling?
+ bool generating_trickle() const { return trickle_; }
+
+ // Signals to indicate events. API users can (and should)
+ // register for these.
+ sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
+ SignalGatheringStateChange;
+ sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
+ SignalConnectionStateChange;
+
+ // The thread to direct method calls to
+ nsCOMPtr<nsIEventTarget> thread() { return sts_target_; }
+
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx)
+
+ private:
+ explicit NrIceCtx(const std::string& name);
+
+ virtual ~NrIceCtx();
+
+ DISALLOW_COPY_ASSIGN(NrIceCtx);
+
+ // Callbacks for nICEr
+ static void gather_cb(NR_SOCKET s, int h, void* arg); // ICE gather complete
+
+ // Handler implementation
+ static int select_pair(void* obj, nr_ice_media_stream* stream,
+ int component_id, nr_ice_cand_pair** potentials,
+ int potential_ct);
+ static int stream_ready(void* obj, nr_ice_media_stream* stream);
+ static int stream_failed(void* obj, nr_ice_media_stream* stream);
+ static int ice_checking(void* obj, nr_ice_peer_ctx* pctx);
+ static int ice_connected(void* obj, nr_ice_peer_ctx* pctx);
+ static int ice_disconnected(void* obj, nr_ice_peer_ctx* pctx);
+ static int msg_recvd(void* obj, nr_ice_peer_ctx* pctx,
+ nr_ice_media_stream* stream, int component_id,
+ unsigned char* msg, int len);
+ static void trickle_cb(void* arg, nr_ice_ctx* ctx,
+ nr_ice_media_stream* stream, int component_id,
+ nr_ice_candidate* candidate);
+
+ // Find a media stream by stream ptr. Gross
+ RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream* stream);
+
+ // Set the state
+ void SetConnectionState(ConnectionState state);
+
+ // Set the state
+ void SetGatheringState(GatheringState state);
+
+ void GenerateObfuscatedAddress(nr_ice_candidate* candidate,
+ std::string* mdns_address,
+ std::string* actual_address);
+
+ ConnectionState connection_state_;
+ GatheringState gathering_state_;
+ const std::string name_;
+ bool ice_controlling_set_;
+ std::map<std::string, RefPtr<NrIceMediaStream>> streams_;
+ nr_ice_ctx* ctx_;
+ nr_ice_peer_ctx* peer_;
+ nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
+ nr_ice_handler* ice_handler_; // Must be pointer
+ bool trickle_;
+ nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
+ Config config_;
+ RefPtr<TestNat> nat_;
+ std::shared_ptr<NrSocketProxyConfig> proxy_config_;
+ std::map<std::string, std::string> obfuscated_host_addresses_;
+};
+
+} // namespace mozilla
+#endif