Line data Source code
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 <string>
54 : #include <vector>
55 :
56 : #include "sigslot.h"
57 :
58 : #include "prnetdb.h"
59 :
60 : #include "mozilla/RefPtr.h"
61 : #include "mozilla/TimeStamp.h"
62 : #include "mozilla/UniquePtr.h"
63 : #include "nsAutoPtr.h"
64 : #include "nsIEventTarget.h"
65 : #include "nsITimer.h"
66 : #include "nsTArray.h"
67 :
68 : #include "m_cpp_utils.h"
69 : #include "nricestunaddr.h"
70 :
71 : typedef struct nr_ice_ctx_ nr_ice_ctx;
72 : typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
73 : typedef struct nr_ice_media_stream_ nr_ice_media_stream;
74 : typedef struct nr_ice_handler_ nr_ice_handler;
75 : typedef struct nr_ice_handler_vtbl_ nr_ice_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 : // Timestamps set whenever a packet is dropped due to global rate limiting
88 : // (see nr_socket_prsock.cpp)
89 : TimeStamp nr_socket_short_term_violation_time();
90 : TimeStamp nr_socket_long_term_violation_time();
91 :
92 : class NrIceMediaStream;
93 :
94 : extern const char kNrIceTransportUdp[];
95 : extern const char kNrIceTransportTcp[];
96 : extern const char kNrIceTransportTls[];
97 :
98 0 : class NrIceStunServer {
99 : public:
100 : explicit NrIceStunServer(const PRNetAddr& addr) : has_addr_(true) {
101 : memcpy(&addr_, &addr, sizeof(addr));
102 : }
103 :
104 : // The main function to use. Will take either an address or a hostname.
105 0 : static UniquePtr<NrIceStunServer> Create(const std::string& addr, uint16_t port,
106 : const char *transport = kNrIceTransportUdp) {
107 0 : UniquePtr<NrIceStunServer> server(new NrIceStunServer(transport));
108 :
109 0 : nsresult rv = server->Init(addr, port);
110 0 : if (NS_FAILED(rv))
111 0 : return nullptr;
112 :
113 0 : return server;
114 : }
115 :
116 : nsresult ToNicerStunStruct(nr_ice_stun_server* server) const;
117 :
118 : protected:
119 0 : explicit NrIceStunServer(const char *transport) :
120 0 : addr_(), transport_(transport) {}
121 :
122 0 : nsresult Init(const std::string& addr, uint16_t port) {
123 0 : PRStatus status = PR_StringToNetAddr(addr.c_str(), &addr_);
124 0 : if (status == PR_SUCCESS) {
125 : // Parseable as an address
126 0 : addr_.inet.port = PR_htons(port);
127 0 : port_ = port;
128 0 : has_addr_ = true;
129 0 : return NS_OK;
130 : }
131 0 : else if (addr.size() < 256) {
132 : // Apparently this is a hostname.
133 0 : host_ = addr;
134 0 : port_ = port;
135 0 : has_addr_ = false;
136 0 : return NS_OK;
137 : }
138 :
139 0 : return NS_ERROR_FAILURE;
140 : }
141 :
142 : bool has_addr_;
143 : std::string host_;
144 : uint16_t port_;
145 : PRNetAddr addr_;
146 : std::string transport_;
147 : };
148 :
149 0 : class NrIceTurnServer : public NrIceStunServer {
150 : public:
151 0 : static UniquePtr<NrIceTurnServer> Create(const std::string& addr, uint16_t port,
152 : const std::string& username,
153 : const std::vector<unsigned char>& password,
154 : const char *transport = kNrIceTransportUdp) {
155 0 : UniquePtr<NrIceTurnServer> server(new NrIceTurnServer(username, password, transport));
156 :
157 0 : nsresult rv = server->Init(addr, port);
158 0 : if (NS_FAILED(rv))
159 0 : return nullptr;
160 :
161 0 : return server;
162 : }
163 :
164 : nsresult ToNicerTurnStruct(nr_ice_turn_server *server) const;
165 :
166 : private:
167 0 : NrIceTurnServer(const std::string& username,
168 : const std::vector<unsigned char>& password,
169 0 : const char *transport) :
170 0 : NrIceStunServer(transport), username_(username), password_(password) {}
171 :
172 : std::string username_;
173 : std::vector<unsigned char> password_;
174 : };
175 :
176 0 : class NrIceProxyServer {
177 : public:
178 0 : NrIceProxyServer(const std::string& host, uint16_t port,
179 0 : const std::string& alpn) :
180 0 : host_(host), port_(port), alpn_(alpn) {
181 0 : }
182 :
183 : NrIceProxyServer() : NrIceProxyServer("", 0, "") {}
184 :
185 0 : const std::string& host() const { return host_; }
186 0 : uint16_t port() const { return port_; }
187 : const std::string& alpn() const { return alpn_; }
188 :
189 : private:
190 : std::string host_;
191 : uint16_t port_;
192 : std::string alpn_;
193 : };
194 :
195 : class TestNat;
196 :
197 : class NrIceStats {
198 : public:
199 : uint16_t stun_retransmits = 0;
200 : uint16_t turn_401s = 0;
201 : uint16_t turn_403s = 0;
202 : uint16_t turn_438s = 0;
203 : };
204 :
205 : class NrIceCtx {
206 : friend class NrIceCtxHandler;
207 : public:
208 : enum ConnectionState { ICE_CTX_INIT,
209 : ICE_CTX_CHECKING,
210 : ICE_CTX_CONNECTED,
211 : ICE_CTX_COMPLETED,
212 : ICE_CTX_FAILED,
213 : ICE_CTX_DISCONNECTED,
214 : ICE_CTX_CLOSED
215 : };
216 :
217 : enum GatheringState { ICE_CTX_GATHER_INIT,
218 : ICE_CTX_GATHER_STARTED,
219 : ICE_CTX_GATHER_COMPLETE
220 : };
221 :
222 : enum Controlling { ICE_CONTROLLING,
223 : ICE_CONTROLLED
224 : };
225 :
226 : enum Policy { ICE_POLICY_RELAY,
227 : ICE_POLICY_NO_HOST,
228 : ICE_POLICY_ALL
229 : };
230 :
231 : // initialize ICE globals, crypto, and logging
232 : static void InitializeGlobals(bool allow_loopback = false,
233 : bool tcp_enabled = true,
234 : bool allow_link_local = false);
235 : static std::string GetNewUfrag();
236 : static std::string GetNewPwd();
237 :
238 : // static GetStunAddrs for use in parent process to support
239 : // sandboxing restrictions
240 : static nsTArray<NrIceStunAddr> GetStunAddrs();
241 : void SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs);
242 :
243 : bool Initialize();
244 : bool Initialize(const std::string& ufrag, const std::string& pwd);
245 :
246 : int SetNat(const RefPtr<TestNat>& aNat);
247 :
248 : // Deinitialize all ICE global state. Used only for testing.
249 : static void internal_DeinitializeGlobal();
250 :
251 : // Divide some timers to faster testing. Used only for testing.
252 : void internal_SetTimerAccelarator(int divider);
253 :
254 0 : nr_ice_ctx *ctx() { return ctx_; }
255 0 : nr_ice_peer_ctx *peer() { return peer_; }
256 :
257 : // Testing only.
258 : void destroy_peer_ctx();
259 :
260 : void SetStream(size_t index, NrIceMediaStream* stream);
261 :
262 0 : RefPtr<NrIceMediaStream> GetStream(size_t index) {
263 0 : if (index < streams_.size()) {
264 0 : return streams_[index];
265 : }
266 0 : return nullptr;
267 : }
268 :
269 : // Some might be null
270 0 : size_t GetStreamCount() const
271 : {
272 0 : return streams_.size();
273 : }
274 :
275 : // The name of the ctx
276 0 : const std::string& name() const { return name_; }
277 :
278 : // Get ufrag and password.
279 : std::string ufrag() const;
280 : std::string pwd() const;
281 :
282 : // Current state
283 0 : ConnectionState connection_state() const {
284 0 : return connection_state_;
285 : }
286 :
287 : // Current state
288 0 : GatheringState gathering_state() const {
289 0 : return gathering_state_;
290 : }
291 :
292 : // Get the global attributes
293 : std::vector<std::string> GetGlobalAttributes();
294 :
295 : // Set the other side's global attributes
296 : nsresult ParseGlobalAttributes(std::vector<std::string> attrs);
297 :
298 : // Set whether we are controlling or not.
299 : nsresult SetControlling(Controlling controlling);
300 :
301 : Controlling GetControlling();
302 :
303 : // Set whether we're allowed to produce none, relay or all candidates.
304 : // TODO(jib@mozilla.com): Work out what change means mid-connection (1181768)
305 : nsresult SetPolicy(Policy policy);
306 :
307 0 : Policy policy() const {
308 0 : return policy_;
309 : }
310 :
311 : // Set the STUN servers. Must be called before StartGathering
312 : // (if at all).
313 : nsresult SetStunServers(const std::vector<NrIceStunServer>& stun_servers);
314 :
315 : // Set the TURN servers. Must be called before StartGathering
316 : // (if at all).
317 : nsresult SetTurnServers(const std::vector<NrIceTurnServer>& turn_servers);
318 :
319 : // Provide the resolution provider. Must be called before
320 : // StartGathering.
321 : nsresult SetResolver(nr_resolver *resolver);
322 :
323 : // Provide the proxy address. Must be called before
324 : // StartGathering.
325 : nsresult SetProxyServer(const NrIceProxyServer& proxy_server);
326 :
327 : // Start ICE gathering
328 : nsresult StartGathering(bool default_route_only, bool proxy_only);
329 :
330 : // Start checking
331 : nsresult StartChecks(bool offerer);
332 :
333 : // Notify that the network has gone online/offline
334 : void UpdateNetworkState(bool online);
335 :
336 : // Finalize the ICE negotiation. I.e., there will be no
337 : // more forking.
338 : nsresult Finalize();
339 :
340 : void AccumulateStats(const NrIceStats& stats);
341 : NrIceStats Destroy();
342 :
343 : // Are we trickling?
344 0 : bool generating_trickle() const { return trickle_; }
345 :
346 : // Signals to indicate events. API users can (and should)
347 : // register for these.
348 : sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
349 : SignalGatheringStateChange;
350 : sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
351 : SignalConnectionStateChange;
352 :
353 : // The thread to direct method calls to
354 0 : nsCOMPtr<nsIEventTarget> thread() { return sts_target_; }
355 :
356 0 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtx)
357 :
358 : private:
359 : NrIceCtx(const std::string& name, Policy policy);
360 :
361 : virtual ~NrIceCtx();
362 :
363 : DISALLOW_COPY_ASSIGN(NrIceCtx);
364 :
365 : // Callbacks for nICEr
366 : static void gather_cb(NR_SOCKET s, int h, void *arg); // ICE gather complete
367 :
368 : // Handler implementation
369 : static int select_pair(void *obj,nr_ice_media_stream *stream,
370 : int component_id, nr_ice_cand_pair **potentials,
371 : int potential_ct);
372 : static int stream_ready(void *obj, nr_ice_media_stream *stream);
373 : static int stream_failed(void *obj, nr_ice_media_stream *stream);
374 : static int ice_checking(void *obj, nr_ice_peer_ctx *pctx);
375 : static int ice_connected(void *obj, nr_ice_peer_ctx *pctx);
376 : static int ice_disconnected(void *obj, nr_ice_peer_ctx *pctx);
377 : static int msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
378 : nr_ice_media_stream *stream, int component_id,
379 : unsigned char *msg, int len);
380 : static void trickle_cb(void *arg, nr_ice_ctx *ctx, nr_ice_media_stream *stream,
381 : int component_id, nr_ice_candidate *candidate);
382 :
383 : // Find a media stream by stream ptr. Gross
384 : RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream);
385 :
386 : // Set the state
387 : void SetConnectionState(ConnectionState state);
388 :
389 : // Set the state
390 : void SetGatheringState(GatheringState state);
391 :
392 : ConnectionState connection_state_;
393 : GatheringState gathering_state_;
394 : const std::string name_;
395 : bool offerer_;
396 : TimeStamp ice_start_time_;
397 : bool ice_controlling_set_;
398 : std::vector<RefPtr<NrIceMediaStream> > streams_;
399 : nr_ice_ctx *ctx_;
400 : nr_ice_peer_ctx *peer_;
401 : nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
402 : nr_ice_handler* ice_handler_; // Must be pointer
403 : bool trickle_;
404 : nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
405 : Policy policy_;
406 : RefPtr<TestNat> nat_;
407 : };
408 :
409 :
410 : } // close namespace
411 : #endif
|