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 :
8 : // Original author: ekr@rtfm.com
9 :
10 : // Some of this code is cut-and-pasted from nICEr. Copyright is:
11 :
12 : /*
13 : Copyright (c) 2007, Adobe Systems, Incorporated
14 : All rights reserved.
15 :
16 : Redistribution and use in source and binary forms, with or without
17 : modification, are permitted provided that the following conditions are
18 : met:
19 :
20 : * Redistributions of source code must retain the above copyright
21 : notice, this list of conditions and the following disclaimer.
22 :
23 : * Redistributions in binary form must reproduce the above copyright
24 : notice, this list of conditions and the following disclaimer in the
25 : documentation and/or other materials provided with the distribution.
26 :
27 : * Neither the name of Adobe Systems, Network Resonance nor the names of its
28 : contributors may be used to endorse or promote products derived from
29 : this software without specific prior written permission.
30 :
31 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36 : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37 : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38 : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39 : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41 : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 : */
43 :
44 : #include <string>
45 : #include <vector>
46 :
47 : #include "mozilla/Telemetry.h"
48 : #include "mozilla/UniquePtr.h"
49 :
50 : #include "logging.h"
51 : #include "nspr.h"
52 : #include "nss.h"
53 : #include "pk11pub.h"
54 : #include "plbase64.h"
55 :
56 : #include "nsCOMPtr.h"
57 : #include "nsComponentManagerUtils.h"
58 : #include "nsError.h"
59 : #include "nsIEventTarget.h"
60 : #include "nsNetCID.h"
61 : #include "nsComponentManagerUtils.h"
62 : #include "nsServiceManagerUtils.h"
63 : #include "ScopedNSSTypes.h"
64 : #include "runnable_utils.h"
65 : #include "nsIPrefService.h"
66 : #include "nsIPrefBranch.h"
67 :
68 : // nICEr includes
69 : extern "C" {
70 : #include "nr_api.h"
71 : #include "registry.h"
72 : #include "async_timer.h"
73 : #include "r_crc32.h"
74 : #include "r_memory.h"
75 : #include "ice_reg.h"
76 : #include "ice_util.h"
77 : #include "transport_addr.h"
78 : #include "nr_crypto.h"
79 : #include "nr_socket.h"
80 : #include "nr_socket_local.h"
81 : #include "nr_proxy_tunnel.h"
82 : #include "stun_client_ctx.h"
83 : #include "stun_reg.h"
84 : #include "stun_server_ctx.h"
85 : #include "stun_util.h"
86 : #include "ice_codeword.h"
87 : #include "ice_ctx.h"
88 : #include "ice_candidate.h"
89 : #include "ice_handler.h"
90 : }
91 :
92 : // Local includes
93 : #include "nricectx.h"
94 : #include "nricemediastream.h"
95 : #include "nr_socket_prsock.h"
96 : #include "nrinterfaceprioritizer.h"
97 : #include "rlogconnector.h"
98 : #include "test_nr_socket.h"
99 :
100 : namespace mozilla {
101 :
102 0 : TimeStamp nr_socket_short_term_violation_time() {
103 0 : return NrSocketBase::short_term_violation_time();
104 : }
105 :
106 0 : TimeStamp nr_socket_long_term_violation_time() {
107 0 : return NrSocketBase::long_term_violation_time();
108 : }
109 :
110 0 : MOZ_MTLOG_MODULE("mtransport")
111 :
112 : const char kNrIceTransportUdp[] = "udp";
113 : const char kNrIceTransportTcp[] = "tcp";
114 : const char kNrIceTransportTls[] = "tls";
115 :
116 : static bool initialized = false;
117 :
118 : // Implement NSPR-based crypto algorithms
119 0 : static int nr_crypto_nss_random_bytes(UCHAR *buf, int len) {
120 0 : UniquePK11SlotInfo slot(PK11_GetInternalSlot());
121 0 : if (!slot)
122 0 : return R_INTERNAL;
123 :
124 0 : SECStatus rv = PK11_GenerateRandomOnSlot(slot.get(), buf, len);
125 0 : if (rv != SECSuccess)
126 0 : return R_INTERNAL;
127 :
128 0 : return 0;
129 : }
130 :
131 0 : static int nr_crypto_nss_hmac(UCHAR *key, int keyl, UCHAR *buf, int bufl,
132 : UCHAR *result) {
133 0 : CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC;
134 0 : PK11SlotInfo *slot = nullptr;
135 0 : MOZ_ASSERT(keyl > 0);
136 0 : SECItem keyi = { siBuffer, key, static_cast<unsigned int>(keyl)};
137 0 : PK11SymKey *skey = nullptr;
138 0 : PK11Context *hmac_ctx = nullptr;
139 : SECStatus status;
140 : unsigned int hmac_len;
141 0 : SECItem param = { siBuffer, nullptr, 0 };
142 0 : int err = R_INTERNAL;
143 :
144 0 : slot = PK11_GetInternalKeySlot();
145 0 : if (!slot)
146 0 : goto abort;
147 :
148 : skey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
149 0 : CKA_SIGN, &keyi, nullptr);
150 0 : if (!skey)
151 0 : goto abort;
152 :
153 :
154 : hmac_ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN,
155 0 : skey, ¶m);
156 0 : if (!hmac_ctx)
157 0 : goto abort;
158 :
159 0 : status = PK11_DigestBegin(hmac_ctx);
160 0 : if (status != SECSuccess)
161 0 : goto abort;
162 :
163 0 : status = PK11_DigestOp(hmac_ctx, buf, bufl);
164 0 : if (status != SECSuccess)
165 0 : goto abort;
166 :
167 0 : status = PK11_DigestFinal(hmac_ctx, result, &hmac_len, 20);
168 0 : if (status != SECSuccess)
169 0 : goto abort;
170 :
171 0 : MOZ_ASSERT(hmac_len == 20);
172 :
173 0 : err = 0;
174 :
175 : abort:
176 0 : if(hmac_ctx) PK11_DestroyContext(hmac_ctx, PR_TRUE);
177 0 : if (skey) PK11_FreeSymKey(skey);
178 0 : if (slot) PK11_FreeSlot(slot);
179 :
180 0 : return err;
181 : }
182 :
183 0 : static int nr_crypto_nss_md5(UCHAR *buf, int bufl, UCHAR *result) {
184 0 : int err = R_INTERNAL;
185 : SECStatus rv;
186 :
187 0 : const SECHashObject *ho = HASH_GetHashObject(HASH_AlgMD5);
188 0 : MOZ_ASSERT(ho);
189 0 : if (!ho)
190 0 : goto abort;
191 :
192 0 : MOZ_ASSERT(ho->length == 16);
193 :
194 0 : rv = HASH_HashBuf(ho->type, result, buf, bufl);
195 0 : if (rv != SECSuccess)
196 0 : goto abort;
197 :
198 0 : err = 0;
199 : abort:
200 0 : return err;
201 : }
202 :
203 : static nr_ice_crypto_vtbl nr_ice_crypto_nss_vtbl = {
204 : nr_crypto_nss_random_bytes,
205 : nr_crypto_nss_hmac,
206 : nr_crypto_nss_md5
207 : };
208 :
209 0 : nsresult NrIceStunServer::ToNicerStunStruct(nr_ice_stun_server *server) const {
210 : int r;
211 :
212 0 : memset(server, 0, sizeof(nr_ice_stun_server));
213 0 : if (transport_ == kNrIceTransportUdp) {
214 0 : server->transport = IPPROTO_UDP;
215 0 : } else if (transport_ == kNrIceTransportTcp) {
216 0 : server->transport = IPPROTO_TCP;
217 0 : } else if (transport_ == kNrIceTransportTls) {
218 0 : server->transport = IPPROTO_TCP;
219 0 : if (has_addr_) {
220 : // Refuse to try TLS without an FQDN
221 0 : return NS_ERROR_INVALID_ARG;
222 : }
223 0 : server->tls = 1;
224 : } else {
225 0 : MOZ_MTLOG(ML_ERROR, "Unsupported STUN server transport: " << transport_);
226 0 : return NS_ERROR_FAILURE;
227 : }
228 :
229 0 : if (has_addr_) {
230 0 : r = nr_praddr_to_transport_addr(&addr_, &server->u.addr,
231 0 : server->transport, 0);
232 0 : if (r) {
233 0 : return NS_ERROR_FAILURE;
234 : }
235 0 : server->type=NR_ICE_STUN_SERVER_TYPE_ADDR;
236 : }
237 : else {
238 0 : MOZ_ASSERT(sizeof(server->u.dnsname.host) > host_.size());
239 0 : PL_strncpyz(server->u.dnsname.host, host_.c_str(),
240 0 : sizeof(server->u.dnsname.host));
241 0 : server->u.dnsname.port = port_;
242 0 : server->type=NR_ICE_STUN_SERVER_TYPE_DNSNAME;
243 : }
244 :
245 0 : return NS_OK;
246 : }
247 :
248 :
249 0 : nsresult NrIceTurnServer::ToNicerTurnStruct(nr_ice_turn_server *server) const {
250 0 : memset(server, 0, sizeof(nr_ice_turn_server));
251 :
252 0 : nsresult rv = ToNicerStunStruct(&server->turn_server);
253 0 : if (NS_FAILED(rv))
254 0 : return rv;
255 :
256 0 : if (!(server->username=r_strdup(username_.c_str())))
257 0 : return NS_ERROR_OUT_OF_MEMORY;
258 :
259 : // TODO(ekr@rtfm.com): handle non-ASCII passwords somehow?
260 : // STUN requires they be SASLpreped, but we don't know if
261 : // they are at this point.
262 :
263 : // C++03 23.2.4, Paragraph 1 stipulates that the elements
264 : // in std::vector must be contiguous, and can therefore be
265 : // used as input to functions expecting C arrays.
266 0 : int r = r_data_create(&server->password,
267 0 : const_cast<UCHAR *>(&password_[0]),
268 0 : password_.size());
269 0 : if (r) {
270 0 : RFREE(server->username);
271 0 : return NS_ERROR_OUT_OF_MEMORY;
272 : }
273 :
274 0 : return NS_OK;
275 : }
276 :
277 0 : NrIceCtx::NrIceCtx(const std::string& name, Policy policy)
278 : : connection_state_(ICE_CTX_INIT),
279 : gathering_state_(ICE_CTX_GATHER_INIT),
280 : name_(name),
281 : offerer_(false),
282 : ice_controlling_set_(false),
283 : streams_(),
284 : ctx_(nullptr),
285 : peer_(nullptr),
286 : ice_handler_vtbl_(nullptr),
287 : ice_handler_(nullptr),
288 : trickle_(true),
289 : policy_(policy),
290 0 : nat_ (nullptr) {
291 0 : }
292 :
293 : // Handler callbacks
294 0 : int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream,
295 : int component_id, nr_ice_cand_pair **potentials,
296 : int potential_ct) {
297 0 : MOZ_MTLOG(ML_DEBUG, "select pair called: potential_ct = "
298 : << potential_ct);
299 :
300 0 : return 0;
301 : }
302 :
303 0 : int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) {
304 0 : MOZ_MTLOG(ML_DEBUG, "stream_ready called");
305 :
306 : // Get the ICE ctx.
307 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
308 :
309 0 : RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
310 :
311 : // Streams which do not exist should never be ready.
312 0 : MOZ_ASSERT(s);
313 :
314 0 : s->Ready();
315 :
316 0 : return 0;
317 : }
318 :
319 0 : int NrIceCtx::stream_failed(void *obj, nr_ice_media_stream *stream) {
320 0 : MOZ_MTLOG(ML_DEBUG, "stream_failed called");
321 :
322 : // Get the ICE ctx
323 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
324 0 : RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
325 :
326 : // Streams which do not exist should never fail.
327 0 : MOZ_ASSERT(s);
328 :
329 0 : ctx->SetConnectionState(ICE_CTX_FAILED);
330 0 : s -> SignalFailed(s);
331 0 : return 0;
332 : }
333 :
334 0 : int NrIceCtx::ice_checking(void *obj, nr_ice_peer_ctx *pctx) {
335 0 : MOZ_MTLOG(ML_DEBUG, "ice_checking called");
336 :
337 : // Get the ICE ctx
338 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
339 :
340 0 : ctx->SetConnectionState(ICE_CTX_CHECKING);
341 :
342 0 : return 0;
343 : }
344 :
345 0 : int NrIceCtx::ice_connected(void *obj, nr_ice_peer_ctx *pctx) {
346 0 : MOZ_MTLOG(ML_DEBUG, "ice_connected called");
347 :
348 : // Get the ICE ctx
349 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
350 :
351 : // This is called even on failed contexts.
352 0 : if (ctx->connection_state() != ICE_CTX_FAILED) {
353 0 : ctx->SetConnectionState(ICE_CTX_CONNECTED);
354 : }
355 :
356 0 : return 0;
357 : }
358 :
359 0 : int NrIceCtx::ice_disconnected(void *obj, nr_ice_peer_ctx *pctx) {
360 0 : MOZ_MTLOG(ML_DEBUG, "ice_disconnected called");
361 :
362 : // Get the ICE ctx
363 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
364 :
365 0 : ctx->SetConnectionState(ICE_CTX_DISCONNECTED);
366 :
367 0 : return 0;
368 : }
369 :
370 0 : int NrIceCtx::msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
371 : nr_ice_media_stream *stream, int component_id,
372 : UCHAR *msg, int len) {
373 : // Get the ICE ctx
374 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
375 0 : RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
376 :
377 : // Streams which do not exist should never have packets.
378 0 : MOZ_ASSERT(s);
379 :
380 0 : s->SignalPacketReceived(s, component_id, msg, len);
381 :
382 0 : return 0;
383 : }
384 :
385 0 : void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
386 : nr_ice_media_stream *stream,
387 : int component_id,
388 : nr_ice_candidate *candidate) {
389 : // Get the ICE ctx
390 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
391 0 : RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
392 :
393 0 : if (!s) {
394 : // This stream has been removed because it is inactive
395 0 : return;
396 : }
397 :
398 : // Format the candidate.
399 : char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
400 : int r = nr_ice_format_candidate_attribute(candidate, candidate_str,
401 0 : sizeof(candidate_str));
402 0 : MOZ_ASSERT(!r);
403 0 : if (r)
404 0 : return;
405 :
406 0 : MOZ_MTLOG(ML_INFO, "NrIceCtx(" << ctx->name_ << "): trickling candidate "
407 : << candidate_str);
408 :
409 0 : s->SignalCandidate(s, candidate_str);
410 : }
411 :
412 :
413 : void
414 0 : NrIceCtx::InitializeGlobals(bool allow_loopback,
415 : bool tcp_enabled,
416 : bool allow_link_local) {
417 : // Initialize the crypto callbacks and logging stuff
418 0 : if (!initialized) {
419 0 : NR_reg_init(NR_REG_MODE_LOCAL);
420 0 : nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
421 0 : initialized = true;
422 :
423 : // Set the priorites for candidate type preferences.
424 : // These numbers come from RFC 5245 S. 4.1.2.2
425 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100);
426 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110);
427 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126);
428 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5);
429 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX_TCP, 99);
430 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX_TCP, 109);
431 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125);
432 0 : NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);
433 :
434 0 : int32_t stun_client_maximum_transmits = 7;
435 0 : int32_t ice_trickle_grace_period = 5000;
436 0 : int32_t ice_tcp_so_sock_count = 3;
437 0 : int32_t ice_tcp_listen_backlog = 10;
438 0 : nsAutoCString force_net_interface;
439 : nsresult res;
440 : nsCOMPtr<nsIPrefService> prefs =
441 0 : do_GetService("@mozilla.org/preferences-service;1", &res);
442 :
443 0 : if (NS_SUCCEEDED(res)) {
444 0 : nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
445 0 : if (branch) {
446 0 : branch->GetIntPref(
447 : "media.peerconnection.ice.stun_client_maximum_transmits",
448 0 : &stun_client_maximum_transmits);
449 0 : branch->GetIntPref(
450 : "media.peerconnection.ice.trickle_grace_period",
451 0 : &ice_trickle_grace_period);
452 0 : branch->GetIntPref(
453 : "media.peerconnection.ice.tcp_so_sock_count",
454 0 : &ice_tcp_so_sock_count);
455 0 : branch->GetIntPref(
456 : "media.peerconnection.ice.tcp_listen_backlog",
457 0 : &ice_tcp_listen_backlog);
458 0 : branch->GetCharPref(
459 : "media.peerconnection.ice.force_interface",
460 0 : getter_Copies(force_net_interface));
461 : }
462 : }
463 :
464 0 : NR_reg_set_uint4((char *)"stun.client.maximum_transmits",
465 0 : stun_client_maximum_transmits);
466 0 : NR_reg_set_uint4((char *)NR_ICE_REG_TRICKLE_GRACE_PERIOD,
467 0 : ice_trickle_grace_period);
468 : NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
469 0 : ice_tcp_so_sock_count);
470 : NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG,
471 0 : ice_tcp_listen_backlog);
472 :
473 0 : NR_reg_set_char((char *)NR_ICE_REG_ICE_TCP_DISABLE, !tcp_enabled);
474 :
475 0 : if (allow_loopback) {
476 0 : NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LOOPBACK_ADDRS, 1);
477 : }
478 :
479 0 : if (allow_link_local) {
480 0 : NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
481 : }
482 0 : if (force_net_interface.Length() > 0) {
483 : // Stupid cast.... but needed
484 0 : const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface));
485 0 : NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get()));
486 : }
487 : }
488 0 : }
489 :
490 : std::string
491 0 : NrIceCtx::GetNewUfrag()
492 : {
493 : char* ufrag;
494 : int r;
495 :
496 0 : if ((r=nr_ice_get_new_ice_ufrag(&ufrag))) {
497 0 : MOZ_CRASH("Unable to get new ice ufrag");
498 : return "";
499 : }
500 :
501 0 : std::string ufragStr = ufrag;
502 0 : RFREE(ufrag);
503 :
504 0 : return ufragStr;
505 : }
506 :
507 : std::string
508 0 : NrIceCtx::GetNewPwd()
509 : {
510 : char* pwd;
511 : int r;
512 :
513 0 : if ((r=nr_ice_get_new_ice_pwd(&pwd))) {
514 0 : MOZ_CRASH("Unable to get new ice pwd");
515 : return "";
516 : }
517 :
518 0 : std::string pwdStr = pwd;
519 0 : RFREE(pwd);
520 :
521 0 : return pwdStr;
522 : }
523 :
524 : #define MAXADDRS 100 // mirrors setting in ice_ctx.c
525 :
526 : /* static */
527 : nsTArray<NrIceStunAddr>
528 0 : NrIceCtx::GetStunAddrs()
529 : {
530 0 : nsTArray<NrIceStunAddr> addrs;
531 :
532 : nr_local_addr local_addrs[MAXADDRS];
533 0 : int addr_ct=0;
534 :
535 : // most likely running on parent process and need crypto vtbl
536 : // initialized on Windows (Linux and OSX don't seem to care)
537 0 : if (!initialized) {
538 0 : nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
539 : }
540 :
541 0 : MOZ_MTLOG(ML_INFO, "NrIceCtx static call to find local stun addresses");
542 0 : if (nr_stun_find_local_addresses(local_addrs, MAXADDRS, &addr_ct)) {
543 0 : MOZ_MTLOG(ML_INFO, "Error finding local stun addresses");
544 : } else {
545 0 : for(int i=0; i<addr_ct; ++i) {
546 0 : NrIceStunAddr addr(&local_addrs[i]);
547 0 : addrs.AppendElement(addr);
548 : }
549 : }
550 :
551 0 : return addrs;
552 : }
553 :
554 : void
555 0 : NrIceCtx::SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs)
556 : {
557 : nr_local_addr* local_addrs;
558 0 : local_addrs = new nr_local_addr[addrs.Length()];
559 :
560 0 : for(size_t i=0; i<addrs.Length(); ++i) {
561 0 : nr_local_addr_copy(&local_addrs[i],
562 0 : const_cast<nr_local_addr*>(&addrs[i].localAddr()));
563 : }
564 0 : nr_ice_set_local_addresses(ctx_, local_addrs, addrs.Length());
565 :
566 0 : delete[] local_addrs;
567 0 : }
568 :
569 : bool
570 0 : NrIceCtx::Initialize()
571 : {
572 0 : std::string ufrag = GetNewUfrag();
573 0 : std::string pwd = GetNewPwd();
574 :
575 0 : return Initialize(ufrag, pwd);
576 : }
577 :
578 : bool
579 0 : NrIceCtx::Initialize(const std::string& ufrag,
580 : const std::string& pwd)
581 : {
582 0 : MOZ_ASSERT(!ufrag.empty());
583 0 : MOZ_ASSERT(!pwd.empty());
584 0 : if (ufrag.empty() || pwd.empty()) {
585 0 : return false;
586 : }
587 :
588 : // Create the ICE context
589 : int r;
590 :
591 0 : UINT4 flags = NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
592 0 : switch (policy_) {
593 : case ICE_POLICY_RELAY:
594 0 : flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
595 0 : break;
596 : case ICE_POLICY_NO_HOST:
597 0 : flags |= NR_ICE_CTX_FLAGS_HIDE_HOST_CANDIDATES;
598 0 : break;
599 : case ICE_POLICY_ALL:
600 0 : break;
601 : }
602 :
603 0 : r = nr_ice_ctx_create_with_credentials(const_cast<char *>(name_.c_str()),
604 : flags,
605 0 : const_cast<char *>(ufrag.c_str()),
606 0 : const_cast<char *>(pwd.c_str()),
607 0 : &ctx_);
608 0 : MOZ_ASSERT(ufrag == ctx_->ufrag);
609 0 : MOZ_ASSERT(pwd == ctx_->pwd);
610 :
611 0 : if (r) {
612 0 : MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name_ << "'");
613 0 : return false;
614 : }
615 :
616 0 : nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
617 0 : if (!prioritizer) {
618 0 : MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
619 0 : return false;
620 : }
621 :
622 0 : r = nr_ice_ctx_set_interface_prioritizer(ctx_, prioritizer);
623 0 : if (r) {
624 0 : MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer.");
625 0 : return false;
626 : }
627 :
628 0 : if (generating_trickle()) {
629 0 : r = nr_ice_ctx_set_trickle_cb(ctx_, &NrIceCtx::trickle_cb, this);
630 0 : if (r) {
631 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name_ << "'");
632 0 : return false;
633 : }
634 : }
635 :
636 0 : nsCString mapping_type;
637 0 : nsCString filtering_type;
638 0 : bool block_udp = false;
639 0 : bool block_tcp = false;
640 :
641 : nsresult rv;
642 : nsCOMPtr<nsIPrefService> pref_service =
643 0 : do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
644 :
645 0 : if (NS_SUCCEEDED(rv)) {
646 0 : nsCOMPtr<nsIPrefBranch> pref_branch;
647 0 : rv = pref_service->GetBranch(nullptr, getter_AddRefs(pref_branch));
648 0 : if (NS_SUCCEEDED(rv)) {
649 0 : rv = pref_branch->GetCharPref(
650 : "media.peerconnection.nat_simulator.mapping_type",
651 0 : getter_Copies(mapping_type));
652 0 : rv = pref_branch->GetCharPref(
653 : "media.peerconnection.nat_simulator.filtering_type",
654 0 : getter_Copies(filtering_type));
655 0 : rv = pref_branch->GetBoolPref(
656 : "media.peerconnection.nat_simulator.block_udp",
657 0 : &block_udp);
658 0 : rv = pref_branch->GetBoolPref(
659 : "media.peerconnection.nat_simulator.block_tcp",
660 0 : &block_tcp);
661 : }
662 : }
663 :
664 0 : if (!mapping_type.IsEmpty() && !filtering_type.IsEmpty()) {
665 0 : MOZ_MTLOG(ML_DEBUG, "NAT filtering type: " << filtering_type.get());
666 0 : MOZ_MTLOG(ML_DEBUG, "NAT mapping type: " << mapping_type.get());
667 0 : TestNat* test_nat = new TestNat;
668 0 : test_nat->filtering_type_ = TestNat::ToNatBehavior(filtering_type.get());
669 0 : test_nat->mapping_type_ = TestNat::ToNatBehavior(mapping_type.get());
670 0 : test_nat->block_udp_ = block_udp;
671 0 : test_nat->block_tcp_ = block_tcp;
672 0 : test_nat->enabled_ = true;
673 0 : SetNat(test_nat);
674 : }
675 :
676 : // Create the handler objects
677 0 : ice_handler_vtbl_ = new nr_ice_handler_vtbl();
678 0 : ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
679 0 : ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
680 0 : ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
681 0 : ice_handler_vtbl_->ice_connected = &NrIceCtx::ice_connected;
682 0 : ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
683 0 : ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking;
684 0 : ice_handler_vtbl_->ice_disconnected = &NrIceCtx::ice_disconnected;
685 :
686 0 : ice_handler_ = new nr_ice_handler();
687 0 : ice_handler_->vtbl = ice_handler_vtbl_;
688 0 : ice_handler_->obj = this;
689 :
690 : // Create the peer ctx. Because we do not support parallel forking, we
691 : // only have one peer ctx.
692 0 : std::string peer_name = name_ + ":default";
693 0 : r = nr_ice_peer_ctx_create(ctx_, ice_handler_,
694 0 : const_cast<char *>(peer_name.c_str()),
695 0 : &peer_);
696 0 : if (r) {
697 0 : MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name_ << "'");
698 0 : return false;
699 : }
700 :
701 0 : sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
702 :
703 0 : if (!NS_SUCCEEDED(rv))
704 0 : return false;
705 :
706 0 : return true;
707 : }
708 :
709 0 : int NrIceCtx::SetNat(const RefPtr<TestNat>& aNat) {
710 0 : nat_ = aNat;
711 : nr_socket_factory *fac;
712 0 : int r = nat_->create_socket_factory(&fac);
713 0 : if (r) {
714 0 : return r;
715 : }
716 0 : nr_ice_ctx_set_socket_factory(ctx_, fac);
717 0 : return 0;
718 : }
719 :
720 : // ONLY USE THIS FOR TESTING. Will cause totally unpredictable and possibly very
721 : // bad effects if ICE is still live.
722 0 : void NrIceCtx::internal_DeinitializeGlobal() {
723 0 : NR_reg_del((char *)"stun");
724 0 : NR_reg_del((char *)"ice");
725 0 : RLogConnector::DestroyInstance();
726 0 : nr_crypto_vtbl = nullptr;
727 0 : initialized = false;
728 0 : }
729 :
730 0 : void NrIceCtx::internal_SetTimerAccelarator(int divider) {
731 0 : ctx_->test_timer_divider = divider;
732 0 : }
733 :
734 0 : void NrIceCtx::AccumulateStats(const NrIceStats& stats) {
735 0 : nr_ice_accumulate_count(&(ctx_->stats.stun_retransmits),
736 0 : stats.stun_retransmits);
737 0 : nr_ice_accumulate_count(&(ctx_->stats.turn_401s), stats.turn_401s);
738 0 : nr_ice_accumulate_count(&(ctx_->stats.turn_403s), stats.turn_403s);
739 0 : nr_ice_accumulate_count(&(ctx_->stats.turn_438s), stats.turn_438s);
740 0 : }
741 :
742 0 : NrIceStats NrIceCtx::Destroy() {
743 : // designed to be called more than once so if stats are desired, this can be
744 : // called just prior to the destructor
745 0 : MOZ_MTLOG(ML_DEBUG, "Destroying ICE ctx '" << name_ <<"'");
746 0 : for (auto& stream : streams_) {
747 0 : if (stream) {
748 0 : stream->Close();
749 : }
750 : }
751 :
752 0 : NrIceStats stats;
753 0 : if (ctx_) {
754 0 : stats.stun_retransmits = ctx_->stats.stun_retransmits;
755 0 : stats.turn_401s = ctx_->stats.turn_401s;
756 0 : stats.turn_403s = ctx_->stats.turn_403s;
757 0 : stats.turn_438s = ctx_->stats.turn_438s;
758 : }
759 :
760 0 : if (!ice_start_time_.IsNull()) {
761 0 : TimeDuration time_delta = TimeStamp::Now() - ice_start_time_;
762 0 : ice_start_time_ = TimeStamp(); // null out
763 :
764 0 : if (offerer_) {
765 0 : Telemetry::Accumulate(
766 : Telemetry::WEBRTC_ICE_OFFERER_ABORT_TIME,
767 0 : time_delta.ToMilliseconds());
768 : } else {
769 0 : Telemetry::Accumulate(
770 : Telemetry::WEBRTC_ICE_ANSWERER_ABORT_TIME,
771 0 : time_delta.ToMilliseconds());
772 : }
773 : }
774 :
775 0 : if (peer_) {
776 0 : nr_ice_peer_ctx_destroy(&peer_);
777 : }
778 0 : if (ctx_) {
779 0 : nr_ice_ctx_destroy(&ctx_);
780 : }
781 :
782 0 : delete ice_handler_vtbl_;
783 0 : delete ice_handler_;
784 :
785 0 : ice_handler_vtbl_ = nullptr;
786 0 : ice_handler_ = nullptr;
787 0 : streams_.clear();
788 :
789 0 : return stats;
790 : }
791 :
792 0 : NrIceCtx::~NrIceCtx() {
793 0 : Destroy();
794 0 : }
795 :
796 : void
797 0 : NrIceCtx::SetStream(size_t index, NrIceMediaStream* stream) {
798 0 : if (index >= streams_.size()) {
799 0 : streams_.resize(index + 1);
800 : }
801 :
802 0 : RefPtr<NrIceMediaStream> oldStream(streams_[index]);
803 0 : streams_[index] = stream;
804 :
805 0 : if (oldStream) {
806 0 : oldStream->Close();
807 : }
808 0 : }
809 :
810 0 : std::string NrIceCtx::ufrag() const {
811 0 : return ctx_->ufrag;
812 : }
813 :
814 0 : std::string NrIceCtx::pwd() const {
815 0 : return ctx_->pwd;
816 : }
817 :
818 0 : void NrIceCtx::destroy_peer_ctx() {
819 0 : nr_ice_peer_ctx_destroy(&peer_);
820 0 : }
821 :
822 0 : nsresult NrIceCtx::SetControlling(Controlling controlling) {
823 0 : if (!ice_controlling_set_) {
824 0 : peer_->controlling = (controlling == ICE_CONTROLLING)? 1 : 0;
825 0 : ice_controlling_set_ = true;
826 :
827 0 : MOZ_MTLOG(ML_DEBUG, "ICE ctx " << name_ << " setting controlling to" <<
828 : controlling);
829 : }
830 0 : return NS_OK;
831 : }
832 :
833 0 : NrIceCtx::Controlling NrIceCtx::GetControlling() {
834 0 : return (peer_->controlling) ? ICE_CONTROLLING : ICE_CONTROLLED;
835 : }
836 :
837 0 : nsresult NrIceCtx::SetPolicy(Policy policy) {
838 0 : policy_ = policy;
839 0 : return NS_OK;
840 : }
841 :
842 0 : nsresult NrIceCtx::SetStunServers(const std::vector<NrIceStunServer>&
843 : stun_servers) {
844 0 : if (stun_servers.empty())
845 0 : return NS_OK;
846 :
847 0 : auto servers = MakeUnique<nr_ice_stun_server[]>(stun_servers.size());
848 :
849 0 : for (size_t i=0; i < stun_servers.size(); ++i) {
850 0 : nsresult rv = stun_servers[i].ToNicerStunStruct(&servers[i]);
851 0 : if (NS_FAILED(rv)) {
852 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set STUN server for '" << name_ << "'");
853 0 : return NS_ERROR_FAILURE;
854 : }
855 : }
856 :
857 0 : int r = nr_ice_ctx_set_stun_servers(ctx_, servers.get(), stun_servers.size());
858 0 : if (r) {
859 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set STUN server for '" << name_ << "'");
860 0 : return NS_ERROR_FAILURE;
861 : }
862 :
863 0 : return NS_OK;
864 : }
865 :
866 : // TODO(ekr@rtfm.com): This is just SetStunServers with s/Stun/Turn
867 : // Could we do a template or something?
868 0 : nsresult NrIceCtx::SetTurnServers(const std::vector<NrIceTurnServer>&
869 : turn_servers) {
870 0 : if (turn_servers.empty())
871 0 : return NS_OK;
872 :
873 0 : auto servers = MakeUnique<nr_ice_turn_server[]>(turn_servers.size());
874 :
875 0 : for (size_t i=0; i < turn_servers.size(); ++i) {
876 0 : nsresult rv = turn_servers[i].ToNicerTurnStruct(&servers[i]);
877 0 : if (NS_FAILED(rv)) {
878 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set TURN server for '" << name_ << "'");
879 0 : return NS_ERROR_FAILURE;
880 : }
881 : }
882 :
883 0 : int r = nr_ice_ctx_set_turn_servers(ctx_, servers.get(), turn_servers.size());
884 0 : if (r) {
885 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set TURN server for '" << name_ << "'");
886 0 : return NS_ERROR_FAILURE;
887 : }
888 :
889 : // TODO(ekr@rtfm.com): This leaks the username/password. Need to free that.
890 :
891 0 : return NS_OK;
892 : }
893 :
894 0 : nsresult NrIceCtx::SetResolver(nr_resolver *resolver) {
895 0 : int r = nr_ice_ctx_set_resolver(ctx_, resolver);
896 :
897 0 : if (r) {
898 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set resolver for '" << name_ << "'");
899 0 : return NS_ERROR_FAILURE;
900 : }
901 :
902 0 : return NS_OK;
903 : }
904 :
905 0 : nsresult NrIceCtx::SetProxyServer(const NrIceProxyServer& proxy_server) {
906 : int r,_status;
907 0 : nr_proxy_tunnel_config *config = nullptr;
908 0 : nr_socket_wrapper_factory *wrapper = nullptr;
909 :
910 0 : if ((r = nr_proxy_tunnel_config_create(&config))) {
911 0 : ABORT(r);
912 : }
913 :
914 0 : if ((r = nr_proxy_tunnel_config_set_proxy(config,
915 0 : proxy_server.host().c_str(),
916 0 : proxy_server.port()))) {
917 0 : ABORT(r);
918 : }
919 :
920 0 : if ((r = nr_proxy_tunnel_config_set_resolver(config, ctx_->resolver))) {
921 0 : ABORT(r);
922 : }
923 :
924 0 : if ((r = nr_socket_wrapper_factory_proxy_tunnel_create(config, &wrapper))) {
925 0 : MOZ_MTLOG(LogLevel::Error, "Couldn't create proxy tunnel wrapper.");
926 0 : ABORT(r);
927 : }
928 :
929 : // nr_ice_ctx will own the wrapper after this call
930 0 : if ((r = nr_ice_ctx_set_turn_tcp_socket_wrapper(ctx_, wrapper))) {
931 0 : MOZ_MTLOG(ML_ERROR, "Couldn't set proxy for '" << name_ << "': " << r);
932 0 : ABORT(r);
933 : }
934 :
935 0 : _status = 0;
936 : abort:
937 0 : nr_proxy_tunnel_config_destroy(&config);
938 0 : if (_status) {
939 0 : nr_socket_wrapper_factory_destroy(&wrapper);
940 0 : return NS_ERROR_FAILURE;
941 : }
942 0 : return NS_OK;
943 : }
944 :
945 0 : nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only) {
946 0 : ASSERT_ON_THREAD(sts_target_);
947 0 : SetGatheringState(ICE_CTX_GATHER_STARTED);
948 :
949 0 : if (default_route_only) {
950 0 : nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
951 : } else {
952 0 : nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS);
953 : }
954 :
955 0 : if (proxy_only) {
956 0 : nr_ice_ctx_add_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
957 : } else {
958 0 : nr_ice_ctx_remove_flags(ctx_, NR_ICE_CTX_FLAGS_ONLY_PROXY);
959 : }
960 :
961 : // This might start gathering for the first time, or again after
962 : // renegotiation, or might do nothing at all if gathering has already
963 : // finished.
964 0 : int r = nr_ice_gather(ctx_, &NrIceCtx::gather_cb, this);
965 :
966 0 : if (!r) {
967 0 : SetGatheringState(ICE_CTX_GATHER_COMPLETE);
968 0 : } else if (r != R_WOULDBLOCK) {
969 0 : MOZ_MTLOG(ML_ERROR, "Couldn't gather ICE candidates for '"
970 : << name_ << "', error=" << r);
971 0 : SetConnectionState(ICE_CTX_FAILED);
972 0 : return NS_ERROR_FAILURE;
973 : }
974 :
975 0 : return NS_OK;
976 : }
977 :
978 0 : RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
979 : nr_ice_media_stream *stream) {
980 0 : for (auto& stream_ : streams_) {
981 0 : if (stream_ && (stream_->stream() == stream)) {
982 0 : return stream_;
983 : }
984 : }
985 :
986 0 : return nullptr;
987 : }
988 :
989 0 : std::vector<std::string> NrIceCtx::GetGlobalAttributes() {
990 0 : char **attrs = nullptr;
991 : int attrct;
992 : int r;
993 0 : std::vector<std::string> ret;
994 :
995 0 : r = nr_ice_get_global_attributes(ctx_, &attrs, &attrct);
996 0 : if (r) {
997 0 : MOZ_MTLOG(ML_ERROR, "Couldn't get ufrag and password for '"
998 : << name_ << "'");
999 0 : return ret;
1000 : }
1001 :
1002 0 : for (int i=0; i<attrct; i++) {
1003 0 : ret.push_back(std::string(attrs[i]));
1004 0 : RFREE(attrs[i]);
1005 : }
1006 0 : RFREE(attrs);
1007 :
1008 0 : return ret;
1009 : }
1010 :
1011 0 : nsresult NrIceCtx::ParseGlobalAttributes(std::vector<std::string> attrs) {
1012 0 : std::vector<char *> attrs_in;
1013 :
1014 0 : for (auto& attr : attrs) {
1015 0 : attrs_in.push_back(const_cast<char *>(attr.c_str()));
1016 : }
1017 :
1018 0 : int r = nr_ice_peer_ctx_parse_global_attributes(peer_,
1019 0 : attrs_in.size() ?
1020 : &attrs_in[0] : nullptr,
1021 0 : attrs_in.size());
1022 0 : if (r) {
1023 0 : MOZ_MTLOG(ML_ERROR, "Couldn't parse global attributes for "
1024 : << name_ << "'");
1025 0 : return NS_ERROR_FAILURE;
1026 : }
1027 :
1028 0 : return NS_OK;
1029 : }
1030 :
1031 0 : nsresult NrIceCtx::StartChecks(bool offerer) {
1032 : int r;
1033 :
1034 0 : offerer_ = offerer;
1035 0 : ice_start_time_ = TimeStamp::Now();
1036 :
1037 0 : r=nr_ice_peer_ctx_pair_candidates(peer_);
1038 0 : if (r) {
1039 0 : MOZ_MTLOG(ML_ERROR, "Couldn't pair candidates on "
1040 : << name_ << "'");
1041 0 : SetConnectionState(ICE_CTX_FAILED);
1042 0 : return NS_ERROR_FAILURE;
1043 : }
1044 :
1045 0 : r = nr_ice_peer_ctx_start_checks2(peer_,1);
1046 0 : if (r) {
1047 0 : if (r == R_NOT_FOUND) {
1048 0 : MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks on "
1049 : << name_ << "' assuming trickle ICE");
1050 : } else {
1051 0 : MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks on "
1052 : << name_ << "'");
1053 0 : SetConnectionState(ICE_CTX_FAILED);
1054 0 : return NS_ERROR_FAILURE;
1055 : }
1056 : }
1057 :
1058 0 : return NS_OK;
1059 : }
1060 :
1061 :
1062 0 : void NrIceCtx::gather_cb(NR_SOCKET s, int h, void *arg) {
1063 0 : NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
1064 :
1065 0 : ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
1066 0 : }
1067 :
1068 0 : nsresult NrIceCtx::Finalize() {
1069 0 : int r = nr_ice_ctx_finalize(ctx_, peer_);
1070 :
1071 0 : if (r) {
1072 0 : MOZ_MTLOG(ML_ERROR, "Couldn't finalize "
1073 : << name_ << "'");
1074 0 : return NS_ERROR_FAILURE;
1075 : }
1076 :
1077 0 : return NS_OK;
1078 : }
1079 :
1080 0 : void NrIceCtx::UpdateNetworkState(bool online) {
1081 0 : MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): updating network state to " <<
1082 : (online ? "online" : "offline"));
1083 0 : if (online) {
1084 0 : nr_ice_peer_ctx_refresh_consent_all_streams(peer_);
1085 : } else {
1086 0 : nr_ice_peer_ctx_disconnect_all_streams(peer_);
1087 : }
1088 0 : }
1089 :
1090 0 : void NrIceCtx::SetConnectionState(ConnectionState state) {
1091 0 : if (state == connection_state_)
1092 0 : return;
1093 :
1094 0 : if (!ice_start_time_.IsNull() && (state > ICE_CTX_CHECKING)) {
1095 0 : TimeDuration time_delta = TimeStamp::Now() - ice_start_time_;
1096 0 : ice_start_time_ = TimeStamp();
1097 :
1098 0 : switch (state) {
1099 : case ICE_CTX_INIT:
1100 : case ICE_CTX_CHECKING:
1101 0 : MOZ_CRASH();
1102 : break;
1103 : case ICE_CTX_CONNECTED:
1104 : case ICE_CTX_COMPLETED:
1105 0 : if (offerer_) {
1106 0 : Telemetry::Accumulate(
1107 : Telemetry::WEBRTC_ICE_OFFERER_SUCCESS_TIME,
1108 0 : time_delta.ToMilliseconds());
1109 : } else {
1110 0 : Telemetry::Accumulate(
1111 : Telemetry::WEBRTC_ICE_ANSWERER_SUCCESS_TIME,
1112 0 : time_delta.ToMilliseconds());
1113 : }
1114 0 : break;
1115 : case ICE_CTX_FAILED:
1116 0 : if (offerer_) {
1117 0 : Telemetry::Accumulate(
1118 : Telemetry::WEBRTC_ICE_OFFERER_FAILURE_TIME,
1119 0 : time_delta.ToMilliseconds());
1120 : } else {
1121 0 : Telemetry::Accumulate(
1122 : Telemetry::WEBRTC_ICE_ANSWERER_FAILURE_TIME,
1123 0 : time_delta.ToMilliseconds());
1124 : }
1125 0 : break;
1126 : case ICE_CTX_DISCONNECTED:
1127 : // We get this every time an ICE disconnect gets reported.
1128 : // Do we want a Telemetry probe counting how often this happens?
1129 0 : break;
1130 : case ICE_CTX_CLOSED:
1131 : // This doesn't seem to be used...
1132 0 : break;
1133 : }
1134 : }
1135 :
1136 0 : MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): state " <<
1137 : connection_state_ << "->" << state);
1138 0 : connection_state_ = state;
1139 :
1140 0 : if (connection_state_ == ICE_CTX_FAILED) {
1141 0 : MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): dumping r_log ringbuffer... ");
1142 0 : std::deque<std::string> logs;
1143 0 : RLogConnector::GetInstance()->GetAny(0, &logs);
1144 0 : for (auto& log : logs) {
1145 0 : MOZ_MTLOG(ML_INFO, log);
1146 : }
1147 : }
1148 :
1149 0 : SignalConnectionStateChange(this, state);
1150 : }
1151 :
1152 0 : void NrIceCtx::SetGatheringState(GatheringState state) {
1153 0 : if (state == gathering_state_)
1154 0 : return;
1155 :
1156 0 : MOZ_MTLOG(ML_DEBUG, "NrIceCtx(" << name_ << "): gathering state " <<
1157 : gathering_state_ << "->" << state);
1158 0 : gathering_state_ = state;
1159 :
1160 0 : SignalGatheringStateChange(this, state);
1161 : }
1162 :
1163 : } // close namespace
1164 :
1165 : // Reimplement nr_ice_compute_codeword to avoid copyright issues
1166 0 : void nr_ice_compute_codeword(char *buf, int len,char *codeword) {
1167 : UINT4 c;
1168 :
1169 0 : r_crc32(buf,len,&c);
1170 :
1171 0 : PL_Base64Encode(reinterpret_cast<char*>(&c), 3, codeword);
1172 0 : codeword[4] = 0;
1173 :
1174 0 : return;
1175 : }
|