Coverage Report

Created: 2018-09-25 14:53

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