media/mtransport/nricectx.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     8 // Original author: ekr@rtfm.com
    10 // Some of this code is cut-and-pasted from nICEr. Copyright is:
    12 /*
    13 Copyright (c) 2007, Adobe Systems, Incorporated
    14 All rights reserved.
    16 Redistribution and use in source and binary forms, with or without
    17 modification, are permitted provided that the following conditions are
    18 met:
    20 * Redistributions of source code must retain the above copyright
    21   notice, this list of conditions and the following disclaimer.
    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.
    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.
    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 */
    44 #include <string>
    45 #include <vector>
    47 #include "logging.h"
    48 #include "nspr.h"
    49 #include "nss.h"
    50 #include "pk11pub.h"
    51 #include "plbase64.h"
    53 #include "nsCOMPtr.h"
    54 #include "nsComponentManagerUtils.h"
    55 #include "nsError.h"
    56 #include "nsIEventTarget.h"
    57 #include "nsNetCID.h"
    58 #include "nsComponentManagerUtils.h"
    59 #include "nsServiceManagerUtils.h"
    60 #include "ScopedNSSTypes.h"
    62 // nICEr includes
    63 extern "C" {
    64 #include "nr_api.h"
    65 #include "registry.h"
    66 #include "async_timer.h"
    67 #include "r_crc32.h"
    68 #include "r_memory.h"
    69 #include "ice_reg.h"
    70 #include "ice_util.h"
    71 #include "transport_addr.h"
    72 #include "nr_crypto.h"
    73 #include "nr_socket.h"
    74 #include "nr_socket_local.h"
    75 #include "stun_client_ctx.h"
    76 #include "stun_server_ctx.h"
    77 #include "ice_codeword.h"
    78 #include "ice_ctx.h"
    79 #include "ice_candidate.h"
    80 #include "ice_handler.h"
    81 }
    83 // Local includes
    84 #include "nricectx.h"
    85 #include "nricemediastream.h"
    86 #include "nr_socket_prsock.h"
    87 #include "nrinterfaceprioritizer.h"
    88 #include "rlogringbuffer.h"
    90 namespace mozilla {
    92 MOZ_MTLOG_MODULE("mtransport")
    94 const char kNrIceTransportUdp[] = "udp";
    95 const char kNrIceTransportTcp[] = "tcp";
    97 static bool initialized = false;
    99 // Implement NSPR-based crypto algorithms
   100 static int nr_crypto_nss_random_bytes(UCHAR *buf, int len) {
   101   ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
   102   if (!slot)
   103     return R_INTERNAL;
   105   SECStatus rv = PK11_GenerateRandomOnSlot(slot, buf, len);
   106   if (rv != SECSuccess)
   107     return R_INTERNAL;
   109   return 0;
   110 }
   112 static int nr_crypto_nss_hmac(UCHAR *key, int keyl, UCHAR *buf, int bufl,
   113                               UCHAR *result) {
   114   CK_MECHANISM_TYPE mech = CKM_SHA_1_HMAC;
   115   PK11SlotInfo *slot = 0;
   116   MOZ_ASSERT(keyl > 0);
   117   SECItem keyi = { siBuffer, key, static_cast<unsigned int>(keyl)};
   118   PK11SymKey *skey = 0;
   119   PK11Context *hmac_ctx = 0;
   120   SECStatus status;
   121   unsigned int hmac_len;
   122   SECItem param = { siBuffer, nullptr, 0 };
   123   int err = R_INTERNAL;
   125   slot = PK11_GetInternalKeySlot();
   126   if (!slot)
   127     goto abort;
   129   skey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
   130                           CKA_SIGN, &keyi, nullptr);
   131   if (!skey)
   132     goto abort;
   135   hmac_ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN,
   136                                         skey, &param);
   137   if (!hmac_ctx)
   138     goto abort;
   140   status = PK11_DigestBegin(hmac_ctx);
   141   if (status != SECSuccess)
   142     goto abort;
   144   status = PK11_DigestOp(hmac_ctx, buf, bufl);
   145   if (status != SECSuccess)
   146     goto abort;
   148   status = PK11_DigestFinal(hmac_ctx, result, &hmac_len, 20);
   149   if (status != SECSuccess)
   150     goto abort;
   152   MOZ_ASSERT(hmac_len == 20);
   154   err = 0;
   156  abort:
   157   if(hmac_ctx) PK11_DestroyContext(hmac_ctx, PR_TRUE);
   158   if (skey) PK11_FreeSymKey(skey);
   159   if (slot) PK11_FreeSlot(slot);
   161   return err;
   162 }
   164 static int nr_crypto_nss_md5(UCHAR *buf, int bufl, UCHAR *result) {
   165   int err = R_INTERNAL;
   166   SECStatus rv;
   168   const SECHashObject *ho = HASH_GetHashObject(HASH_AlgMD5);
   169   MOZ_ASSERT(ho);
   170   if (!ho)
   171     goto abort;
   173   MOZ_ASSERT(ho->length == 16);
   175   rv = HASH_HashBuf(ho->type, result, buf, bufl);
   176   if (rv != SECSuccess)
   177     goto abort;
   179   err = 0;
   180 abort:
   181   return err;
   182 }
   184 static nr_ice_crypto_vtbl nr_ice_crypto_nss_vtbl = {
   185   nr_crypto_nss_random_bytes,
   186   nr_crypto_nss_hmac,
   187   nr_crypto_nss_md5
   188 };
   193 nsresult NrIceStunServer::ToNicerStunStruct(nr_ice_stun_server *server,
   194                                             const std::string &transport) const {
   195   int r;
   196   int transport_int;
   198   memset(server, 0, sizeof(nr_ice_stun_server));
   199   if (transport == kNrIceTransportUdp) {
   200     transport_int = IPPROTO_UDP;
   201   } else if (transport == kNrIceTransportTcp) {
   202     transport_int = IPPROTO_TCP;
   203   } else {
   204     MOZ_ASSERT(false);
   205     return NS_ERROR_FAILURE;
   206   }
   208   if (has_addr_) {
   209     r = nr_praddr_to_transport_addr(&addr_, &server->u.addr,
   210                                     transport_int, 0);
   211     if (r) {
   212       return NS_ERROR_FAILURE;
   213     }
   214     server->type=NR_ICE_STUN_SERVER_TYPE_ADDR;
   215   }
   216   else {
   217     MOZ_ASSERT(sizeof(server->u.dnsname.host) > host_.size());
   218     PL_strncpyz(server->u.dnsname.host, host_.c_str(),
   219                 sizeof(server->u.dnsname.host));
   220     server->u.dnsname.port = port_;
   221     server->type=NR_ICE_STUN_SERVER_TYPE_DNSNAME;
   222   }
   224   return NS_OK;
   225 }
   228 nsresult NrIceTurnServer::ToNicerTurnStruct(nr_ice_turn_server *server) const {
   229   memset(server, 0, sizeof(nr_ice_turn_server));
   231   nsresult rv = ToNicerStunStruct(&server->turn_server, transport_);
   232   if (NS_FAILED(rv))
   233     return rv;
   235   if (transport_ == kNrIceTransportUdp) {
   236     server->transport = IPPROTO_UDP;
   237   } else if (transport_ == kNrIceTransportTcp) {
   238     server->transport = IPPROTO_TCP;
   239   } else {
   240     MOZ_ASSERT(false);
   241     return NS_ERROR_FAILURE;
   242   }
   244   if (username_.empty())
   245     return NS_ERROR_INVALID_ARG;
   246   if (password_.empty())
   247     return NS_ERROR_INVALID_ARG;
   249   if (!(server->username=r_strdup(username_.c_str())))
   250     return NS_ERROR_OUT_OF_MEMORY;
   252   // TODO(ekr@rtfm.com): handle non-ASCII passwords somehow?
   253   // STUN requires they be SASLpreped, but we don't know if
   254   // they are at this point.
   256   // C++03 23.2.4, Paragraph 1 stipulates that the elements
   257   // in std::vector must be contiguous, and can therefore be
   258   // used as input to functions expecting C arrays.
   259   int r = r_data_create(&server->password,
   260                         const_cast<UCHAR *>(&password_[0]),
   261                         password_.size());
   262   if (r) {
   263     RFREE(server->username);
   264     return NS_ERROR_OUT_OF_MEMORY;
   265   }
   267   return NS_OK;
   268 }
   270 // Handler callbacks
   271 int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream,
   272                    int component_id, nr_ice_cand_pair **potentials,
   273                    int potential_ct) {
   274   MOZ_MTLOG(ML_DEBUG, "select pair called: potential_ct = "
   275             << potential_ct);
   277   return 0;
   278 }
   280 int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) {
   281   MOZ_MTLOG(ML_DEBUG, "stream_ready called");
   283   // Get the ICE ctx.
   284   NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
   286   RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
   288   // Streams which do not exist should never be ready.
   289   MOZ_ASSERT(s);
   291   s->Ready();
   293   return 0;
   294 }
   296 int NrIceCtx::stream_failed(void *obj, nr_ice_media_stream *stream) {
   297   MOZ_MTLOG(ML_DEBUG, "stream_failed called");
   299   // Get the ICE ctx
   300   NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
   301   RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
   303   // Streams which do not exist should never fail.
   304   MOZ_ASSERT(s);
   306   ctx->SetConnectionState(ICE_CTX_FAILED);
   307   s -> SignalFailed(s);
   308   return 0;
   309 }
   311 int NrIceCtx::ice_completed(void *obj, nr_ice_peer_ctx *pctx) {
   312   MOZ_MTLOG(ML_DEBUG, "ice_completed called");
   314   // Get the ICE ctx
   315   NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
   317   // This is called even on failed contexts.
   318   if (ctx->connection_state() != ICE_CTX_FAILED) {
   319     ctx->SetConnectionState(ICE_CTX_OPEN);
   320   }
   322   return 0;
   323 }
   325 int NrIceCtx::msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
   326                         nr_ice_media_stream *stream, int component_id,
   327                         UCHAR *msg, int len) {
   328   // Get the ICE ctx
   329   NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
   330   RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
   332   // Streams which do not exist should never have packets.
   333   MOZ_ASSERT(s);
   335   s->SignalPacketReceived(s, component_id, msg, len);
   337   return 0;
   338 }
   340 void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
   341                           nr_ice_media_stream *stream,
   342                           int component_id,
   343                           nr_ice_candidate *candidate) {
   344   // Get the ICE ctx
   345   NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
   346   RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
   348   // Streams which do not exist shouldn't have candidates.
   349   MOZ_ASSERT(s);
   351   // Format the candidate.
   352   char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
   353   int r = nr_ice_format_candidate_attribute(candidate, candidate_str,
   354                                             sizeof(candidate_str));
   355   MOZ_ASSERT(!r);
   356   if (r)
   357     return;
   359   MOZ_MTLOG(ML_INFO, "NrIceCtx(" << ctx->name_ << "): trickling candidate "
   360             << candidate_str);
   362   s->SignalCandidate(s, candidate_str);
   363 }
   365 RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
   366                                   bool offerer,
   367                                   bool set_interface_priorities) {
   369   RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer);
   371   // Initialize the crypto callbacks and logging stuff
   372   if (!initialized) {
   373     NR_reg_init(NR_REG_MODE_LOCAL);
   374     RLogRingBuffer::CreateInstance();
   375     nr_crypto_vtbl = &nr_ice_crypto_nss_vtbl;
   376     initialized = true;
   378     // Set the priorites for candidate type preferences.
   379     // These numbers come from RFC 5245 S. 4.1.2.2
   380     NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_SRV_RFLX, 100);
   381     NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_PEER_RFLX, 110);
   382     NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST, 126);
   383     NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED, 5);
   384     NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);
   386     if (set_interface_priorities) {
   387       NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
   388       NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
   389       NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
   390       NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
   391       NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
   392       NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
   393       NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251);
   394       NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249);
   395       NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250);
   396       NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249);
   397       NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248);
   398       NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247);
   399       NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251);
   400       NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252);
   401       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240);
   402       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241);
   403       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239);
   404       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238);
   405       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237);
   406       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236);
   407       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235);
   408       NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234);
   409       NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
   410       NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
   411     }
   413     NR_reg_set_uint4((char *)"stun.client.maximum_transmits",5);
   414   }
   416   // Create the ICE context
   417   int r;
   419   UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
   420       NR_ICE_CTX_FLAGS_ANSWERER;
   421   flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
   423   r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
   424                         &ctx->ctx_);
   425   if (r) {
   426     MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name << "'");
   427     return nullptr;
   428   }
   430 #ifdef USE_INTERFACE_PRIORITIZER
   431   nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
   432   if (!prioritizer) {
   433     MOZ_MTLOG(PR_LOG_ERROR, "Couldn't create interface prioritizer.");
   434     return nullptr;
   435   }
   437   r = nr_ice_ctx_set_interface_prioritizer(ctx->ctx_, prioritizer);
   438   if (r) {
   439     MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set interface prioritizer.");
   440     return nullptr;
   441   }
   442 #endif  // USE_INTERFACE_PRIORITIZER
   444   if (ctx->generating_trickle()) {
   445     r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
   446     if (r) {
   447       MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'");
   448       return nullptr;
   449     }
   450   }
   452   // Create the handler objects
   453   ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
   454   ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
   455   ctx->ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
   456   ctx->ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
   457   ctx->ice_handler_vtbl_->ice_completed = &NrIceCtx::ice_completed;
   458   ctx->ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
   460   ctx->ice_handler_ = new nr_ice_handler();
   461   ctx->ice_handler_->vtbl = ctx->ice_handler_vtbl_;
   462   ctx->ice_handler_->obj = ctx;
   464   // Create the peer ctx. Because we do not support parallel forking, we
   465   // only have one peer ctx.
   466   std::string peer_name = name + ":default";
   467   r = nr_ice_peer_ctx_create(ctx->ctx_, ctx->ice_handler_,
   468                              const_cast<char *>(peer_name.c_str()),
   469                              &ctx->peer_);
   470   if (r) {
   471     MOZ_MTLOG(ML_ERROR, "Couldn't create ICE peer ctx for '" << name << "'");
   472     return nullptr;
   473   }
   475   nsresult rv;
   476   ctx->sts_target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   478   if (!NS_SUCCEEDED(rv))
   479     return nullptr;
   481   return ctx;
   482 }
   485 NrIceCtx::~NrIceCtx() {
   486   MOZ_MTLOG(ML_DEBUG, "Destroying ICE ctx '" << name_ <<"'");
   487   nr_ice_peer_ctx_destroy(&peer_);
   488   nr_ice_ctx_destroy(&ctx_);
   489   delete ice_handler_vtbl_;
   490   delete ice_handler_;
   491 }
   493 RefPtr<NrIceMediaStream>
   494 NrIceCtx::CreateStream(const std::string& name, int components) {
   495   RefPtr<NrIceMediaStream> stream =
   496     NrIceMediaStream::Create(this, name, components);
   498   streams_.push_back(stream);
   500   return stream;
   501 }
   503 void NrIceCtx::destroy_peer_ctx() {
   504   nr_ice_peer_ctx_destroy(&peer_);
   505 }
   507 nsresult NrIceCtx::SetControlling(Controlling controlling) {
   508   peer_->controlling = (controlling == ICE_CONTROLLING)? 1 : 0;
   510   MOZ_MTLOG(ML_DEBUG, "ICE ctx " << name_ << " setting controlling to" <<
   511             controlling);
   512   return NS_OK;
   513 }
   515 nsresult NrIceCtx::SetStunServers(const std::vector<NrIceStunServer>&
   516                                   stun_servers) {
   517   if (stun_servers.empty())
   518     return NS_OK;
   520   ScopedDeleteArray<nr_ice_stun_server> servers(
   521       new nr_ice_stun_server[stun_servers.size()]);
   523   for (size_t i=0; i < stun_servers.size(); ++i) {
   524     nsresult rv = stun_servers[i].ToNicerStunStruct(&servers[i]);
   525     if (NS_FAILED(rv)) {
   526       MOZ_MTLOG(ML_ERROR, "Couldn't set STUN server for '" << name_ << "'");
   527       return NS_ERROR_FAILURE;
   528     }
   529   }
   531   int r = nr_ice_ctx_set_stun_servers(ctx_, servers, stun_servers.size());
   532   if (r) {
   533     MOZ_MTLOG(ML_ERROR, "Couldn't set STUN server for '" << name_ << "'");
   534     return NS_ERROR_FAILURE;
   535   }
   537   return NS_OK;
   538 }
   540 // TODO(ekr@rtfm.com): This is just SetStunServers with s/Stun/Turn
   541 // Could we do a template or something?
   542 nsresult NrIceCtx::SetTurnServers(const std::vector<NrIceTurnServer>&
   543                                   turn_servers) {
   544   if (turn_servers.empty())
   545     return NS_OK;
   547   ScopedDeleteArray<nr_ice_turn_server> servers(
   548       new nr_ice_turn_server[turn_servers.size()]);
   550   for (size_t i=0; i < turn_servers.size(); ++i) {
   551     nsresult rv = turn_servers[i].ToNicerTurnStruct(&servers[i]);
   552     if (NS_FAILED(rv)) {
   553       MOZ_MTLOG(ML_ERROR, "Couldn't set TURN server for '" << name_ << "'");
   554       return NS_ERROR_FAILURE;
   555     }
   556   }
   558   int r = nr_ice_ctx_set_turn_servers(ctx_, servers, turn_servers.size());
   559   if (r) {
   560     MOZ_MTLOG(ML_ERROR, "Couldn't set TURN server for '" << name_ << "'");
   561     return NS_ERROR_FAILURE;
   562   }
   564   // TODO(ekr@rtfm.com): This leaks the username/password. Need to free that.
   566   return NS_OK;
   567 }
   569 nsresult NrIceCtx::SetResolver(nr_resolver *resolver) {
   570   int r = nr_ice_ctx_set_resolver(ctx_, resolver);
   572   if (r) {
   573     MOZ_MTLOG(ML_ERROR, "Couldn't set resolver for '" << name_ << "'");
   574     return NS_ERROR_FAILURE;
   575   }
   577   return NS_OK;
   578 }
   580 nsresult NrIceCtx::StartGathering() {
   581   MOZ_ASSERT(ctx_->state == ICE_CTX_INIT);
   582   if (ctx_->state != ICE_CTX_INIT) {
   583     MOZ_MTLOG(ML_ERROR, "ICE ctx in the wrong state for gathering: '"
   584               << name_ << "'");
   585     SetConnectionState(ICE_CTX_FAILED);
   586     return NS_ERROR_FAILURE;
   587   }
   589   int r = nr_ice_initialize(ctx_, &NrIceCtx::initialized_cb,
   590                             this);
   592   if (r && r != R_WOULDBLOCK) {
   593       MOZ_MTLOG(ML_ERROR, "Couldn't gather ICE candidates for '"
   594                 << name_ << "'");
   595       SetConnectionState(ICE_CTX_FAILED);
   596       return NS_ERROR_FAILURE;
   597   }
   599   SetGatheringState(ICE_CTX_GATHER_STARTED);
   601   return NS_OK;
   602 }
   604 RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
   605     nr_ice_media_stream *stream) {
   606   for (size_t i=0; i<streams_.size(); ++i) {
   607     if (streams_[i]->stream() == stream) {
   608       return streams_[i];
   609     }
   610   }
   612   return nullptr;
   613 }
   615 std::vector<std::string> NrIceCtx::GetGlobalAttributes() {
   616   char **attrs = 0;
   617   int attrct;
   618   int r;
   619   std::vector<std::string> ret;
   621   r = nr_ice_get_global_attributes(ctx_, &attrs, &attrct);
   622   if (r) {
   623     MOZ_MTLOG(ML_ERROR, "Couldn't get ufrag and password for '"
   624               << name_ << "'");
   625     return ret;
   626   }
   628   for (int i=0; i<attrct; i++) {
   629     ret.push_back(std::string(attrs[i]));
   630     RFREE(attrs[i]);
   631   }
   632   RFREE(attrs);
   634   return ret;
   635 }
   637 nsresult NrIceCtx::ParseGlobalAttributes(std::vector<std::string> attrs) {
   638   std::vector<char *> attrs_in;
   640   for (size_t i=0; i<attrs.size(); ++i) {
   641     attrs_in.push_back(const_cast<char *>(attrs[i].c_str()));
   642   }
   644   int r = nr_ice_peer_ctx_parse_global_attributes(peer_,
   645                                                   attrs_in.size() ?
   646                                                   &attrs_in[0] : nullptr,
   647                                                   attrs_in.size());
   648   if (r) {
   649     MOZ_MTLOG(ML_ERROR, "Couldn't parse global attributes for "
   650               << name_ << "'");
   651     return NS_ERROR_FAILURE;
   652   }
   654   return NS_OK;
   655 }
   657 nsresult NrIceCtx::StartChecks() {
   658   int r;
   660   r=nr_ice_peer_ctx_pair_candidates(peer_);
   661   if (r) {
   662     MOZ_MTLOG(ML_ERROR, "Couldn't pair candidates on "
   663               << name_ << "'");
   664     SetConnectionState(ICE_CTX_FAILED);
   665     return NS_ERROR_FAILURE;
   666   }
   668   r = nr_ice_peer_ctx_start_checks2(peer_,1);
   669   if (r) {
   670     if (r == R_NOT_FOUND) {
   671       MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks on "
   672                 << name_ << "' assuming trickle ICE");
   673     } else {
   674       MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks on "
   675                 << name_ << "'");
   676       SetConnectionState(ICE_CTX_FAILED);
   677       return NS_ERROR_FAILURE;
   678     }
   679   } else {
   680     SetConnectionState(ICE_CTX_CHECKING);
   681   }
   683   return NS_OK;
   684 }
   687 void NrIceCtx::initialized_cb(NR_SOCKET s, int h, void *arg) {
   688   NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
   690   ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
   691 }
   693 nsresult NrIceCtx::Finalize() {
   694   int r = nr_ice_ctx_finalize(ctx_, peer_);
   696   if (r) {
   697     MOZ_MTLOG(ML_ERROR, "Couldn't finalize "
   698          << name_ << "'");
   699     return NS_ERROR_FAILURE;
   700   }
   702   return NS_OK;
   703 }
   705 void NrIceCtx::SetConnectionState(ConnectionState state) {
   706   if (state == connection_state_)
   707     return;
   709   MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): state " <<
   710             connection_state_ << "->" << state);
   711   connection_state_ = state;
   713   SignalConnectionStateChange(this, state);
   714 }
   716 void NrIceCtx::SetGatheringState(GatheringState state) {
   717   if (state == gathering_state_)
   718     return;
   720   MOZ_MTLOG(ML_DEBUG, "NrIceCtx(" << name_ << "): gathering state " <<
   721             gathering_state_ << "->" << state);
   722   gathering_state_ = state;
   724   SignalGatheringStateChange(this, state);
   725 }
   727 }  // close namespace
   729 // Reimplement nr_ice_compute_codeword to avoid copyright issues
   730 void nr_ice_compute_codeword(char *buf, int len,char *codeword) {
   731     UINT4 c;
   733     r_crc32(buf,len,&c);
   735     PL_Base64Encode(reinterpret_cast<char*>(&c), 3, codeword);
   736     codeword[4] = 0;
   738     return;
   739 }

mercurial