media/mtransport/test/ice_unittest.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     7 // Original author: ekr@rtfm.com
     9 #include <algorithm>
    10 #include <deque>
    11 #include <iostream>
    12 #include <limits>
    13 #include <map>
    14 #include <string>
    15 #include <vector>
    17 #include "sigslot.h"
    19 #include "logging.h"
    20 #include "nspr.h"
    21 #include "nss.h"
    22 #include "ssl.h"
    24 #include "mozilla/Scoped.h"
    25 #include "nsThreadUtils.h"
    26 #include "nsXPCOM.h"
    28 #include "nricectx.h"
    29 #include "nricemediastream.h"
    30 #include "nriceresolverfake.h"
    31 #include "nriceresolver.h"
    32 #include "nrinterfaceprioritizer.h"
    33 #include "mtransport_test_utils.h"
    34 #include "gtest_ringbuffer_dumper.h"
    35 #include "rlogringbuffer.h"
    36 #include "runnable_utils.h"
    37 #include "stunserver.h"
    38 // TODO(bcampen@mozilla.com): Big fat hack since the build system doesn't give
    39 // us a clean way to add object files to a single executable.
    40 #include "stunserver.cpp"
    41 #include "stun_udp_socket_filter.h"
    42 #include "mozilla/net/DNS.h"
    44 #define GTEST_HAS_RTTI 0
    45 #include "gtest/gtest.h"
    46 #include "gtest_utils.h"
    48 using namespace mozilla;
    49 MtransportTestUtils *test_utils;
    51 bool stream_added = false;
    53 static int kDefaultTimeout = 7000;
    55 const std::string kDefaultStunServerAddress((char *)"23.21.150.121");
    56 const std::string kDefaultStunServerHostname(
    57     (char *)"ec2-23-21-150-121.compute-1.amazonaws.com");
    58 const std::string kBogusStunServerHostname(
    59     (char *)"stun-server-nonexistent.invalid");
    60 const uint16_t kDefaultStunServerPort=3478;
    61 const std::string kBogusIceCandidate(
    62     (char *)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
    64 std::string g_stun_server_address(kDefaultStunServerAddress);
    65 std::string g_stun_server_hostname(kDefaultStunServerHostname);
    66 std::string g_turn_server;
    67 std::string g_turn_user;
    68 std::string g_turn_password;
    70 namespace {
    72 enum TrickleMode { TRICKLE_NONE, TRICKLE_SIMULATE, TRICKLE_REAL };
    74 typedef bool (*CandidateFilter)(const std::string& candidate);
    76 static bool IsRelayCandidate(const std::string& candidate) {
    77   return candidate.find("typ relay") != std::string::npos;
    78 }
    80 bool ContainsSucceededPair(const std::vector<NrIceCandidatePair>& pairs) {
    81   for (size_t i = 0; i < pairs.size(); ++i) {
    82     if (pairs[i].state == NrIceCandidatePair::STATE_SUCCEEDED) {
    83       return true;
    84     }
    85   }
    86   return false;
    87 }
    89 // Note: Does not correspond to any notion of prioritization; this is just
    90 // so we can use stl containers/algorithms that need a comparator
    91 bool operator<(const NrIceCandidate& lhs,
    92                const NrIceCandidate& rhs) {
    93   if (lhs.cand_addr.host == rhs.cand_addr.host) {
    94     if (lhs.cand_addr.port == rhs.cand_addr.port) {
    95       if (lhs.cand_addr.transport == rhs.cand_addr.transport) {
    96         return lhs.type < rhs.type;
    97       }
    98       return lhs.cand_addr.transport < rhs.cand_addr.transport;
    99     }
   100     return lhs.cand_addr.port < rhs.cand_addr.port;
   101   }
   102   return lhs.cand_addr.host < rhs.cand_addr.host;
   103 }
   105 bool operator==(const NrIceCandidate& lhs,
   106                 const NrIceCandidate& rhs) {
   107   return !((lhs < rhs) || (rhs < lhs));
   108 }
   110 class IceCandidatePairCompare {
   111   public:
   112     bool operator()(const NrIceCandidatePair& lhs,
   113                     const NrIceCandidatePair& rhs) const {
   114       if (lhs.priority == rhs.priority) {
   115         if (lhs.local == rhs.local) {
   116           if (lhs.remote == rhs.remote) {
   117             return lhs.codeword < rhs.codeword;
   118           }
   119           return lhs.remote < rhs.remote;
   120         }
   121         return lhs.local < rhs.local;
   122       }
   123       return lhs.priority < rhs.priority;
   124     }
   125 };
   127 class IceTestPeer : public sigslot::has_slots<> {
   128  public:
   130   IceTestPeer(const std::string& name, bool offerer, bool set_priorities) :
   131       name_(name),
   132       ice_ctx_(NrIceCtx::Create(name, offerer, set_priorities)),
   133       streams_(),
   134       candidates_(),
   135       gathering_complete_(false),
   136       ready_ct_(0),
   137       ice_complete_(false),
   138       received_(0),
   139       sent_(0),
   140       fake_resolver_(),
   141       dns_resolver_(new NrIceResolver()),
   142       remote_(nullptr),
   143       candidate_filter_(nullptr),
   144       expected_local_type_(NrIceCandidate::ICE_HOST),
   145       expected_local_transport_(kNrIceTransportUdp),
   146       expected_remote_type_(NrIceCandidate::ICE_HOST),
   147       trickle_mode_(TRICKLE_NONE),
   148       trickled_(0) {
   149     ice_ctx_->SignalGatheringStateChange.connect(
   150         this,
   151         &IceTestPeer::GatheringStateChange);
   152     ice_ctx_->SignalConnectionStateChange.connect(
   153         this,
   154         &IceTestPeer::ConnectionStateChange);
   155   }
   157   ~IceTestPeer() {
   158     test_utils->sts_target()->Dispatch(WrapRunnable(this,
   159                                                     &IceTestPeer::Shutdown),
   160         NS_DISPATCH_SYNC);
   162     // Give the ICE destruction callback time to fire before
   163     // we destroy the resolver.
   164     PR_Sleep(1000);
   165   }
   167   void AddStream(int components) {
   168     char name[100];
   169     snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
   170              (int)streams_.size());
   172     mozilla::RefPtr<NrIceMediaStream> stream =
   173         ice_ctx_->CreateStream(static_cast<char *>(name), components);
   175     ASSERT_TRUE(stream);
   176     streams_.push_back(stream);
   177     stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
   178     stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
   179     stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
   180     stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
   181   }
   183   void SetStunServer(const std::string addr, uint16_t port) {
   184     std::vector<NrIceStunServer> stun_servers;
   185     ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create(addr,
   186                                                                     port));
   187     stun_servers.push_back(*server);
   188     ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers)));
   189   }
   191   void SetTurnServer(const std::string addr, uint16_t port,
   192                      const std::string username,
   193                      const std::string password,
   194                      const char* transport) {
   195     std::vector<unsigned char> password_vec(password.begin(), password.end());
   196     SetTurnServer(addr, port, username, password_vec, transport);
   197   }
   200   void SetTurnServer(const std::string addr, uint16_t port,
   201                      const std::string username,
   202                      const std::vector<unsigned char> password,
   203                      const char* transport) {
   204     std::vector<NrIceTurnServer> turn_servers;
   205     ScopedDeletePtr<NrIceTurnServer> server(NrIceTurnServer::Create(
   206         addr, port, username, password, transport));
   207     turn_servers.push_back(*server);
   208     ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers)));
   209   }
   211   void SetTurnServers(const std::vector<NrIceTurnServer> servers) {
   212     ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers)));
   213   }
   215   void SetFakeResolver() {
   216     ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
   217     PRNetAddr addr;
   218     PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(),
   219                                           &addr);
   220     addr.inet.port = kDefaultStunServerPort;
   221     ASSERT_EQ(PR_SUCCESS, status);
   222     fake_resolver_.SetAddr(g_stun_server_hostname, addr);
   223     ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
   224         fake_resolver_.AllocateResolver())));
   225   }
   227   void SetDNSResolver() {
   228     ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
   229     ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
   230         dns_resolver_->AllocateResolver())));
   231   }
   233   void Gather() {
   234     nsresult res;
   236     test_utils->sts_target()->Dispatch(
   237         WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res),
   238         NS_DISPATCH_SYNC);
   240     ASSERT_TRUE(NS_SUCCEEDED(res));
   241   }
   243   // Get various pieces of state
   244   std::vector<std::string> GetGlobalAttributes() {
   245     return ice_ctx_->GetGlobalAttributes();
   246   }
   248    std::vector<std::string> GetCandidates(size_t stream) {
   249     std::vector<std::string> v;
   251     RUN_ON_THREAD(
   252         test_utils->sts_target(),
   253         WrapRunnableRet(this, &IceTestPeer::GetCandidates_s, stream, &v),
   254         NS_DISPATCH_SYNC);
   256     return v;
   257   }
   259   std::vector<std::string> GetCandidates_s(size_t stream) {
   260     std::vector<std::string> candidates;
   262     if (stream >= streams_.size())
   263       return candidates;
   265     std::vector<std::string> candidates_in =
   266       streams_[stream]->GetCandidates();
   269     for (size_t i=0; i < candidates_in.size(); i++) {
   270       if ((!candidate_filter_) || candidate_filter_(candidates_in[i])) {
   271         std::cerr << "Returning candidate: " << candidates_in[i] << std::endl;
   272         candidates.push_back(candidates_in[i]);
   273       }
   274     }
   276     return candidates;
   277   }
   279   void SetExpectedTypes(NrIceCandidate::Type local,
   280                         NrIceCandidate::Type remote,
   281                         std::string local_transport = kNrIceTransportUdp) {
   282     expected_local_type_ = local;
   283     expected_local_transport_ = local_transport;
   284     expected_remote_type_ = remote;
   285   }
   287   bool gathering_complete() { return gathering_complete_; }
   288   int ready_ct() { return ready_ct_; }
   289   bool is_ready(size_t stream) {
   290     return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
   291   }
   292   bool ice_complete() { return ice_complete_; }
   293   size_t received() { return received_; }
   294   size_t sent() { return sent_; }
   296   // Start connecting to another peer
   297   void Connect_s(IceTestPeer *remote, TrickleMode trickle_mode,
   298                  bool start = true) {
   299     nsresult res;
   301     remote_ = remote;
   303     trickle_mode_ = trickle_mode;
   304     res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
   305     ASSERT_TRUE(NS_SUCCEEDED(res));
   307     if (trickle_mode == TRICKLE_NONE ||
   308         trickle_mode == TRICKLE_REAL) {
   309       for (size_t i=0; i<streams_.size(); ++i) {
   310         std::vector<std::string> candidates =
   311             remote->GetCandidates(i);
   313         for (size_t j=0; j<candidates.size(); ++j) {
   314           std::cerr << "Candidate: " + candidates[j] << std::endl;
   315         }
   316         res = streams_[i]->ParseAttributes(candidates);
   317         ASSERT_TRUE(NS_SUCCEEDED(res));
   318       }
   319     } else {
   320       // Parse empty attributes and then trickle them out later
   321       for (size_t i=0; i<streams_.size(); ++i) {
   322         std::vector<std::string> empty_attrs;
   323         res = streams_[i]->ParseAttributes(empty_attrs);
   324         ASSERT_TRUE(NS_SUCCEEDED(res));
   325       }
   326     }
   328     if (start) {
   329       // Now start checks
   330       res = ice_ctx_->StartChecks();
   331       ASSERT_TRUE(NS_SUCCEEDED(res));
   332     }
   333   }
   335   void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
   336                bool start = true) {
   337     test_utils->sts_target()->Dispatch(
   338         WrapRunnable(
   339             this, &IceTestPeer::Connect_s, remote, trickle_mode, start),
   340         NS_DISPATCH_SYNC);
   341   }
   343   void SimulateTrickle(size_t stream) {
   344     std::cerr << "Doing trickle for stream " << stream << std::endl;
   345     // If we are in trickle deferred mode, now trickle in the candidates
   346     // for |stream}
   347     nsresult res;
   349     ASSERT_GT(remote_->streams_.size(), stream);
   351     std::vector<std::string> candidates =
   352       remote_->GetCandidates(stream);
   354     for (size_t j=0; j<candidates.size(); j++) {
   355       test_utils->sts_target()->Dispatch(
   356         WrapRunnableRet(streams_[stream],
   357                         &NrIceMediaStream::ParseTrickleCandidate,
   358                         candidates[j],
   359                         &res), NS_DISPATCH_SYNC);
   361       ASSERT_TRUE(NS_SUCCEEDED(res));
   362     }
   363   }
   365   void DumpCandidate(std::string which, const NrIceCandidate& cand) {
   366     std::string type;
   368     switch(cand.type) {
   369       case NrIceCandidate::ICE_HOST:
   370         type = "host";
   371         break;
   372       case NrIceCandidate::ICE_SERVER_REFLEXIVE:
   373         type = "srflx";
   374         break;
   375       case NrIceCandidate::ICE_PEER_REFLEXIVE:
   376         type = "prflx";
   377         break;
   378       case NrIceCandidate::ICE_RELAYED:
   379         type = "relay";
   380         if (which.find("Local") != std::string::npos) {
   381           type += "(" + cand.local_addr.transport + ")";
   382         }
   383         break;
   384       default:
   385         FAIL();
   386     };
   388     std::cerr << which
   389               << " --> "
   390               << type
   391               << " "
   392               << cand.local_addr.host
   393               << ":"
   394               << cand.local_addr.port
   395               << " codeword="
   396               << cand.codeword
   397               << std::endl;
   398   }
   400   void DumpAndCheckActiveCandidates_s() {
   401     std::cerr << "Active candidates:" << std::endl;
   402     for (size_t i=0; i < streams_.size(); ++i) {
   403       for (int j=0; j < streams_[i]->components(); ++j) {
   404         std::cerr << "Stream " << i << " component " << j+1 << std::endl;
   406         NrIceCandidate *local;
   407         NrIceCandidate *remote;
   409         nsresult res = streams_[i]->GetActivePair(j+1, &local, &remote);
   410         if (res == NS_ERROR_NOT_AVAILABLE) {
   411           std::cerr << "Component unpaired or disabled." << std::endl;
   412         } else {
   413           ASSERT_TRUE(NS_SUCCEEDED(res));
   414           DumpCandidate("Local  ", *local);
   415           ASSERT_EQ(expected_local_type_, local->type);
   416           ASSERT_EQ(expected_local_transport_, local->local_addr.transport);
   417           DumpCandidate("Remote ", *remote);
   418           ASSERT_EQ(expected_remote_type_, remote->type);
   419           delete local;
   420           delete remote;
   421         }
   422       }
   423     }
   424   }
   426   void DumpAndCheckActiveCandidates() {
   427     test_utils->sts_target()->Dispatch(
   428       WrapRunnable(this, &IceTestPeer::DumpAndCheckActiveCandidates_s),
   429       NS_DISPATCH_SYNC);
   430   }
   432   void Close() {
   433     test_utils->sts_target()->Dispatch(
   434       WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx),
   435       NS_DISPATCH_SYNC);
   436   }
   438   void Shutdown() {
   439     ice_ctx_ = nullptr;
   440   }
   442   void StartChecks() {
   443     nsresult res;
   445     // Now start checks
   446     test_utils->sts_target()->Dispatch(
   447         WrapRunnableRet(ice_ctx_, &NrIceCtx::StartChecks, &res),
   448         NS_DISPATCH_SYNC);
   449     ASSERT_TRUE(NS_SUCCEEDED(res));
   450   }
   452   // Handle events
   453   void GatheringStateChange(NrIceCtx* ctx,
   454                             NrIceCtx::GatheringState state) {
   455     (void)ctx;
   456     if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
   457       return;
   458     }
   460     std::cerr << "Gathering complete for " <<  name_ << std::endl;
   461     gathering_complete_ = true;
   463     std::cerr << "CANDIDATES:" << std::endl;
   464     for (size_t i=0; i<streams_.size(); ++i) {
   465       std::cerr << "Stream " << name_ << std::endl;
   466       std::vector<std::string> candidates =
   467           streams_[i]->GetCandidates();
   469       for(size_t j=0; j<candidates.size(); ++j) {
   470         std::cerr << candidates[j] << std::endl;
   471       }
   472     }
   473     std::cerr << std::endl;
   475   }
   477   void CandidateInitialized(NrIceMediaStream *stream, const std::string &candidate) {
   478     std::cerr << "Candidate initialized: " << candidate << std::endl;
   479     candidates_[stream->name()].push_back(candidate);
   481     // If we are connected, then try to trickle to the
   482     // other side.
   483     if (remote_ && remote_->remote_) {
   484       std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
   485           std::find(streams_.begin(), streams_.end(), stream);
   486       ASSERT_NE(streams_.end(), it);
   487       size_t index = it - streams_.begin();
   489       ASSERT_GT(remote_->streams_.size(), index);
   490       nsresult res = remote_->streams_[index]->ParseTrickleCandidate(
   491           candidate);
   492       ASSERT_TRUE(NS_SUCCEEDED(res));
   493       ++trickled_;
   494     }
   495   }
   497   nsresult GetCandidatePairs(size_t stream_index,
   498                              std::vector<NrIceCandidatePair>* pairs) {
   499     MOZ_ASSERT(pairs);
   500     if (stream_index >= streams_.size()) {
   501       // Is there a better error for "no such index"?
   502       ADD_FAILURE() << "No such media stream index: " << stream_index;
   503       return NS_ERROR_INVALID_ARG;
   504     }
   506     nsresult res;
   507     test_utils->sts_target()->Dispatch(
   508         WrapRunnableRet(streams_[stream_index],
   509                         &NrIceMediaStream::GetCandidatePairs,
   510                         pairs,
   511                         &res),
   512         NS_DISPATCH_SYNC);
   513     return res;
   514   }
   516   void DumpCandidatePair(const NrIceCandidatePair& pair) {
   517       std::cerr << std::endl;
   518       DumpCandidate("Local", pair.local);
   519       DumpCandidate("Remote", pair.remote);
   520       std::cerr << "state = " << pair.state
   521                 << " priority = " << pair.priority
   522                 << " nominated = " << pair.nominated
   523                 << " selected = " << pair.selected
   524                 << " codeword = " << pair.codeword << std::endl;
   525   }
   527   void DumpCandidatePairs(NrIceMediaStream *stream) {
   528     std::vector<NrIceCandidatePair> pairs;
   529     nsresult res = stream->GetCandidatePairs(&pairs);
   530     ASSERT_TRUE(NS_SUCCEEDED(res));
   532     std::cerr << "Begin list of candidate pairs [" << std::endl;
   534     for (std::vector<NrIceCandidatePair>::iterator p = pairs.begin();
   535          p != pairs.end(); ++p) {
   536       DumpCandidatePair(*p);
   537     }
   538     std::cerr << "]" << std::endl;
   539   }
   541   void DumpCandidatePairs() {
   542     std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
   543     for (size_t s = 0; s < streams_.size(); ++s) {
   544       DumpCandidatePairs(streams_[s]);
   545     }
   546     std::cerr << "]" << std::endl;
   547   }
   549   bool CandidatePairsPriorityDescending(const std::vector<NrIceCandidatePair>&
   550                                         pairs) {
   551     // Verify that priority is descending
   552     uint64_t priority = std::numeric_limits<uint64_t>::max();
   554     for (size_t p = 0; p < pairs.size(); ++p) {
   555       if (priority < pairs[p].priority) {
   556         std::cerr << "Priority increased in subsequent pairs:" << std::endl;
   557         DumpCandidatePair(pairs[p-1]);
   558         DumpCandidatePair(pairs[p]);
   559         return false;
   560       } else if (priority == pairs[p].priority) {
   561         std::cerr << "Duplicate priority in subseqent pairs:" << std::endl;
   562         DumpCandidatePair(pairs[p-1]);
   563         DumpCandidatePair(pairs[p]);
   564         return false;
   565       }
   566       priority = pairs[p].priority;
   567     }
   568     return true;
   569   }
   571   void UpdateAndValidateCandidatePairs(size_t stream_index,
   572                                        std::vector<NrIceCandidatePair>*
   573                                        new_pairs) {
   574     std::vector<NrIceCandidatePair> old_pairs = *new_pairs;
   575     GetCandidatePairs(stream_index, new_pairs);
   576     ASSERT_TRUE(CandidatePairsPriorityDescending(*new_pairs)) << "New list of "
   577             "candidate pairs is either not sorted in priority order, or has "
   578             "duplicate priorities.";
   579     ASSERT_TRUE(CandidatePairsPriorityDescending(old_pairs)) << "Old list of "
   580             "candidate pairs is either not sorted in priority order, or has "
   581             "duplicate priorities. This indicates some bug in the test case.";
   582     std::vector<NrIceCandidatePair> added_pairs;
   583     std::vector<NrIceCandidatePair> removed_pairs;
   585     // set_difference computes the set of elements that are present in the
   586     // first set, but not the second
   587     // NrIceCandidatePair::operator< compares based on the priority, local
   588     // candidate, and remote candidate in that order. This means this will
   589     // catch cases where the priority has remained the same, but one of the
   590     // candidates has changed.
   591     std::set_difference((*new_pairs).begin(),
   592                         (*new_pairs).end(),
   593                         old_pairs.begin(),
   594                         old_pairs.end(),
   595                         std::inserter(added_pairs, added_pairs.begin()),
   596                         IceCandidatePairCompare());
   598     std::set_difference(old_pairs.begin(),
   599                         old_pairs.end(),
   600                         (*new_pairs).begin(),
   601                         (*new_pairs).end(),
   602                         std::inserter(removed_pairs, removed_pairs.begin()),
   603                         IceCandidatePairCompare());
   605     for (std::vector<NrIceCandidatePair>::iterator a = added_pairs.begin();
   606          a != added_pairs.end(); ++a) {
   607         std::cerr << "Found new candidate pair." << std::endl;
   608         DumpCandidatePair(*a);
   609     }
   611     for (std::vector<NrIceCandidatePair>::iterator r = removed_pairs.begin();
   612          r != removed_pairs.end(); ++r) {
   613         std::cerr << "Pre-existing candidate pair is now missing:" << std::endl;
   614         DumpCandidatePair(*r);
   615     }
   617     ASSERT_TRUE(removed_pairs.empty()) << "At least one candidate pair has "
   618                                           "gone missing.";
   619   }
   621   void StreamReady(NrIceMediaStream *stream) {
   622     ++ready_ct_;
   623     std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
   624     DumpCandidatePairs(stream);
   625   }
   626   void StreamFailed(NrIceMediaStream *stream) {
   627     std::cerr << "Stream failed " << stream->name() << " ct=" << ready_ct_ << std::endl;
   628     DumpCandidatePairs(stream);
   629   }
   631   void ConnectionStateChange(NrIceCtx* ctx,
   632                              NrIceCtx::ConnectionState state) {
   633     (void)ctx;
   634     if (state != NrIceCtx::ICE_CTX_OPEN) {
   635       return;
   636     }
   637     std::cerr << "ICE completed " << name_ << std::endl;
   638     ice_complete_ = true;
   639   }
   641   void PacketReceived(NrIceMediaStream *stream, int component, const unsigned char *data,
   642                       int len) {
   643     std::cerr << "Received " << len << " bytes" << std::endl;
   644     ++received_;
   645   }
   647   void SendPacket(int stream, int component, const unsigned char *data,
   648                   int len) {
   649     ASSERT_TRUE(NS_SUCCEEDED(streams_[stream]->SendPacket(component, data, len)));
   651     ++sent_;
   652     std::cerr << "Sent " << len << " bytes" << std::endl;
   653   }
   655   void SetCandidateFilter(CandidateFilter filter) {
   656     candidate_filter_ = filter;
   657   }
   659   // Allow us to parse candidates directly on the current thread.
   660   void ParseCandidate(size_t i, const std::string& candidate) {
   661     std::vector<std::string> attributes;
   663     attributes.push_back(candidate);
   664     streams_[i]->ParseAttributes(attributes);
   665   }
   667   void DisableComponent(size_t stream, int component_id) {
   668     ASSERT_LT(stream, streams_.size());
   669     nsresult res = streams_[stream]->DisableComponent(component_id);
   670     ASSERT_TRUE(NS_SUCCEEDED(res));
   671   }
   673   int trickled() { return trickled_; }
   675  private:
   676   std::string name_;
   677   nsRefPtr<NrIceCtx> ice_ctx_;
   678   std::vector<mozilla::RefPtr<NrIceMediaStream> > streams_;
   679   std::map<std::string, std::vector<std::string> > candidates_;
   680   bool gathering_complete_;
   681   int ready_ct_;
   682   bool ice_complete_;
   683   size_t received_;
   684   size_t sent_;
   685   NrIceResolverFake fake_resolver_;
   686   nsRefPtr<NrIceResolver> dns_resolver_;
   687   IceTestPeer *remote_;
   688   CandidateFilter candidate_filter_;
   689   NrIceCandidate::Type expected_local_type_;
   690   std::string expected_local_transport_;
   691   NrIceCandidate::Type expected_remote_type_;
   692   TrickleMode trickle_mode_;
   693   int trickled_;
   694 };
   696 class IceGatherTest : public ::testing::Test {
   697  public:
   698   void SetUp() {
   699     test_utils->sts_target()->Dispatch(WrapRunnable(TestStunServer::GetInstance(),
   700                                                     &TestStunServer::Reset),
   701                                        NS_DISPATCH_SYNC);
   702     peer_ = new IceTestPeer("P1", true, false);
   703     peer_->AddStream(1);
   704   }
   706   void Gather(bool wait = true) {
   707      peer_->Gather();
   709     if (wait) {
   710       WaitForGather();
   711     }
   712   }
   714   void WaitForGather() {
   715     ASSERT_TRUE_WAIT(peer_->gathering_complete(), kDefaultTimeout);
   716   }
   718   void UseFakeStunServerWithResponse(const std::string& fake_addr,
   719                                      uint16_t fake_port) {
   720     TestStunServer::GetInstance()->SetResponseAddr(fake_addr, fake_port);
   721     // Sets an additional stun server
   722     peer_->SetStunServer(TestStunServer::GetInstance()->addr(),
   723                          TestStunServer::GetInstance()->port());
   724   }
   726   // NB: Only does substring matching, watch out for stuff like "1.2.3.4"
   727   // matching "21.2.3.47". " 1.2.3.4 " should not have false positives.
   728   bool StreamHasMatchingCandidate(unsigned int stream,
   729                                   const std::string& match) {
   730     std::vector<std::string> candidates = peer_->GetCandidates(stream);
   731     for (size_t c = 0; c < candidates.size(); ++c) {
   732       if (std::string::npos != candidates[c].find(match)) {
   733         return true;
   734       }
   735     }
   736     return false;
   737   }
   739  protected:
   740   mozilla::ScopedDeletePtr<IceTestPeer> peer_;
   741 };
   743 class IceConnectTest : public ::testing::Test {
   744  public:
   745   IceConnectTest() : initted_(false) {}
   747   void SetUp() {
   748     nsresult rv;
   749     target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   750     ASSERT_TRUE(NS_SUCCEEDED(rv));
   751   }
   753   void AddStream(const std::string& name, int components) {
   754     Init(false);
   755     p1_->AddStream(components);
   756     p2_->AddStream(components);
   757   }
   759   void Init(bool set_priorities) {
   760     if (!initted_) {
   761       p1_ = new IceTestPeer("P1", true, set_priorities);
   762       p2_ = new IceTestPeer("P2", false, set_priorities);
   763     }
   764     initted_ = true;
   765   }
   767   bool Gather(bool wait) {
   768     Init(false);
   769     p1_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
   770     p2_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
   771     p1_->Gather();
   772     p2_->Gather();
   774     if (wait) {
   775       EXPECT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
   776       if (!p1_->gathering_complete())
   777         return false;
   778       EXPECT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
   779       if (!p2_->gathering_complete())
   780         return false;
   781     }
   782     return true;
   783   }
   785   void SetTurnServer(const std::string addr, uint16_t port,
   786                      const std::string username,
   787                      const std::string password,
   788                      const char* transport = kNrIceTransportUdp) {
   789     p1_->SetTurnServer(addr, port, username, password, transport);
   790     p2_->SetTurnServer(addr, port, username, password, transport);
   791   }
   793   void SetTurnServers(const std::vector<NrIceTurnServer>& servers) {
   794     p1_->SetTurnServers(servers);
   795     p2_->SetTurnServers(servers);
   796   }
   798   void SetCandidateFilter(CandidateFilter filter, bool both=true) {
   799     p1_->SetCandidateFilter(filter);
   800     if (both) {
   801       p2_->SetCandidateFilter(filter);
   802     }
   803   }
   805   void Connect() {
   806     p1_->Connect(p2_, TRICKLE_NONE);
   807     p2_->Connect(p1_, TRICKLE_NONE);
   809     ASSERT_TRUE_WAIT(p1_->ready_ct() == 1 && p2_->ready_ct() == 1,
   810                      kDefaultTimeout);
   811     ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
   812                      kDefaultTimeout);
   814     p1_->DumpAndCheckActiveCandidates();
   815     p2_->DumpAndCheckActiveCandidates();
   816   }
   818   void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote,
   819                         std::string transport = kNrIceTransportUdp) {
   820     p1_->SetExpectedTypes(local, remote, transport);
   821     p2_->SetExpectedTypes(local, remote, transport);
   822   }
   824   void SetExpectedTypes(NrIceCandidate::Type local1, NrIceCandidate::Type remote1,
   825                         NrIceCandidate::Type local2, NrIceCandidate::Type remote2) {
   826     p1_->SetExpectedTypes(local1, remote1);
   827     p2_->SetExpectedTypes(local2, remote2);
   828   }
   830   void ConnectP1(TrickleMode mode = TRICKLE_NONE) {
   831     p1_->Connect(p2_, mode);
   832   }
   834   void ConnectP2(TrickleMode mode = TRICKLE_NONE) {
   835     p2_->Connect(p1_, mode);
   836   }
   838   void WaitForComplete(int expected_streams = 1) {
   839     ASSERT_TRUE_WAIT(p1_->ready_ct() == expected_streams &&
   840                      p2_->ready_ct() == expected_streams, kDefaultTimeout);
   841     ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(),
   842                      kDefaultTimeout);
   843   }
   845   void WaitForGather() {
   846     ASSERT_TRUE_WAIT(p1_->gathering_complete(), kDefaultTimeout);
   847     ASSERT_TRUE_WAIT(p2_->gathering_complete(), kDefaultTimeout);
   848   }
   850   void ConnectTrickle(TrickleMode trickle = TRICKLE_SIMULATE) {
   851     p1_->Connect(p2_, trickle);
   852     p2_->Connect(p1_, trickle);
   853   }
   855   void SimulateTrickle(size_t stream) {
   856     p1_->SimulateTrickle(stream);
   857     p2_->SimulateTrickle(stream);
   858     ASSERT_TRUE_WAIT(p1_->is_ready(stream), kDefaultTimeout);
   859     ASSERT_TRUE_WAIT(p2_->is_ready(stream), kDefaultTimeout);
   860   }
   862   void SimulateTrickleP1(size_t stream) {
   863     p1_->SimulateTrickle(stream);
   864   }
   866   void SimulateTrickleP2(size_t stream) {
   867     p2_->SimulateTrickle(stream);
   868   }
   870   void VerifyConnected() {
   871   }
   873   void CloseP1() {
   874     p1_->Close();
   875   }
   877   void ConnectThenDelete() {
   878     p1_->Connect(p2_, TRICKLE_NONE, true);
   879     p2_->Connect(p1_, TRICKLE_NONE, false);
   880     test_utils->sts_target()->Dispatch(WrapRunnable(this,
   881                                                     &IceConnectTest::CloseP1),
   882                                        NS_DISPATCH_SYNC);
   883     p2_->StartChecks();
   885     // Wait to see if we crash
   886     PR_Sleep(PR_MillisecondsToInterval(kDefaultTimeout));
   887   }
   889   void SendReceive() {
   890     //    p1_->Send(2);
   891     test_utils->sts_target()->Dispatch(
   892         WrapRunnable(p1_.get(),
   893                      &IceTestPeer::SendPacket, 0, 1,
   894                      reinterpret_cast<const unsigned char *>("TEST"), 4),
   895         NS_DISPATCH_SYNC);
   896     ASSERT_EQ(1u, p1_->sent());
   897     ASSERT_TRUE_WAIT(p2_->received() == 1, 1000);
   898   }
   900  protected:
   901   bool initted_;
   902   nsCOMPtr<nsIEventTarget> target_;
   903   mozilla::ScopedDeletePtr<IceTestPeer> p1_;
   904   mozilla::ScopedDeletePtr<IceTestPeer> p2_;
   905 };
   907 class PrioritizerTest : public ::testing::Test {
   908  public:
   909   PrioritizerTest():
   910     prioritizer_(nullptr) {}
   912   ~PrioritizerTest() {
   913     if (prioritizer_) {
   914       nr_interface_prioritizer_destroy(&prioritizer_);
   915     }
   916   }
   918   void SetPriorizer(nr_interface_prioritizer *prioritizer) {
   919     prioritizer_ = prioritizer;
   920   }
   922   void AddInterface(const std::string& num, int type, int estimated_speed) {
   923     std::string str_addr = "10.0.0." + num;
   924     std::string ifname = "eth" + num;
   925     nr_local_addr local_addr;
   926     local_addr.interface.type = type;
   927     local_addr.interface.estimated_speed = estimated_speed;
   929     int r = nr_ip4_str_port_to_transport_addr(str_addr.c_str(), 0,
   930                                               IPPROTO_UDP, &(local_addr.addr));
   931     ASSERT_EQ(0, r);
   932     strncpy(local_addr.addr.ifname, ifname.c_str(), MAXIFNAME);
   934     r = nr_interface_prioritizer_add_interface(prioritizer_, &local_addr);
   935     ASSERT_EQ(0, r);
   936     r = nr_interface_prioritizer_sort_preference(prioritizer_);
   937     ASSERT_EQ(0, r);
   938   }
   940   void HasLowerPreference(const std::string& num1, const std::string& num2) {
   941     std::string key1 = "eth" + num1 + ":10.0.0." + num1;
   942     std::string key2 = "eth" + num2 + ":10.0.0." + num2;
   943     UCHAR pref1, pref2;
   944     int r = nr_interface_prioritizer_get_priority(prioritizer_, key1.c_str(), &pref1);
   945     ASSERT_EQ(0, r);
   946     r = nr_interface_prioritizer_get_priority(prioritizer_, key2.c_str(), &pref2);
   947     ASSERT_EQ(0, r);
   948     ASSERT_LE(pref1, pref2);
   949   }
   951  private:
   952   nr_interface_prioritizer *prioritizer_;
   953 };
   955 class PacketFilterTest : public ::testing::Test {
   956  public:
   957   PacketFilterTest(): filter_(nullptr) {}
   959   void SetUp() {
   960     nsCOMPtr<nsIUDPSocketFilterHandler> handler =
   961       do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID);
   962     handler->NewFilter(getter_AddRefs(filter_));
   963   }
   965   void TestIncoming(const uint8_t* data, uint32_t len,
   966                     uint8_t from_addr, int from_port,
   967                     bool expected_result) {
   968     mozilla::net::NetAddr addr;
   969     MakeNetAddr(&addr, from_addr, from_port);
   970     bool result;
   971     nsresult rv = filter_->FilterPacket(&addr, data, len,
   972                                         nsIUDPSocketFilter::SF_INCOMING,
   973                                         &result);
   974     ASSERT_EQ(NS_OK, rv);
   975     ASSERT_EQ(expected_result, result);
   976   }
   978   void TestOutgoing(const uint8_t* data, uint32_t len,
   979                     uint8_t to_addr, int to_port,
   980                     bool expected_result) {
   981     mozilla::net::NetAddr addr;
   982     MakeNetAddr(&addr, to_addr, to_port);
   983     bool result;
   984     nsresult rv = filter_->FilterPacket(&addr, data, len,
   985                                         nsIUDPSocketFilter::SF_OUTGOING,
   986                                         &result);
   987     ASSERT_EQ(NS_OK, rv);
   988     ASSERT_EQ(expected_result, result);
   989   }
   991  private:
   992   void MakeNetAddr(mozilla::net::NetAddr* net_addr,
   993                    uint8_t last_digit, uint16_t port) {
   994     net_addr->inet.family = AF_INET;
   995     net_addr->inet.ip = 192 << 24 | 168 << 16 | 1 << 8 | last_digit;
   996     net_addr->inet.port = port;
   997   }
   999   nsCOMPtr<nsIUDPSocketFilter> filter_;
  1000 };
  1001 }  // end namespace
  1003 TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
  1004   peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
  1005   Gather();
  1008 TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
  1009   peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
  1010   peer_->SetFakeResolver();
  1011   Gather();
  1014 TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
  1015   peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
  1016   peer_->SetFakeResolver();
  1017   Gather();
  1020 TEST_F(IceGatherTest, TestGatherFakeStunBogusHostname) {
  1021   peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
  1022   peer_->SetFakeResolver();
  1023   Gather();
  1026 TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
  1027   peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
  1028   peer_->SetDNSResolver();
  1029   Gather();
  1030   // TODO(jib@mozilla.com): ensure we get server reflexive candidates Bug 848094
  1033 TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
  1034   peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
  1035   peer_->SetDNSResolver();
  1036   Gather();
  1039 TEST_F(IceGatherTest, TestGatherDNSStunBogusHostname) {
  1040   peer_->SetStunServer(kBogusStunServerHostname, kDefaultStunServerPort);
  1041   peer_->SetDNSResolver();
  1042   Gather();
  1045 TEST_F(IceGatherTest, TestGatherTurn) {
  1046   if (g_turn_server.empty())
  1047     return;
  1048   peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1049                        g_turn_user, g_turn_password, kNrIceTransportUdp);
  1050   Gather();
  1053 TEST_F(IceGatherTest, TestGatherTurnTcp) {
  1054   if (g_turn_server.empty())
  1055     return;
  1056   peer_->SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1057                        g_turn_user, g_turn_password, kNrIceTransportTcp);
  1058   Gather();
  1061 TEST_F(IceGatherTest, TestGatherDisableComponent) {
  1062   peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
  1063   peer_->AddStream(2);
  1064   peer_->DisableComponent(1, 2);
  1065   Gather();
  1066   std::vector<std::string> candidates =
  1067     peer_->GetCandidates(1);
  1069   for (size_t i=0; i<candidates.size(); ++i) {
  1070     size_t sp1 = candidates[i].find(' ');
  1071     ASSERT_EQ(0, candidates[i].compare(sp1+1, 1, "1", 1));
  1076 // Verify that a bogus candidate doesn't cause crashes on the
  1077 // main thread. See bug 856433.
  1078 TEST_F(IceGatherTest, TestBogusCandidate) {
  1079   Gather();
  1080   peer_->ParseCandidate(0, kBogusIceCandidate);
  1083 TEST_F(IceGatherTest, VerifyTestStunServer) {
  1084   UseFakeStunServerWithResponse("192.0.2.133", 3333);
  1085   Gather();
  1086   ASSERT_TRUE(StreamHasMatchingCandidate(0, " 192.0.2.133 3333 "));
  1089 TEST_F(IceGatherTest, TestStunServerReturnsWildcardAddr) {
  1090   UseFakeStunServerWithResponse("0.0.0.0", 3333);
  1091   Gather();
  1092   ASSERT_FALSE(StreamHasMatchingCandidate(0, " 0.0.0.0 "));
  1095 TEST_F(IceGatherTest, TestStunServerReturnsPort0) {
  1096   UseFakeStunServerWithResponse("192.0.2.133", 0);
  1097   Gather();
  1098   ASSERT_FALSE(StreamHasMatchingCandidate(0, " 192.0.2.133 0 "));
  1101 TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
  1102   UseFakeStunServerWithResponse("127.0.0.133", 3333);
  1103   Gather();
  1104   ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
  1107 TEST_F(IceGatherTest, TestStunServerTrickle) {
  1108   UseFakeStunServerWithResponse("192.0.2.1", 3333);
  1109   TestStunServer::GetInstance()->SetActive(false);
  1110   Gather(false);
  1111   ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
  1112   TestStunServer::GetInstance()->SetActive(true);
  1113   WaitForGather();
  1114   ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
  1117 TEST_F(IceConnectTest, TestGather) {
  1118   AddStream("first", 1);
  1119   ASSERT_TRUE(Gather(true));
  1122 TEST_F(IceConnectTest, TestGatherAutoPrioritize) {
  1123   Init(false);
  1124   AddStream("first", 1);
  1125   ASSERT_TRUE(Gather(true));
  1129 TEST_F(IceConnectTest, TestConnect) {
  1130   AddStream("first", 1);
  1131   ASSERT_TRUE(Gather(true));
  1132   Connect();
  1135 TEST_F(IceConnectTest, TestConnectTwoComponents) {
  1136   AddStream("first", 2);
  1137   ASSERT_TRUE(Gather(true));
  1138   Connect();
  1141 TEST_F(IceConnectTest, TestConnectTwoComponentsDisableSecond) {
  1142   AddStream("first", 2);
  1143   ASSERT_TRUE(Gather(true));
  1144   p1_->DisableComponent(0, 2);
  1145   p2_->DisableComponent(0, 2);
  1146   Connect();
  1150 TEST_F(IceConnectTest, TestConnectP2ThenP1) {
  1151   AddStream("first", 1);
  1152   ASSERT_TRUE(Gather(true));
  1153   ConnectP2();
  1154   PR_Sleep(1000);
  1155   ConnectP1();
  1156   WaitForComplete();
  1159 TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
  1160   AddStream("first", 1);
  1161   ASSERT_TRUE(Gather(true));
  1162   ConnectP2();
  1163   PR_Sleep(1000);
  1164   ConnectP1(TRICKLE_SIMULATE);
  1165   SimulateTrickleP1(0);
  1166   WaitForComplete();
  1169 TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
  1170   AddStream("first", 1);
  1171   AddStream("second", 2);
  1172   ASSERT_TRUE(Gather(true));
  1173   ConnectP2();
  1174   PR_Sleep(1000);
  1175   ConnectP1(TRICKLE_SIMULATE);
  1176   SimulateTrickleP1(0);
  1177   std::cerr << "Sleeping between trickle streams" << std::endl;
  1178   PR_Sleep(1000);  // Give this some time to settle but not complete
  1179                    // all of ICE.
  1180   SimulateTrickleP1(1);
  1181   WaitForComplete(2);
  1184 TEST_F(IceConnectTest, TestConnectAutoPrioritize) {
  1185   Init(false);
  1186   AddStream("first", 1);
  1187   ASSERT_TRUE(Gather(true));
  1188   Connect();
  1191 TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
  1192   AddStream("first", 1);
  1193   ASSERT_TRUE(Gather(true));
  1194   ConnectTrickle();
  1195   SimulateTrickle(0);
  1196   ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
  1197   ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
  1200 TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
  1201   AddStream("first", 1);
  1202   AddStream("second", 1);
  1203   ASSERT_TRUE(Gather(true));
  1204   ConnectTrickle();
  1205   SimulateTrickle(0);
  1206   SimulateTrickle(1);
  1207   ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
  1208   ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
  1211 TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
  1212   AddStream("first", 1);
  1213   AddStream("second", 1);
  1214   ASSERT_TRUE(Gather(false));
  1215   ConnectTrickle(TRICKLE_REAL);
  1216   ASSERT_TRUE_WAIT(p1_->ice_complete(), kDefaultTimeout);
  1217   ASSERT_TRUE_WAIT(p2_->ice_complete(), kDefaultTimeout);
  1218   WaitForGather();  // ICE can complete before we finish gathering.
  1221 TEST_F(IceConnectTest, TestSendReceive) {
  1222   AddStream("first", 1);
  1223   ASSERT_TRUE(Gather(true));
  1224   Connect();
  1225   SendReceive();
  1228 TEST_F(IceConnectTest, TestConnectTurn) {
  1229   if (g_turn_server.empty())
  1230     return;
  1232   AddStream("first", 1);
  1233   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1234                 g_turn_user, g_turn_password);
  1235   ASSERT_TRUE(Gather(true));
  1236   Connect();
  1239 TEST_F(IceConnectTest, TestConnectTurnTcp) {
  1240   if (g_turn_server.empty())
  1241     return;
  1243   AddStream("first", 1);
  1244   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1245                 g_turn_user, g_turn_password, kNrIceTransportTcp);
  1246   ASSERT_TRUE(Gather(true));
  1247   Connect();
  1250 TEST_F(IceConnectTest, TestConnectTurnOnly) {
  1251   if (g_turn_server.empty())
  1252     return;
  1254   AddStream("first", 1);
  1255   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1256                 g_turn_user, g_turn_password);
  1257   ASSERT_TRUE(Gather(true));
  1258   SetCandidateFilter(IsRelayCandidate);
  1259   SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
  1260                    NrIceCandidate::Type::ICE_RELAYED);
  1261   Connect();
  1264 TEST_F(IceConnectTest, TestConnectTurnTcpOnly) {
  1265   if (g_turn_server.empty())
  1266     return;
  1268   AddStream("first", 1);
  1269   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1270                 g_turn_user, g_turn_password, kNrIceTransportTcp);
  1271   ASSERT_TRUE(Gather(true));
  1272   SetCandidateFilter(IsRelayCandidate);
  1273   SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
  1274                    NrIceCandidate::Type::ICE_RELAYED,
  1275                    kNrIceTransportTcp);
  1276   Connect();
  1279 TEST_F(IceConnectTest, TestSendReceiveTurnOnly) {
  1280   if (g_turn_server.empty())
  1281     return;
  1283   AddStream("first", 1);
  1284   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1285                 g_turn_user, g_turn_password);
  1286   ASSERT_TRUE(Gather(true));
  1287   SetCandidateFilter(IsRelayCandidate);
  1288   SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
  1289                    NrIceCandidate::Type::ICE_RELAYED);
  1290   Connect();
  1291   SendReceive();
  1294 TEST_F(IceConnectTest, TestSendReceiveTurnTcpOnly) {
  1295   if (g_turn_server.empty())
  1296     return;
  1298   AddStream("first", 1);
  1299   SetTurnServer(g_turn_server, kDefaultStunServerPort,
  1300                 g_turn_user, g_turn_password, kNrIceTransportTcp);
  1301   ASSERT_TRUE(Gather(true));
  1302   SetCandidateFilter(IsRelayCandidate);
  1303   SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
  1304                    NrIceCandidate::Type::ICE_RELAYED,
  1305                    kNrIceTransportTcp);
  1306   Connect();
  1307   SendReceive();
  1310 TEST_F(IceConnectTest, TestSendReceiveTurnBothOnly) {
  1311   if (g_turn_server.empty())
  1312     return;
  1314   AddStream("first", 1);
  1315   std::vector<NrIceTurnServer> turn_servers;
  1316   std::vector<unsigned char> password_vec(g_turn_password.begin(),
  1317                                           g_turn_password.end());
  1318   turn_servers.push_back(*NrIceTurnServer::Create(
  1319                            g_turn_server, kDefaultStunServerPort,
  1320                            g_turn_user, password_vec, kNrIceTransportTcp));
  1321   turn_servers.push_back(*NrIceTurnServer::Create(
  1322                            g_turn_server, kDefaultStunServerPort,
  1323                            g_turn_user, password_vec, kNrIceTransportUdp));
  1324   SetTurnServers(turn_servers);
  1325   ASSERT_TRUE(Gather(true));
  1326   SetCandidateFilter(IsRelayCandidate);
  1327   // UDP is preferred.
  1328   SetExpectedTypes(NrIceCandidate::Type::ICE_RELAYED,
  1329                    NrIceCandidate::Type::ICE_RELAYED,
  1330                    kNrIceTransportUdp);
  1331   Connect();
  1332   SendReceive();
  1335 TEST_F(IceConnectTest, TestConnectShutdownOneSide) {
  1336   AddStream("first", 1);
  1337   ASSERT_TRUE(Gather(true));
  1338   ConnectThenDelete();
  1341 TEST_F(IceConnectTest, TestPollCandPairsBeforeConnect) {
  1342   AddStream("first", 1);
  1343   ASSERT_TRUE(Gather(true));
  1345   std::vector<NrIceCandidatePair> pairs;
  1346   nsresult res = p1_->GetCandidatePairs(0, &pairs);
  1347   // There should be no candidate pairs prior to calling Connect()
  1348   ASSERT_TRUE(NS_FAILED(res));
  1349   ASSERT_EQ(0U, pairs.size());
  1351   res = p2_->GetCandidatePairs(0, &pairs);
  1352   ASSERT_TRUE(NS_FAILED(res));
  1353   ASSERT_EQ(0U, pairs.size());
  1356 TEST_F(IceConnectTest, TestPollCandPairsAfterConnect) {
  1357   AddStream("first", 1);
  1358   ASSERT_TRUE(Gather(true));
  1359   Connect();
  1361   std::vector<NrIceCandidatePair> pairs;
  1362   nsresult r = p1_->GetCandidatePairs(0, &pairs);
  1363   ASSERT_EQ(NS_OK, r);
  1364   // How detailed of a check do we want to do here? If the turn server is
  1365   // functioning, we'll get at least two pairs, but this is probably not
  1366   // something we should assume.
  1367   ASSERT_NE(0U, pairs.size());
  1368   ASSERT_TRUE(p1_->CandidatePairsPriorityDescending(pairs));
  1369   ASSERT_TRUE(ContainsSucceededPair(pairs));
  1370   pairs.clear();
  1372   r = p2_->GetCandidatePairs(0, &pairs);
  1373   ASSERT_EQ(NS_OK, r);
  1374   ASSERT_NE(0U, pairs.size());
  1375   ASSERT_TRUE(p2_->CandidatePairsPriorityDescending(pairs));
  1376   ASSERT_TRUE(ContainsSucceededPair(pairs));
  1379 TEST_F(IceConnectTest, TestPollCandPairsDuringConnect) {
  1380   AddStream("first", 1);
  1381   ASSERT_TRUE(Gather(true));
  1383   p1_->Connect(p2_, TRICKLE_NONE, false);
  1384   p2_->Connect(p1_, TRICKLE_NONE, false);
  1386   std::vector<NrIceCandidatePair> pairs1;
  1387   std::vector<NrIceCandidatePair> pairs2;
  1389   p1_->StartChecks();
  1390   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1391   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1393   p2_->StartChecks();
  1394   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1395   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1397   WaitForComplete();
  1398   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1399   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1400   ASSERT_TRUE(ContainsSucceededPair(pairs1));
  1401   ASSERT_TRUE(ContainsSucceededPair(pairs2));
  1404 TEST_F(IceConnectTest, TestRLogRingBuffer) {
  1405   RLogRingBuffer::CreateInstance();
  1406   AddStream("first", 1);
  1407   ASSERT_TRUE(Gather(true));
  1409   p1_->Connect(p2_, TRICKLE_NONE, false);
  1410   p2_->Connect(p1_, TRICKLE_NONE, false);
  1412   std::vector<NrIceCandidatePair> pairs1;
  1413   std::vector<NrIceCandidatePair> pairs2;
  1415   p1_->StartChecks();
  1416   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1417   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1419   p2_->StartChecks();
  1420   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1421   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1423   WaitForComplete();
  1424   p1_->UpdateAndValidateCandidatePairs(0, &pairs1);
  1425   p2_->UpdateAndValidateCandidatePairs(0, &pairs2);
  1426   ASSERT_TRUE(ContainsSucceededPair(pairs1));
  1427   ASSERT_TRUE(ContainsSucceededPair(pairs2));
  1429   for (auto p = pairs1.begin(); p != pairs1.end(); ++p) {
  1430     std::deque<std::string> logs;
  1431     std::string substring("CAND-PAIR(");
  1432     substring += p->codeword;
  1433     RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
  1434     ASSERT_NE(0U, logs.size());
  1437   for (auto p = pairs2.begin(); p != pairs2.end(); ++p) {
  1438     std::deque<std::string> logs;
  1439     std::string substring("CAND-PAIR(");
  1440     substring += p->codeword;
  1441     RLogRingBuffer::GetInstance()->Filter(substring, 0, &logs);
  1442     ASSERT_NE(0U, logs.size());
  1445   RLogRingBuffer::DestroyInstance();
  1448 TEST_F(PrioritizerTest, TestPrioritizer) {
  1449   SetPriorizer(::mozilla::CreateInterfacePrioritizer());
  1451   AddInterface("0", NR_INTERFACE_TYPE_VPN, 100); // unknown vpn
  1452   AddInterface("1", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIRED, 100); // wired vpn
  1453   AddInterface("2", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_WIFI, 100); // wifi vpn
  1454   AddInterface("3", NR_INTERFACE_TYPE_VPN | NR_INTERFACE_TYPE_MOBILE, 100); // wifi vpn
  1455   AddInterface("4", NR_INTERFACE_TYPE_WIRED, 1000); // wired, high speed
  1456   AddInterface("5", NR_INTERFACE_TYPE_WIRED, 10); // wired, low speed
  1457   AddInterface("6", NR_INTERFACE_TYPE_WIFI, 10); // wifi, low speed
  1458   AddInterface("7", NR_INTERFACE_TYPE_WIFI, 1000); // wifi, high speed
  1459   AddInterface("8", NR_INTERFACE_TYPE_MOBILE, 10); // mobile, low speed
  1460   AddInterface("9", NR_INTERFACE_TYPE_MOBILE, 1000); // mobile, high speed
  1461   AddInterface("10", NR_INTERFACE_TYPE_UNKNOWN, 10); // unknown, low speed
  1462   AddInterface("11", NR_INTERFACE_TYPE_UNKNOWN, 1000); // unknown, high speed
  1464   // expected preference "4" > "5" > "1" > "7" > "6" > "2" > "9" > "8" > "3" > "11" > "10" > "0"
  1466   HasLowerPreference("0", "10");
  1467   HasLowerPreference("10", "11");
  1468   HasLowerPreference("11", "3");
  1469   HasLowerPreference("3", "8");
  1470   HasLowerPreference("8", "9");
  1471   HasLowerPreference("9", "2");
  1472   HasLowerPreference("2", "6");
  1473   HasLowerPreference("6", "7");
  1474   HasLowerPreference("7", "1");
  1475   HasLowerPreference("1", "5");
  1476   HasLowerPreference("5", "4");
  1479 TEST_F(PacketFilterTest, TestSendNonStunPacket) {
  1480   const unsigned char data[] = "12345abcde";
  1481   TestOutgoing(data, sizeof(data), 123, 45, false);
  1484 TEST_F(PacketFilterTest, TestRecvNonStunPacket) {
  1485   const unsigned char data[] = "12345abcde";
  1486   TestIncoming(data, sizeof(data), 123, 45, false);
  1489 TEST_F(PacketFilterTest, TestSendStunPacket) {
  1490   nr_stun_message *msg;
  1491   ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
  1492   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1493   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1494   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1495   ASSERT_EQ(0, nr_stun_message_destroy(&msg));
  1498 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingId) {
  1499   nr_stun_message *msg;
  1500   ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
  1502   msg->header.id.octet[0] = 1;
  1503   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1504   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1505   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1507   msg->header.id.octet[0] = 0;
  1508   msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
  1509   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1510   TestIncoming(msg->buffer, msg->length, 123, 45, true);
  1512   ASSERT_EQ(0, nr_stun_message_destroy(&msg));
  1515 TEST_F(PacketFilterTest, TestRecvStunPacketWithoutAPendingAddress) {
  1516   nr_stun_message *msg;
  1517   ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
  1519   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1520   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1521   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1523   msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
  1524   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1525   TestIncoming(msg->buffer, msg->length, 123, 46, false);
  1526   TestIncoming(msg->buffer, msg->length, 124, 45, false);
  1528   ASSERT_EQ(0, nr_stun_message_destroy(&msg));
  1531 TEST_F(PacketFilterTest, TestRecvStunPacketWithPendingIdAndAddress) {
  1532   nr_stun_message *msg;
  1533   ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
  1535   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1536   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1537   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1539   msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
  1540   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1541   TestIncoming(msg->buffer, msg->length, 123, 45, true);
  1543   // Test whitelist by filtering non-stun packets.
  1544   const unsigned char data[] = "12345abcde";
  1546   // 123:45 is white-listed.
  1547   TestOutgoing(data, sizeof(data), 123, 45, true);
  1548   TestIncoming(data, sizeof(data), 123, 45, true);
  1550   // Indications pass as well.
  1551   msg->header.type = NR_STUN_MSG_BINDING_INDICATION;
  1552   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1553   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1554   TestIncoming(msg->buffer, msg->length, 123, 45, true);
  1556   // Packets from and to other address are still disallowed.
  1557   TestOutgoing(data, sizeof(data), 123, 46, false);
  1558   TestIncoming(data, sizeof(data), 123, 46, false);
  1559   TestOutgoing(data, sizeof(data), 124, 45, false);
  1560   TestIncoming(data, sizeof(data), 124, 45, false);
  1562   ASSERT_EQ(0, nr_stun_message_destroy(&msg));
  1565 TEST_F(PacketFilterTest, TestSendNonRequestStunPacket) {
  1566   nr_stun_message *msg;
  1567   ASSERT_EQ(0, nr_stun_build_req_no_auth(NULL, &msg));
  1569   msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
  1570   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1571   TestOutgoing(msg->buffer, msg->length, 123, 45, false);
  1573   // Send a packet so we allow the incoming request.
  1574   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1575   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1576   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1578   // This packet makes us able to send a response.
  1579   msg->header.type = NR_STUN_MSG_BINDING_REQUEST;
  1580   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1581   TestIncoming(msg->buffer, msg->length, 123, 45, true);
  1583   msg->header.type = NR_STUN_MSG_BINDING_RESPONSE;
  1584   ASSERT_EQ(0, nr_stun_encode_message(msg));
  1585   TestOutgoing(msg->buffer, msg->length, 123, 45, true);
  1587   ASSERT_EQ(0, nr_stun_message_destroy(&msg));
  1590 static std::string get_environment(const char *name) {
  1591   char *value = getenv(name);
  1593   if (!value)
  1594     return "";
  1596   return value;
  1599 int main(int argc, char **argv)
  1601 #ifdef LINUX
  1602   // This test can cause intermittent oranges on the builders on Linux
  1603   CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_TESTS")
  1604 #endif
  1606   g_turn_server = get_environment("TURN_SERVER_ADDRESS");
  1607   g_turn_user = get_environment("TURN_SERVER_USER");
  1608   g_turn_password = get_environment("TURN_SERVER_PASSWORD");
  1610   if (g_turn_server.empty() ||
  1611       g_turn_user.empty(),
  1612       g_turn_password.empty()) {
  1613     printf(
  1614         "Set TURN_SERVER_ADDRESS, TURN_SERVER_USER, and TURN_SERVER_PASSWORD\n"
  1615         "environment variables to run this test\n");
  1616     g_turn_server="";
  1619   std::string tmp = get_environment("STUN_SERVER_ADDRESS");
  1620   if (tmp != "")
  1621     g_stun_server_address = tmp;
  1624   tmp = get_environment("STUN_SERVER_HOSTNAME");
  1625   if (tmp != "")
  1626     g_stun_server_hostname = tmp;
  1628   test_utils = new MtransportTestUtils();
  1629   NSS_NoDB_Init(nullptr);
  1630   NSS_SetDomesticPolicy();
  1632   // Start the tests
  1633   ::testing::InitGoogleTest(&argc, argv);
  1635   ::testing::TestEventListeners& listeners =
  1636         ::testing::UnitTest::GetInstance()->listeners();
  1637   // Adds a listener to the end.  Google Test takes the ownership.
  1639   listeners.Append(new test::RingbufferDumper(test_utils));
  1640   test_utils->sts_target()->Dispatch(
  1641     WrapRunnableNM(&TestStunServer::GetInstance), NS_DISPATCH_SYNC);
  1643   int rv = RUN_ALL_TESTS();
  1645   test_utils->sts_target()->Dispatch(
  1646     WrapRunnableNM(&TestStunServer::ShutdownInstance), NS_DISPATCH_SYNC);
  1648   delete test_utils;
  1649   return rv;

mercurial