1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/nricectx.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,317 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +// Original author: ekr@rtfm.com 1.11 + 1.12 +// Some of this code is cut-and-pasted from nICEr. Copyright is: 1.13 + 1.14 +/* 1.15 +Copyright (c) 2007, Adobe Systems, Incorporated 1.16 +All rights reserved. 1.17 + 1.18 +Redistribution and use in source and binary forms, with or without 1.19 +modification, are permitted provided that the following conditions are 1.20 +met: 1.21 + 1.22 +* Redistributions of source code must retain the above copyright 1.23 + notice, this list of conditions and the following disclaimer. 1.24 + 1.25 +* Redistributions in binary form must reproduce the above copyright 1.26 + notice, this list of conditions and the following disclaimer in the 1.27 + documentation and/or other materials provided with the distribution. 1.28 + 1.29 +* Neither the name of Adobe Systems, Network Resonance nor the names of its 1.30 + contributors may be used to endorse or promote products derived from 1.31 + this software without specific prior written permission. 1.32 + 1.33 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.34 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.35 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.36 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.37 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.38 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.39 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.40 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.41 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.42 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.43 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.44 +*/ 1.45 + 1.46 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.47 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.48 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.49 + 1.50 +// Original author: ekr@rtfm.com 1.51 + 1.52 +// This is a wrapper around the nICEr ICE stack 1.53 +#ifndef nricectx_h__ 1.54 +#define nricectx_h__ 1.55 + 1.56 +#include <vector> 1.57 + 1.58 +#include "sigslot.h" 1.59 + 1.60 +#include "prnetdb.h" 1.61 + 1.62 +#include "mozilla/RefPtr.h" 1.63 +#include "mozilla/Scoped.h" 1.64 +#include "nsAutoPtr.h" 1.65 +#include "nsIEventTarget.h" 1.66 +#include "nsITimer.h" 1.67 + 1.68 +#include "m_cpp_utils.h" 1.69 + 1.70 +typedef struct nr_ice_ctx_ nr_ice_ctx; 1.71 +typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx; 1.72 +typedef struct nr_ice_media_stream_ nr_ice_media_stream; 1.73 +typedef struct nr_ice_handler_ nr_ice_handler; 1.74 +typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl; 1.75 +typedef struct nr_ice_candidate_ nr_ice_candidate; 1.76 +typedef struct nr_ice_cand_pair_ nr_ice_cand_pair; 1.77 +typedef struct nr_ice_stun_server_ nr_ice_stun_server; 1.78 +typedef struct nr_ice_turn_server_ nr_ice_turn_server; 1.79 +typedef struct nr_resolver_ nr_resolver; 1.80 + 1.81 +typedef void* NR_SOCKET; 1.82 + 1.83 +namespace mozilla { 1.84 + 1.85 +class NrIceMediaStream; 1.86 + 1.87 +extern const char kNrIceTransportUdp[]; 1.88 +extern const char kNrIceTransportTcp[]; 1.89 + 1.90 +class NrIceStunServer { 1.91 + public: 1.92 + NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) { 1.93 + memcpy(&addr_, &addr, sizeof(addr)); 1.94 + } 1.95 + 1.96 + // The main function to use. Will take either an address or a hostname. 1.97 + static NrIceStunServer* Create(const std::string& addr, uint16_t port) { 1.98 + ScopedDeletePtr<NrIceStunServer> server( 1.99 + new NrIceStunServer()); 1.100 + 1.101 + nsresult rv = server->Init(addr, port); 1.102 + if (NS_FAILED(rv)) 1.103 + return nullptr; 1.104 + 1.105 + return server.forget(); 1.106 + } 1.107 + 1.108 + nsresult ToNicerStunStruct(nr_ice_stun_server* server, 1.109 + const std::string& transport = 1.110 + kNrIceTransportUdp) const; 1.111 + 1.112 + protected: 1.113 + NrIceStunServer() : addr_() {} 1.114 + 1.115 + nsresult Init(const std::string& addr, uint16_t port) { 1.116 + PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_); 1.117 + if (status == PR_SUCCESS) { 1.118 + // Parseable as an address 1.119 + addr_.inet.port = PR_htons(port); 1.120 + port_ = port; 1.121 + has_addr_ = true; 1.122 + return NS_OK; 1.123 + } 1.124 + else if (addr.size() < 256) { 1.125 + // Apparently this is a hostname. 1.126 + host_ = addr; 1.127 + port_ = port; 1.128 + has_addr_ = false; 1.129 + return NS_OK; 1.130 + } 1.131 + 1.132 + return NS_ERROR_FAILURE; 1.133 + } 1.134 + 1.135 + bool has_addr_; 1.136 + std::string host_; 1.137 + uint16_t port_; 1.138 + PRNetAddr addr_; 1.139 +}; 1.140 + 1.141 +class NrIceTurnServer : public NrIceStunServer { 1.142 + public: 1.143 + static NrIceTurnServer *Create(const std::string& addr, uint16_t port, 1.144 + const std::string& username, 1.145 + const std::vector<unsigned char>& password, 1.146 + const char *transport = kNrIceTransportUdp) { 1.147 + ScopedDeletePtr<NrIceTurnServer> server( 1.148 + new NrIceTurnServer(username, password, transport)); 1.149 + 1.150 + nsresult rv = server->Init(addr, port); 1.151 + if (NS_FAILED(rv)) 1.152 + return nullptr; 1.153 + 1.154 + return server.forget(); 1.155 + } 1.156 + 1.157 + nsresult ToNicerTurnStruct(nr_ice_turn_server *server) const; 1.158 + 1.159 + private: 1.160 + NrIceTurnServer(const std::string& username, 1.161 + const std::vector<unsigned char>& password, 1.162 + const char *transport) : 1.163 + username_(username), password_(password), transport_(transport) {} 1.164 + 1.165 + std::string username_; 1.166 + std::vector<unsigned char> password_; 1.167 + std::string transport_; 1.168 +}; 1.169 + 1.170 +class NrIceCtx { 1.171 + public: 1.172 + enum ConnectionState { ICE_CTX_INIT, 1.173 + ICE_CTX_CHECKING, 1.174 + ICE_CTX_OPEN, 1.175 + ICE_CTX_FAILED 1.176 + }; 1.177 + 1.178 + enum GatheringState { ICE_CTX_GATHER_INIT, 1.179 + ICE_CTX_GATHER_STARTED, 1.180 + ICE_CTX_GATHER_COMPLETE 1.181 + }; 1.182 + 1.183 + enum Controlling { ICE_CONTROLLING, 1.184 + ICE_CONTROLLED 1.185 + }; 1.186 + 1.187 + static RefPtr<NrIceCtx> Create(const std::string& name, 1.188 + bool offerer, 1.189 + bool set_interface_priorities = true); 1.190 + virtual ~NrIceCtx(); 1.191 + 1.192 + nr_ice_ctx *ctx() { return ctx_; } 1.193 + nr_ice_peer_ctx *peer() { return peer_; } 1.194 + 1.195 + // Testing only. 1.196 + void destroy_peer_ctx(); 1.197 + 1.198 + // Create a media stream 1.199 + RefPtr<NrIceMediaStream> CreateStream(const std::string& name, 1.200 + int components); 1.201 + 1.202 + // The name of the ctx 1.203 + const std::string& name() const { return name_; } 1.204 + 1.205 + // Current state 1.206 + ConnectionState connection_state() const { 1.207 + return connection_state_; 1.208 + } 1.209 + 1.210 + // Current state 1.211 + GatheringState gathering_state() const { 1.212 + return gathering_state_; 1.213 + } 1.214 + 1.215 + // Get the global attributes 1.216 + std::vector<std::string> GetGlobalAttributes(); 1.217 + 1.218 + // Set the other side's global attributes 1.219 + nsresult ParseGlobalAttributes(std::vector<std::string> attrs); 1.220 + 1.221 + // Set whether we are controlling or not. 1.222 + nsresult SetControlling(Controlling controlling); 1.223 + 1.224 + // Set the STUN servers. Must be called before StartGathering 1.225 + // (if at all). 1.226 + nsresult SetStunServers(const std::vector<NrIceStunServer>& stun_servers); 1.227 + 1.228 + // Set the TURN servers. Must be called before StartGathering 1.229 + // (if at all). 1.230 + nsresult SetTurnServers(const std::vector<NrIceTurnServer>& turn_servers); 1.231 + 1.232 + // Provide the resolution provider. Must be called before 1.233 + // StartGathering. 1.234 + nsresult SetResolver(nr_resolver *resolver); 1.235 + 1.236 + // Start ICE gathering 1.237 + nsresult StartGathering(); 1.238 + 1.239 + // Start checking 1.240 + nsresult StartChecks(); 1.241 + 1.242 + // Finalize the ICE negotiation. I.e., there will be no 1.243 + // more forking. 1.244 + nsresult Finalize(); 1.245 + 1.246 + // Are we trickling? 1.247 + bool generating_trickle() const { return trickle_; } 1.248 + 1.249 + // Signals to indicate events. API users can (and should) 1.250 + // register for these. 1.251 + sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState> 1.252 + SignalGatheringStateChange; 1.253 + sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState> 1.254 + SignalConnectionStateChange; 1.255 + 1.256 + // The thread to direct method calls to 1.257 + nsCOMPtr<nsIEventTarget> thread() { return sts_target_; } 1.258 + 1.259 + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx) 1.260 + 1.261 + private: 1.262 + NrIceCtx(const std::string& name, 1.263 + bool offerer) 1.264 + : connection_state_(ICE_CTX_INIT), 1.265 + gathering_state_(ICE_CTX_GATHER_INIT), 1.266 + name_(name), 1.267 + offerer_(offerer), 1.268 + streams_(), 1.269 + ctx_(nullptr), 1.270 + peer_(nullptr), 1.271 + ice_handler_vtbl_(nullptr), 1.272 + ice_handler_(nullptr), 1.273 + trickle_(true) { 1.274 + // XXX: offerer_ will be used eventually; placate clang in the meantime. 1.275 + (void)offerer_; 1.276 + } 1.277 + 1.278 + DISALLOW_COPY_ASSIGN(NrIceCtx); 1.279 + 1.280 + // Callbacks for nICEr 1.281 + static void initialized_cb(NR_SOCKET s, int h, void *arg); // ICE initialized 1.282 + 1.283 + // Handler implementation 1.284 + static int select_pair(void *obj,nr_ice_media_stream *stream, 1.285 + int component_id, nr_ice_cand_pair **potentials, 1.286 + int potential_ct); 1.287 + static int stream_ready(void *obj, nr_ice_media_stream *stream); 1.288 + static int stream_failed(void *obj, nr_ice_media_stream *stream); 1.289 + static int ice_completed(void *obj, nr_ice_peer_ctx *pctx); 1.290 + static int msg_recvd(void *obj, nr_ice_peer_ctx *pctx, 1.291 + nr_ice_media_stream *stream, int component_id, 1.292 + unsigned char *msg, int len); 1.293 + static void trickle_cb(void *arg, nr_ice_ctx *ctx, nr_ice_media_stream *stream, 1.294 + int component_id, nr_ice_candidate *candidate); 1.295 + 1.296 + // Find a media stream by stream ptr. Gross 1.297 + RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream); 1.298 + 1.299 + // Set the state 1.300 + void SetConnectionState(ConnectionState state); 1.301 + 1.302 + // Set the state 1.303 + void SetGatheringState(GatheringState state); 1.304 + 1.305 + ConnectionState connection_state_; 1.306 + GatheringState gathering_state_; 1.307 + const std::string name_; 1.308 + bool offerer_; 1.309 + std::vector<RefPtr<NrIceMediaStream> > streams_; 1.310 + nr_ice_ctx *ctx_; 1.311 + nr_ice_peer_ctx *peer_; 1.312 + nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer 1.313 + nr_ice_handler* ice_handler_; // Must be pointer 1.314 + bool trickle_; 1.315 + nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on 1.316 +}; 1.317 + 1.318 + 1.319 +} // close namespace 1.320 +#endif