diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index e7d3d52efa46..1a721e10a624 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -231,8 +231,12 @@ skip-if = toolkit == 'android' skip-if = toolkit == 'android' [test_peerConnection_restartIceLocalRollback.html] skip-if = toolkit == 'android' +[test_peerConnection_restartIceLocalRollbackNoSubsequentRestart.html] +skip-if = toolkit == 'android' [test_peerConnection_restartIceLocalAndRemoteRollback.html] skip-if = toolkit == 'android' +[test_peerConnection_restartIceLocalAndRemoteRollbackNoSubsequentRestart.html] +skip-if = toolkit == 'android' [test_peerConnection_restartIceBadAnswer.html] skip-if = toolkit == 'android' [test_peerConnection_scaleResolution.html] diff --git a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html index d2280cee87be..1f2b1be9b8f4 100644 --- a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html @@ -64,13 +64,13 @@ STABLE); }, - // Rolling back should shut down gathering + // Rolling back should shut down gathering for the offerer, + // but because the answerer never set a local description, no ICE + // gathering has happened yet, so there's no changes to ICE gathering + // state function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) { return test.pcLocal.endOfTrickleIce; }, - function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) { - return test.pcRemote.endOfTrickleIce; - }, function PC_LOCAL_EXPECT_ICE_CHECKING(test) { test.pcLocal.expectIceChecking(); diff --git a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollbackNoSubsequentRestart.html b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollbackNoSubsequentRestart.html new file mode 100644 index 000000000000..15838b279d1e --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollbackNoSubsequentRestart.html @@ -0,0 +1,86 @@ + + + + + + +
+
+
+ + diff --git a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollbackNoSubsequentRestart.html b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollbackNoSubsequentRestart.html new file mode 100644 index 000000000000..b1b805becc5b --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollbackNoSubsequentRestart.html @@ -0,0 +1,66 @@ + + + + + + +
+
+
+ + diff --git a/media/mtransport/common.build b/media/mtransport/common.build index dfd8d165665b..c1d694fc94fc 100644 --- a/media/mtransport/common.build +++ b/media/mtransport/common.build @@ -10,7 +10,6 @@ mtransport_lcppsrcs = [ 'nr_socket_prsock.cpp', 'nr_timer.cpp', 'nricectx.cpp', - 'nricectxhandler.cpp', 'nricemediastream.cpp', 'nriceresolver.cpp', 'nriceresolverfake.cpp', diff --git a/media/mtransport/nricectx.cpp b/media/mtransport/nricectx.cpp index 70a706399885..da15dc1ab588 100644 --- a/media/mtransport/nricectx.cpp +++ b/media/mtransport/nricectx.cpp @@ -291,18 +291,68 @@ NrIceCtx::NrIceCtx(const std::string& name, Policy policy) nat_ (nullptr) { } +/* static */ +RefPtr +NrIceCtx::Create(const std::string& name, + bool allow_loopback, + bool tcp_enabled, + bool allow_link_local, + Policy policy) +{ + // InitializeGlobals only executes once + NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local); + + RefPtr ctx = new NrIceCtx(name, policy); + + if (!ctx->Initialize()) { + return nullptr; + } + + return ctx; +} + +RefPtr +NrIceCtx::CreateStream(const std::string& id, + const std::string& name, + int components) +{ + if (streams_.count(id)) { + MOZ_ASSERT(false); + return nullptr; + } + + RefPtr stream = + new NrIceMediaStream(this, id, name, components); + streams_[id] = stream; + return stream; +} + +void +NrIceCtx::DestroyStream(const std::string& id) { + auto it = streams_.find(id); + if (it != streams_.end()) { + auto preexisting_stream = it->second; + streams_.erase(it); + preexisting_stream->Close(); + } +} + // Handler callbacks int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream, int component_id, nr_ice_cand_pair **potentials, int potential_ct) { MOZ_MTLOG(ML_DEBUG, "select pair called: potential_ct = " << potential_ct); + MOZ_ASSERT(stream->local_stream); + MOZ_ASSERT(!stream->local_stream->obsolete); return 0; } int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) { MOZ_MTLOG(ML_DEBUG, "stream_ready called"); + MOZ_ASSERT(!stream->local_stream); + MOZ_ASSERT(!stream->obsolete); // Get the ICE ctx. NrIceCtx *ctx = static_cast(obj); @@ -319,6 +369,8 @@ int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) { int NrIceCtx::stream_failed(void *obj, nr_ice_media_stream *stream) { MOZ_MTLOG(ML_DEBUG, "stream_failed called"); + MOZ_ASSERT(!stream->local_stream); + MOZ_ASSERT(!stream->obsolete); // Get the ICE ctx NrIceCtx *ctx = static_cast(obj); @@ -328,7 +380,7 @@ int NrIceCtx::stream_failed(void *obj, nr_ice_media_stream *stream) { MOZ_ASSERT(s); ctx->SetConnectionState(ICE_CTX_FAILED); - s -> SignalFailed(s); + s -> Failed(); return 0; } @@ -387,6 +439,7 @@ void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx, nr_ice_media_stream *stream, int component_id, nr_ice_candidate *candidate) { + MOZ_ASSERT(!stream->obsolete); // Get the ICE ctx NrIceCtx *ctx = static_cast(arg); RefPtr s = ctx->FindStream(stream); @@ -488,40 +541,6 @@ NrIceCtx::InitializeGlobals(bool allow_loopback, } } -std::string -NrIceCtx::GetNewUfrag() -{ - char* ufrag; - int r; - - if ((r=nr_ice_get_new_ice_ufrag(&ufrag))) { - MOZ_CRASH("Unable to get new ice ufrag"); - return ""; - } - - std::string ufragStr = ufrag; - RFREE(ufrag); - - return ufragStr; -} - -std::string -NrIceCtx::GetNewPwd() -{ - char* pwd; - int r; - - if ((r=nr_ice_get_new_ice_pwd(&pwd))) { - MOZ_CRASH("Unable to get new ice pwd"); - return ""; - } - - std::string pwdStr = pwd; - RFREE(pwd); - - return pwdStr; -} - #define MAXADDRS 100 // mirrors setting in ice_ctx.c /* static */ @@ -570,22 +589,6 @@ NrIceCtx::SetStunAddrs(const nsTArray& addrs) bool NrIceCtx::Initialize() { - std::string ufrag = GetNewUfrag(); - std::string pwd = GetNewPwd(); - - return Initialize(ufrag, pwd); -} - -bool -NrIceCtx::Initialize(const std::string& ufrag, - const std::string& pwd) -{ - MOZ_ASSERT(!ufrag.empty()); - MOZ_ASSERT(!pwd.empty()); - if (ufrag.empty() || pwd.empty()) { - return false; - } - // Create the ICE context int r; @@ -601,13 +604,7 @@ NrIceCtx::Initialize(const std::string& ufrag, break; } - r = nr_ice_ctx_create_with_credentials(const_cast(name_.c_str()), - flags, - const_cast(ufrag.c_str()), - const_cast(pwd.c_str()), - &ctx_); - MOZ_ASSERT(ufrag == ctx_->ufrag); - MOZ_ASSERT(pwd == ctx_->pwd); + r = nr_ice_ctx_create(const_cast(name_.c_str()), flags, &ctx_); if (r) { MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name_ << "'"); @@ -792,29 +789,6 @@ NrIceCtx::~NrIceCtx() { Destroy(); } -void -NrIceCtx::SetStream(const std::string& id, NrIceMediaStream* stream) { - auto it = streams_.find(id); - if (it != streams_.end()) { - MOZ_ASSERT(!stream, "Transport ids should be unique, and set only once"); - auto preexisting_stream = it->second; - streams_.erase(it); - preexisting_stream->Close(); - } - - if (stream) { - streams_[id] = stream; - } -} - -std::string NrIceCtx::ufrag() const { - return ctx_->ufrag; -} - -std::string NrIceCtx::pwd() const { - return ctx_->pwd; -} - void NrIceCtx::destroy_peer_ctx() { nr_ice_peer_ctx_destroy(&peer_); } @@ -992,7 +966,7 @@ nsresult NrIceCtx::StartGathering(bool default_route_only, bool proxy_only) { RefPtr NrIceCtx::FindStream(nr_ice_media_stream *stream) { for (auto& idAndStream : streams_) { - if (idAndStream.second->stream() == stream) { + if (idAndStream.second->HasStream(stream)) { return idAndStream.second; } } diff --git a/media/mtransport/nricectx.h b/media/mtransport/nricectx.h index 38d76570cb91..c80091a0d567 100644 --- a/media/mtransport/nricectx.h +++ b/media/mtransport/nricectx.h @@ -68,6 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "m_cpp_utils.h" #include "nricestunaddr.h" +#include "nricemediastream.h" typedef struct nr_ice_ctx_ nr_ice_ctx; typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx; @@ -204,7 +205,6 @@ class NrIceStats { }; class NrIceCtx { - friend class NrIceCtxHandler; public: enum ConnectionState { ICE_CTX_INIT, ICE_CTX_CHECKING, @@ -229,12 +229,22 @@ class NrIceCtx { ICE_POLICY_ALL }; + static RefPtr Create(const std::string& name, + bool allow_loopback = false, + bool tcp_enabled = true, + bool allow_link_local = false, + NrIceCtx::Policy policy = + NrIceCtx::ICE_POLICY_ALL); + + RefPtr CreateStream(const std::string& id, + const std::string& name, + int components); + void DestroyStream(const std::string& id); + // initialize ICE globals, crypto, and logging static void InitializeGlobals(bool allow_loopback = false, bool tcp_enabled = true, bool allow_link_local = false); - static std::string GetNewUfrag(); - static std::string GetNewPwd(); // static GetStunAddrs for use in parent process to support // sandboxing restrictions @@ -242,7 +252,6 @@ class NrIceCtx { void SetStunAddrs(const nsTArray& addrs); bool Initialize(); - bool Initialize(const std::string& ufrag, const std::string& pwd); int SetNat(const RefPtr& aNat); @@ -258,8 +267,6 @@ class NrIceCtx { // Testing only. void destroy_peer_ctx(); - void SetStream(const std::string& id, NrIceMediaStream* stream); - RefPtr GetStream(const std::string& id) { auto it = streams_.find(id); if (it != streams_.end()) { @@ -281,10 +288,6 @@ class NrIceCtx { // The name of the ctx const std::string& name() const { return name_; } - // Get ufrag and password. - std::string ufrag() const; - std::string pwd() const; - // Current state ConnectionState connection_state() const { return connection_state_; diff --git a/media/mtransport/nricectxhandler.cpp b/media/mtransport/nricectxhandler.cpp deleted file mode 100644 index 29b553cbb369..000000000000 --- a/media/mtransport/nricectxhandler.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include - -#include "logging.h" - -// nICEr includes -extern "C" { -#include "nr_api.h" -#include "ice_ctx.h" -} - -// Local includes -#include "nricectxhandler.h" -#include "nricemediastream.h" -#include "nriceresolver.h" - -namespace mozilla { - -MOZ_MTLOG_MODULE("mtransport") - -NrIceCtxHandler::NrIceCtxHandler(const std::string& name, - NrIceCtx::Policy policy) - : current_ctx(new NrIceCtx(name, policy)), - old_ctx(nullptr), - restart_count(0) -{ -} - -RefPtr -NrIceCtxHandler::Create(const std::string& name, - bool allow_loopback, - bool tcp_enabled, - bool allow_link_local, - NrIceCtx::Policy policy) -{ - // InitializeGlobals only executes once - NrIceCtx::InitializeGlobals(allow_loopback, tcp_enabled, allow_link_local); - - RefPtr ctx = new NrIceCtxHandler(name, policy); - - if (ctx == nullptr || - ctx->current_ctx == nullptr || - !ctx->current_ctx->Initialize()) { - return nullptr; - } - - return ctx; -} - - -RefPtr -NrIceCtxHandler::CreateStream(const std::string& name, int components) -{ - // To make tracking NrIceMediaStreams easier during ICE restart - // prepend an int to the name that increments with each ICE restart - std::ostringstream os; - os << restart_count << "-" << name; - return NrIceMediaStream::Create(this->current_ctx, os.str(), components); -} - - -RefPtr -NrIceCtxHandler::CreateCtx() const -{ - return CreateCtx(NrIceCtx::GetNewUfrag(), NrIceCtx::GetNewPwd()); -} - - -RefPtr -NrIceCtxHandler::CreateCtx(const std::string& ufrag, - const std::string& pwd) const -{ - RefPtr new_ctx = new NrIceCtx(this->current_ctx->name(), - this->current_ctx->policy()); - if (new_ctx == nullptr) { - return nullptr; - } - - if (!new_ctx->Initialize(ufrag, pwd)) { - return nullptr; - } - - // copy the stun, and turn servers from the current context - int r = nr_ice_ctx_set_stun_servers(new_ctx->ctx_, - this->current_ctx->ctx_->stun_servers, - this->current_ctx->ctx_->stun_server_ct); - if (r) { - MOZ_MTLOG(ML_ERROR, "Error while setting STUN servers in CreateCtx" - << " (likely ice restart related)"); - return nullptr; - } - - r = nr_ice_ctx_copy_turn_servers(new_ctx->ctx_, - this->current_ctx->ctx_->turn_servers, - this->current_ctx->ctx_->turn_server_ct); - if (r) { - MOZ_MTLOG(ML_ERROR, "Error while copying TURN servers in CreateCtx" - << " (likely ice restart related)"); - return nullptr; - } - - // grab the NrIceResolver stashed in the nr_resolver and allocate another - // for the new ctx. Note: there may not be an nr_resolver. - if (this->current_ctx->ctx_->resolver) { - NrIceResolver* resolver = - static_cast(this->current_ctx->ctx_->resolver->obj); - if (!resolver || - NS_FAILED(new_ctx->SetResolver(resolver->AllocateResolver()))) { - MOZ_MTLOG(ML_ERROR, "Error while setting dns resolver in CreateCtx" - << " (likely ice restart related)"); - return nullptr; - } - } - - return new_ctx; -} - - -bool -NrIceCtxHandler::BeginIceRestart(RefPtr new_ctx) -{ - MOZ_ASSERT(!old_ctx, "existing ice restart in progress"); - if (old_ctx) { - MOZ_MTLOG(ML_ERROR, "Existing ice restart in progress"); - return false; // ice restart already in progress - } - - if (new_ctx == nullptr) { - return false; - } - - ++restart_count; - old_ctx = current_ctx; - current_ctx = new_ctx; - return true; -} - - -void -NrIceCtxHandler::FinalizeIceRestart() -{ - if (old_ctx) { - // Fixup the telemetry by transferring old stats to current ctx. - NrIceStats stats = old_ctx->Destroy(); - current_ctx->AccumulateStats(stats); - } - - // no harm calling this even if we're not in the middle of restarting - old_ctx = nullptr; -} - - -void -NrIceCtxHandler::RollbackIceRestart() -{ - if (old_ctx == nullptr) { - return; - } - current_ctx = old_ctx; - old_ctx = nullptr; -} - -NrIceStats NrIceCtxHandler::Destroy() -{ - NrIceStats stats; - - // designed to be called more than once so if stats are desired, this can be - // called just prior to the destructor - if (old_ctx && current_ctx) { - stats = old_ctx->Destroy(); - current_ctx->AccumulateStats(stats); - } - - if (current_ctx) { - stats = current_ctx->Destroy(); - } - - old_ctx = nullptr; - current_ctx = nullptr; - - return stats; -} - -NrIceCtxHandler::~NrIceCtxHandler() -{ - Destroy(); -} - -} // close namespace diff --git a/media/mtransport/nricectxhandler.h b/media/mtransport/nricectxhandler.h deleted file mode 100644 index 2cf76ded1caf..000000000000 --- a/media/mtransport/nricectxhandler.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef nricectxhandler_h__ -#define nricectxhandler_h__ - -#include "nricectx.h" - -namespace mozilla { - -class NrIceCtxHandler { -public: - // TODO(ekr@rtfm.com): Too many bools here. Bug 1193437. - static RefPtr Create(const std::string& name, - bool allow_loopback = false, - bool tcp_enabled = true, - bool allow_link_local = false, - NrIceCtx::Policy policy = - NrIceCtx::ICE_POLICY_ALL); - - RefPtr CreateStream(const std::string& name, - int components); - // CreateCtx is necessary so we can create and initialize the context - // on main thread, but begin the ice restart mechanics on STS thread - RefPtr CreateCtx() const; // for test - RefPtr CreateCtx(const std::string& ufrag, - const std::string& pwd) const; - - RefPtr ctx() { return current_ctx; } - - bool BeginIceRestart(RefPtr new_ctx); - bool IsRestarting() const { return (old_ctx != nullptr); } - void FinalizeIceRestart(); - void RollbackIceRestart(); - - NrIceStats Destroy(); - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceCtxHandler) - -private: - NrIceCtxHandler(const std::string& name, NrIceCtx::Policy policy); - NrIceCtxHandler() = delete; - ~NrIceCtxHandler(); - DISALLOW_COPY_ASSIGN(NrIceCtxHandler); - - RefPtr current_ctx; - RefPtr old_ctx; // for while restart is in progress - int restart_count; // used to differentiate streams between restarted ctx -}; - -} // close namespace - -#endif // nricectxhandler_h__ diff --git a/media/mtransport/nricemediastream.cpp b/media/mtransport/nricemediastream.cpp index 757afec2b852..8710513ec761 100644 --- a/media/mtransport/nricemediastream.cpp +++ b/media/mtransport/nricemediastream.cpp @@ -183,28 +183,14 @@ static UniquePtr MakeNrIceCandidate(const nr_ice_candidate& cand return out; } -// NrIceMediaStream -RefPtr -NrIceMediaStream::Create(NrIceCtx *ctx, - const std::string& name, - int components) { - RefPtr stream = - new NrIceMediaStream(ctx, name, components); - MOZ_ASSERT(stream->ctx_ == ctx->ctx()); - - int r = nr_ice_add_media_stream(ctx->ctx(), - const_cast(name.c_str()), - components, &stream->stream_); - if (r) { - MOZ_MTLOG(ML_ERROR, "Couldn't create ICE media stream for '" - << name << "'"); - return nullptr; - } - - return stream; +static bool Matches(const nr_ice_media_stream* stream, + const std::string& ufrag, + const std::string& pwd) { + return stream && (stream->ufrag == ufrag) && (stream->pwd == pwd); } NrIceMediaStream::NrIceMediaStream(NrIceCtx *ctx, + const std::string& id, const std::string& name, size_t components) : state_(ICE_CONNECTING), @@ -213,7 +199,8 @@ NrIceMediaStream::NrIceMediaStream(NrIceCtx *ctx, name_(name), components_(components), stream_(nullptr), - has_parsed_attrs_(false) + old_stream_(nullptr), + id_(id) { } @@ -222,35 +209,84 @@ NrIceMediaStream::~NrIceMediaStream() { // are attached to the ice ctx. } -nsresult NrIceMediaStream::ParseAttributes(std::vector& - attributes) { - if (!stream_) - return NS_ERROR_FAILURE; +nsresult NrIceMediaStream::ConnectToPeer( + const std::string& ufrag, + const std::string& pwd, + const std::vector& attributes) { + MOZ_ASSERT(stream_); - std::vector attributes_in; - attributes_in.reserve(attributes.size()); - for (auto& attribute : attributes) { - attributes_in.push_back(const_cast(attribute.c_str())); + if (Matches(old_stream_, ufrag, pwd)) { + // Roll back to old stream, since we apparently aren't using the new one + // (We swap before we close so we never have stream_ == nullptr) + std::swap(stream_, old_stream_); + CloseStream(&old_stream_); + } else if (old_stream_) { + // Right now we wait for ICE to complete before closing the old stream. + // It might be worth it to close it sooner, but we don't want to close it + // right away. + nr_ice_media_stream_set_obsolete(old_stream_); } - // Still need to call nr_ice_ctx_parse_stream_attributes. - int r = nr_ice_peer_ctx_parse_stream_attributes(ctx_peer_, - stream_, - attributes_in.empty() ? - nullptr : &attributes_in[0], - attributes_in.size()); + nr_ice_media_stream* peer_stream; + if (nr_ice_peer_ctx_find_pstream(ctx_peer_, stream_, &peer_stream)) { + // No peer yet + std::vector attributes_in; + attributes_in.reserve(attributes.size()); + for (auto& attribute : attributes) { + MOZ_MTLOG(ML_DEBUG, "Setting " << attribute << " on stream " << name_); + attributes_in.push_back(const_cast(attribute.c_str())); + } + + // Still need to call nr_ice_ctx_parse_stream_attributes. + int r = nr_ice_peer_ctx_parse_stream_attributes(ctx_peer_, + stream_, + attributes_in.empty() ? + nullptr : &attributes_in[0], + attributes_in.size()); + if (r) { + MOZ_MTLOG(ML_ERROR, "Couldn't parse attributes for stream " + << name_ << "'"); + return NS_ERROR_FAILURE; + } + } + + return NS_OK; +} + +nsresult NrIceMediaStream::SetIceCredentials(const std::string& ufrag, + const std::string& pwd) { + if (Matches(stream_, ufrag, pwd)) { + return NS_OK; + } + + MOZ_MTLOG(ML_DEBUG, "Setting ICE credentials for " << name_ << " - " + << ufrag << ":" << pwd); + CloseStream(&old_stream_); + old_stream_ = stream_; + + std::string name(name_ + " - " + ufrag + ":" + pwd); + + int r = nr_ice_add_media_stream(ctx_, + name.c_str(), + ufrag.c_str(), + pwd.c_str(), + components_, &stream_); if (r) { - MOZ_MTLOG(ML_ERROR, "Couldn't parse attributes for stream " - << name_ << "'"); + MOZ_MTLOG(ML_ERROR, "Couldn't create ICE media stream for '" + << name_ << "': error=" << r); + stream_ = old_stream_; + old_stream_ = nullptr; return NS_ERROR_FAILURE; } - has_parsed_attrs_ = true; + state_ = ICE_CONNECTING; return NS_OK; } // Parse trickle ICE candidate nsresult NrIceMediaStream::ParseTrickleCandidate(const std::string& candidate) { + // TODO(bug 1490658): This needs to take ufrag into account. For now, trickle + // candidates will land on the most recently-created ICE stream. int r; MOZ_MTLOG(ML_DEBUG, "NrIceCtx(" << ctx_->label << ")/STREAM(" << @@ -463,7 +499,7 @@ nsresult NrIceMediaStream::GetDefaultCandidate( return NS_OK; } -std::vector NrIceMediaStream::GetCandidates() const { +std::vector NrIceMediaStream::GetAttributes() const { char **attrs = nullptr; int attrct; int r; @@ -587,13 +623,19 @@ nsresult NrIceMediaStream::GetConsentStatus(int component_id, bool *can_send, st return NS_OK; } +bool NrIceMediaStream::HasStream(nr_ice_media_stream *stream) const { + return (stream == stream_) || (stream == old_stream_); +} + nsresult NrIceMediaStream::SendPacket(int component_id, const unsigned char *data, size_t len) { - if (!stream_) + nr_ice_media_stream* stream = old_stream_ ? old_stream_ : stream_; + if (!stream) { return NS_ERROR_FAILURE; + } - int r = nr_ice_media_stream_send(ctx_peer_, stream_, + int r = nr_ice_media_stream_send(ctx_peer_, stream, component_id, const_cast(data), len); if (r) { @@ -615,6 +657,7 @@ void NrIceMediaStream::Ready() { if (state_ != ICE_OPEN) { MOZ_MTLOG(ML_DEBUG, "Marking stream ready '" << name_ << "'"); state_ = ICE_OPEN; + CloseStream(&old_stream_); SignalReady(this); } else { @@ -622,16 +665,34 @@ void NrIceMediaStream::Ready() { } } +void NrIceMediaStream::Failed() { + if (state_ != ICE_CLOSED) { + MOZ_MTLOG(ML_DEBUG, "Marking stream failed '" << name_ << "'"); + state_ = ICE_CLOSED; + // We don't need the old stream anymore. + CloseStream(&old_stream_); + SignalFailed(this); + } +} + void NrIceMediaStream::Close() { MOZ_MTLOG(ML_DEBUG, "Marking stream closed '" << name_ << "'"); state_ = ICE_CLOSED; - if (stream_) { - int r = nr_ice_remove_media_stream(ctx_, &stream_); + CloseStream(&old_stream_); + CloseStream(&stream_); +} + +void +NrIceMediaStream::CloseStream(nr_ice_media_stream **stream) +{ + if (*stream) { + int r = nr_ice_remove_media_stream(ctx_, stream); if (r) { MOZ_ASSERT(false, "Failed to remove stream"); MOZ_MTLOG(ML_ERROR, "Failed to remove stream, error=" << r); } + *stream = nullptr; } } diff --git a/media/mtransport/nricemediastream.h b/media/mtransport/nricemediastream.h index 76802f5be1a6..df2477ce15aa 100644 --- a/media/mtransport/nricemediastream.h +++ b/media/mtransport/nricemediastream.h @@ -137,9 +137,15 @@ struct NrIceCandidatePair { class NrIceMediaStream { public: - static RefPtr Create(NrIceCtx *ctx, - const std::string& name, - int components); + NrIceMediaStream(NrIceCtx *ctx, + const std::string& id, + const std::string& name, + size_t components); + + nsresult SetIceCredentials(const std::string& ufrag, const std::string& pwd); + nsresult ConnectToPeer(const std::string& ufrag, + const std::string& pwd, + const std::vector& peer_attrs); enum State { ICE_CONNECTING, ICE_OPEN, ICE_CLOSED}; State state() const { return state_; } @@ -147,8 +153,8 @@ class NrIceMediaStream { // The name of the stream const std::string& name() const { return name_; } - // Get all the candidates - std::vector GetCandidates() const; + // Get all the ICE attributes; used for testing + std::vector GetAttributes() const; nsresult GetLocalCandidates(std::vector* candidates) const; nsresult GetRemoteCandidates(std::vector* candidates) const; @@ -159,10 +165,6 @@ class NrIceMediaStream { nsresult GetDefaultCandidate(int component, NrIceCandidate* candidate) const; - // Parse remote attributes - nsresult ParseAttributes(std::vector& candidates); - bool HasParsedAttributes() const { return has_parsed_attrs_; } - // Parse trickle ICE candidate nsresult ParseTrickleCandidate(const std::string& candidate); @@ -182,8 +184,7 @@ class NrIceMediaStream { // The number of components size_t components() const { return components_; } - // The underlying nICEr stream - nr_ice_media_stream *stream() { return stream_; } + bool HasStream(nr_ice_media_stream *stream) const; // Signals to indicate events. API users can (and should) // register for these. @@ -192,6 +193,7 @@ class NrIceMediaStream { // Set your state to ready. Called by the NrIceCtx; void Ready(); + void Failed(); // Close the stream. Called by the NrIceCtx. // Different from the destructor because other people @@ -201,8 +203,6 @@ class NrIceMediaStream { // So the receiver of SignalCandidate can determine which transport // the candidate belongs to. - void SetId(const std::string& id) { id_ = id; } - const std::string& GetId() const { return id_; } sigslot::signal2 @@ -216,22 +216,20 @@ class NrIceMediaStream { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceMediaStream) private: - NrIceMediaStream(NrIceCtx *ctx, - const std::string& name, - size_t components); - ~NrIceMediaStream(); DISALLOW_COPY_ASSIGN(NrIceMediaStream); + void CloseStream(nr_ice_media_stream **stream); + State state_; nr_ice_ctx *ctx_; nr_ice_peer_ctx *ctx_peer_; const std::string name_; const size_t components_; nr_ice_media_stream *stream_; - std::string id_; - bool has_parsed_attrs_; + nr_ice_media_stream *old_stream_; + const std::string id_; }; diff --git a/media/mtransport/nriceresolver.h b/media/mtransport/nriceresolver.h index 612c860ae2d5..08b48c1a1132 100644 --- a/media/mtransport/nriceresolver.h +++ b/media/mtransport/nriceresolver.h @@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "nsIDNSService.h" #include "nsIDNSListener.h" #include "nsICancelable.h" +#include "nricectx.h" typedef struct nr_resolver_ nr_resolver; typedef struct nr_resolver_vtbl_ nr_resolver_vtbl; diff --git a/media/mtransport/test/ice_unittest.cpp b/media/mtransport/test/ice_unittest.cpp index b8c35a350b11..70f5a36843b0 100644 --- a/media/mtransport/test/ice_unittest.cpp +++ b/media/mtransport/test/ice_unittest.cpp @@ -23,7 +23,20 @@ #include "nsThreadUtils.h" #include "nsXPCOM.h" -#include "nricectxhandler.h" +extern "C" { +#include "r_types.h" +#include "async_wait.h" +#include "async_timer.h" +#include "r_data.h" +#include "util.h" +#include "r_time.h" +} + +#include "ice_ctx.h" +#include "ice_peer_ctx.h" +#include "ice_media_stream.h" + +#include "nricectx.h" #include "nricemediastream.h" #include "nriceresolverfake.h" #include "nriceresolver.h" @@ -38,17 +51,6 @@ #include "stun_socket_filter.h" #include "mozilla/net/DNS.h" -#include "ice_ctx.h" -#include "ice_peer_ctx.h" -#include "ice_media_stream.h" - -extern "C" { -#include "async_timer.h" -#include "r_data.h" -#include "util.h" -#include "r_time.h" -} - #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" #include "gtest_utils.h" @@ -380,9 +382,9 @@ class IceTestPeer : public sigslot::has_slots<> { bool allow_link_local = false, NrIceCtx::Policy ice_policy = NrIceCtx::ICE_POLICY_ALL) : name_(name), - ice_ctx_(NrIceCtxHandler::Create(name, allow_loopback, - enable_tcp, allow_link_local, - ice_policy)), + ice_ctx_(NrIceCtx::Create(name, allow_loopback, + enable_tcp, allow_link_local, + ice_policy)), offerer_(offerer), candidates_(), stream_counter_(0), @@ -405,16 +407,16 @@ class IceTestPeer : public sigslot::has_slots<> { simulate_ice_lite_(false), nat_(new TestNat), test_utils_(utils) { - ice_ctx_->ctx()->SignalGatheringStateChange.connect( + ice_ctx_->SignalGatheringStateChange.connect( this, &IceTestPeer::GatheringStateChange); - ice_ctx_->ctx()->SignalConnectionStateChange.connect( + ice_ctx_->SignalConnectionStateChange.connect( this, &IceTestPeer::ConnectionStateChange); consent_timestamp_.tv_sec = 0; consent_timestamp_.tv_usec = 0; - int r = ice_ctx_->ctx()->SetNat(nat_); + int r = ice_ctx_->SetNat(nat_); (void)r; MOZ_ASSERT(!r); } @@ -435,13 +437,28 @@ class IceTestPeer : public sigslot::has_slots<> { return id; } + void SetIceCredentials_s(NrIceMediaStream &stream) { + static size_t counter = 0; + std::ostringstream prefix; + prefix << name_ << "-" << counter++; + std::string ufrag = prefix.str() + "-ufrag"; + std::string pwd = prefix.str() + "-pwd"; + if (mIceCredentials.count(stream.GetId())) { + mOldIceCredentials[stream.GetId()] = mIceCredentials[stream.GetId()]; + } + mIceCredentials[stream.GetId()] = std::make_pair(ufrag, pwd); + stream.SetIceCredentials(ufrag, pwd); + } + void AddStream_s(int components) { std::string id = MakeTransportId(stream_counter_++); - RefPtr stream = ice_ctx_->CreateStream(id, components); - ice_ctx_->ctx()->SetStream(id, stream); + RefPtr stream = + ice_ctx_->CreateStream(id, id, components); ASSERT_TRUE(stream); + SetIceCredentials_s(*stream); + stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized); stream->SignalReady.connect(this, &IceTestPeer::StreamReady); stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed); @@ -456,7 +473,7 @@ class IceTestPeer : public sigslot::has_slots<> { } void RemoveStream_s(size_t index) { - ice_ctx_->ctx()->SetStream(MakeTransportId(index), nullptr); + ice_ctx_->DestroyStream(MakeTransportId(index)); } void RemoveStream(size_t index) { @@ -467,7 +484,7 @@ class IceTestPeer : public sigslot::has_slots<> { RefPtr GetStream_s(size_t index) { std::string id = MakeTransportId(index); - return ice_ctx_->ctx()->GetStream(id); + return ice_ctx_->GetStream(id); } void SetStunServer(const std::string addr, uint16_t port, @@ -485,7 +502,7 @@ class IceTestPeer : public sigslot::has_slots<> { } void SetStunServers(const std::vector &servers) { - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(servers))); + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(servers))); } void UseTestStunServer() { @@ -510,11 +527,11 @@ class IceTestPeer : public sigslot::has_slots<> { UniquePtr server(NrIceTurnServer::Create( addr, port, username, password, transport)); turn_servers.push_back(*server); - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetTurnServers(turn_servers))); + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(turn_servers))); } void SetTurnServers(const std::vector servers) { - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetTurnServers(servers))); + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetTurnServers(servers))); } void SetFakeResolver(const std::string& ip, @@ -527,13 +544,13 @@ class IceTestPeer : public sigslot::has_slots<> { ASSERT_EQ(PR_SUCCESS, status); fake_resolver_.SetAddr(fqdn, addr); } - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetResolver( + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver( fake_resolver_.AllocateResolver()))); } void SetDNSResolver() { ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init())); - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetResolver( + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver( dns_resolver_->AllocateResolver()))); } @@ -542,7 +559,7 @@ class IceTestPeer : public sigslot::has_slots<> { test_utils_->sts_target()->Dispatch( WrapRunnableRet(&res, - ice_ctx_->ctx(), + ice_ctx_, &NrIceCtx::StartGathering, default_route_only, false), @@ -556,7 +573,7 @@ class IceTestPeer : public sigslot::has_slots<> { } void SetTimerDivider(int div) { - ice_ctx_->ctx()->internal_SetTimerAccelarator(div); + ice_ctx_->internal_SetTimerAccelarator(div); } void SetStunResponseDelay(uint32_t delay) { @@ -584,19 +601,19 @@ class IceTestPeer : public sigslot::has_slots<> { // Get various pieces of state std::vector GetGlobalAttributes() { - std::vector attrs(ice_ctx_->ctx()->GetGlobalAttributes()); + std::vector attrs(ice_ctx_->GetGlobalAttributes()); if (simulate_ice_lite_) { attrs.push_back("ice-lite"); } return attrs; } - std::vector GetCandidates(size_t stream) { + std::vector GetAttributes(size_t stream) { std::vector v; RUN_ON_THREAD( test_utils_->sts_target(), - WrapRunnableRet(&v, this, &IceTestPeer::GetCandidates_s, stream)); + WrapRunnableRet(&v, this, &IceTestPeer::GetAttributes_s, stream)); return v; } @@ -608,27 +625,31 @@ class IceTestPeer : public sigslot::has_slots<> { return candidate; } - std::vector GetCandidates_s(size_t index) { - std::vector candidates; + std::vector GetAttributes_s(size_t index) { + std::vector attributes; auto stream = GetStream_s(index); if (!stream) { EXPECT_TRUE(false) << "No such stream " << index; - return candidates; + return attributes; } - std::vector candidates_in = stream->GetCandidates(); + std::vector attributes_in = stream->GetAttributes(); - for (const auto& a_candidate : candidates_in) { - std::string candidate(FilterCandidate(a_candidate)); - if (!candidate.empty()) { - std::cerr << name_ << " Returning candidate: " - << candidate << std::endl; - candidates.push_back(candidate); + for (const auto& attribute : attributes_in) { + if (attribute.find("candidate:") != std::string::npos) { + std::string candidate(FilterCandidate(attribute)); + if (!candidate.empty()) { + std::cerr << name_ << " Returning candidate: " + << candidate << std::endl; + attributes.push_back(candidate); + } + } else { + attributes.push_back(attribute); } } - return candidates; + return attributes; } void SetExpectedTypes(NrIceCandidate::Type local, @@ -644,13 +665,13 @@ class IceTestPeer : public sigslot::has_slots<> { } int GetCandidatesPrivateIpv4Range(size_t stream) { - std::vector candidates = GetCandidates(stream); + std::vector attributes = GetAttributes(stream); int host_net = 0; - for (const auto& c : candidates) { - if (c.find("typ host") != std::string::npos) { + for (const auto& a : attributes) { + if (a.find("typ host") != std::string::npos) { nr_transport_addr addr; - std::vector tokens = split(c, ' '); + std::vector tokens = split(a, ' '); int r = nr_str_port_to_transport_addr(tokens.at(4).c_str(), 0, IPPROTO_UDP, &addr); MOZ_ASSERT(!r); if (!r && (addr.ip_version == NR_IPV4)) { @@ -697,23 +718,15 @@ class IceTestPeer : public sigslot::has_slots<> { void RestartIce() { test_utils_->sts_target()->Dispatch( WrapRunnable(this, - &IceTestPeer::RestartIce_s, - ice_ctx_->CreateCtx()), + &IceTestPeer::RestartIce_s), NS_DISPATCH_SYNC); } - void RestartIce_s(RefPtr new_ctx) { - ice_ctx_->BeginIceRestart(new_ctx); - - // set signals for the newly restarted ctx - ice_ctx_->ctx()->SignalGatheringStateChange.connect( - this, - &IceTestPeer::GatheringStateChange); - ice_ctx_->ctx()->SignalConnectionStateChange.connect( - this, - &IceTestPeer::ConnectionStateChange); - + void RestartIce_s() { + for (auto& stream : ice_ctx_->GetStreams()) { + SetIceCredentials_s(*stream); + } // take care of some local bookkeeping ready_ct_ = 0; gathering_complete_ = false; @@ -721,19 +734,6 @@ class IceTestPeer : public sigslot::has_slots<> { ice_failed_ = false; ice_reached_checking_ = false; remote_ = nullptr; - stream_counter_ = 0; - } - - - void FinalizeIceRestart() { - test_utils_->sts_target()->Dispatch( - WrapRunnable(this, &IceTestPeer::FinalizeIceRestart_s), - NS_DISPATCH_SYNC); - } - - - void FinalizeIceRestart_s() { - ice_ctx_->FinalizeIceRestart(); } @@ -745,7 +745,9 @@ class IceTestPeer : public sigslot::has_slots<> { void RollbackIceRestart_s() { - ice_ctx_->RollbackIceRestart(); + for (auto& stream : ice_ctx_->GetStreams()) { + mIceCredentials[stream->GetId()] = mOldIceCredentials[stream->GetId()]; + } } @@ -760,44 +762,38 @@ class IceTestPeer : public sigslot::has_slots<> { ice_connected_ = false; ice_failed_ = false; ice_reached_checking_ = false; - res = ice_ctx_->ctx()->ParseGlobalAttributes(remote->GetGlobalAttributes()); + res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes()); ASSERT_TRUE(NS_SUCCEEDED(res)); - if (trickle_mode == TRICKLE_NONE || - trickle_mode == TRICKLE_REAL) { - for (size_t i=0; iHasParsedAttributes()) { - continue; - } - std::vector candidates = - remote->GetCandidates(i); + for (size_t i=0; i attributes = remote->GetAttributes(i); - for (const auto& candidate : candidates) { - std::cerr << name_ << " Adding remote candidate: " + candidate << std::endl; + for (auto it = attributes.begin(); it != attributes.end();) { + if (trickle_mode == TRICKLE_SIMULATE && + it->find("candidate:") != std::string::npos) { + std::cerr << name_ << " Deferring remote candidate: " << *it + << std::endl; + attributes.erase(it); + } else { + std::cerr << name_ << " Adding remote attribute: " + *it + << std::endl; + ++it; + } } - res = aStream->ParseAttributes(candidates); - ASSERT_TRUE(NS_SUCCEEDED(res)); - } - } else { - // Parse empty attributes and then trickle them out later - for (size_t i=0; iHasParsedAttributes()) { - continue; - } - std::vector empty_attrs; - std::cout << "Calling ParseAttributes on stream " << i << std::endl; - res = aStream->ParseAttributes(empty_attrs); + auto credentials = mIceCredentials[aStream->GetId()]; + res = aStream->ConnectToPeer( + credentials.first, credentials.second, attributes); ASSERT_TRUE(NS_SUCCEEDED(res)); } } if (start) { - ice_ctx_->ctx()->SetControlling( + ice_ctx_->SetControlling( offerer_ ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED); // Now start checks - res = ice_ctx_->ctx()->StartChecks(offerer_); + res = ice_ctx_->StartChecks(offerer_); ASSERT_TRUE(NS_SUCCEEDED(res)); } } @@ -829,13 +825,14 @@ class IceTestPeer : public sigslot::has_slots<> { std::vector& ControlTrickle(size_t stream) { std::cerr << "Doing controlled trickle for stream " << stream << std::endl; - std::vector candidates = - remote_->GetCandidates(stream); + std::vector attributes = remote_->GetAttributes(stream); - for (const auto& candidate : candidates) { - controlled_trickle_candidates_[stream].push_back( - new SchedulableTrickleCandidate( - this, stream, candidate, test_utils_)); + for (const auto& attribute : attributes) { + if (attribute.find("candidate:") != std::string::npos) { + controlled_trickle_candidates_[stream].push_back( + new SchedulableTrickleCandidate( + this, stream, attribute, test_utils_)); + } } return controlled_trickle_candidates_[stream]; @@ -919,7 +916,7 @@ class IceTestPeer : public sigslot::has_slots<> { void DumpAndCheckActiveCandidates_s() { std::cerr << name_ << " Active candidates:" << std::endl; - for (const auto& stream : ice_ctx_->ctx()->GetStreams()) { + for (const auto& stream : ice_ctx_->GetStreams()) { for (size_t j=0; j < stream->components(); ++j) { std::cerr << name_ << " Stream " << stream->GetId() << " component " << j+1 << std::endl; @@ -969,7 +966,7 @@ class IceTestPeer : public sigslot::has_slots<> { void Close() { test_utils_->sts_target()->Dispatch( - WrapRunnable(ice_ctx_->ctx(), &NrIceCtx::destroy_peer_ctx), + WrapRunnable(ice_ctx_, &NrIceCtx::destroy_peer_ctx), NS_DISPATCH_SYNC); } @@ -999,13 +996,13 @@ class IceTestPeer : public sigslot::has_slots<> { nsresult res; test_utils_->sts_target()->Dispatch( - WrapRunnableRet(&res, ice_ctx_->ctx(), &NrIceCtx::SetControlling, + WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::SetControlling, offerer_ ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED), NS_DISPATCH_SYNC); // Now start checks test_utils_->sts_target()->Dispatch( - WrapRunnableRet(&res, ice_ctx_->ctx(), &NrIceCtx::StartChecks, + WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::StartChecks, offerer_), NS_DISPATCH_SYNC); ASSERT_TRUE(NS_SUCCEEDED(res)); @@ -1024,14 +1021,14 @@ class IceTestPeer : public sigslot::has_slots<> { std::cerr << name_ << " Gathering complete" << std::endl; gathering_complete_ = true; - std::cerr << name_ << " CANDIDATES:" << std::endl; - for (const auto& stream : ice_ctx_->ctx()->GetStreams()) { + std::cerr << name_ << " ATTRIBUTES:" << std::endl; + for (const auto& stream : ice_ctx_->GetStreams()) { std::cerr << "Stream " << stream->GetId() << std::endl; - std::vector candidates = stream->GetCandidates(); + std::vector attributes = stream->GetAttributes(); - for(const auto& candidate : candidates) { - std::cerr << candidate << std::endl; + for(const auto& attribute : attributes) { + std::cerr << attribute << std::endl; } } std::cerr << std::endl; @@ -1116,7 +1113,7 @@ class IceTestPeer : public sigslot::has_slots<> { void DumpCandidatePairs_s() { std::cerr << "Dumping candidate pairs for all streams [" << std::endl; - for (const auto& stream : ice_ctx_->ctx()->GetStreams()) { + for (const auto& stream : ice_ctx_->GetStreams()) { DumpCandidatePairs_s(stream.get()); } std::cerr << "]" << std::endl; @@ -1281,11 +1278,7 @@ class IceTestPeer : public sigslot::has_slots<> { void ParseCandidate_s(size_t i, const std::string& candidate) { auto media_stream = GetStream_s(i); ASSERT_TRUE(media_stream.get()) << "No such stream " << i; - - std::vector attributes; - - attributes.push_back(candidate); - media_stream->ParseAttributes(attributes); + media_stream->ParseTrickleCandidate(candidate); } void ParseCandidate(size_t i, const std::string& candidate) @@ -1355,7 +1348,7 @@ class IceTestPeer : public sigslot::has_slots<> { } void ChangeNetworkState_s(bool online) { - ice_ctx_->ctx()->UpdateNetworkState(online); + ice_ctx_->UpdateNetworkState(online); } void ChangeNetworkStateToOffline() { @@ -1377,7 +1370,7 @@ class IceTestPeer : public sigslot::has_slots<> { void SetControlling(NrIceCtx::Controlling controlling) { nsresult res; test_utils_->sts_target()->Dispatch( - WrapRunnableRet(&res, ice_ctx_->ctx(), + WrapRunnableRet(&res, ice_ctx_, &NrIceCtx::SetControlling, controlling), NS_DISPATCH_SYNC); @@ -1385,7 +1378,7 @@ class IceTestPeer : public sigslot::has_slots<> { } NrIceCtx::Controlling GetControlling() { - return ice_ctx_->ctx()->GetControlling(); + return ice_ctx_->GetControlling(); } void SetTiebreaker(uint64_t tiebreaker) { @@ -1397,7 +1390,7 @@ class IceTestPeer : public sigslot::has_slots<> { } void SetTiebreaker_s(uint64_t tiebreaker) { - ice_ctx_->ctx()->peer()->tiebreaker = tiebreaker; + ice_ctx_->peer()->tiebreaker = tiebreaker; } void SimulateIceLite() { @@ -1423,12 +1416,14 @@ class IceTestPeer : public sigslot::has_slots<> { private: std::string name_; - RefPtr ice_ctx_; + RefPtr ice_ctx_; bool offerer_; std::map > candidates_; // Maps from stream id to list of remote trickle candidates std::map > controlled_trickle_candidates_; + std::map> mIceCredentials; + std::map> mOldIceCredentials; size_t stream_counter_; bool shutting_down_; bool gathering_complete_; @@ -1598,11 +1593,11 @@ class WebRtcIceGatherTest : public StunTest { bool StreamHasMatchingCandidate(unsigned int stream, const std::string& match, const std::string& match2 = "") { - std::vector candidates = peer_->GetCandidates(stream); - for (auto& candidate : candidates) { - if (std::string::npos != candidate.find(match)) { + std::vector attributes = peer_->GetAttributes(stream); + for (auto& attribute : attributes) { + if (std::string::npos != attribute.find(match)) { if (!match2.length() || - std::string::npos != candidate.find(match2)) { + std::string::npos != attribute.find(match2)) { return true; } } @@ -1610,14 +1605,14 @@ class WebRtcIceGatherTest : public StunTest { return false; } - void DumpCandidates(unsigned int stream) { - std::vector candidates = peer_->GetCandidates(stream); + void DumpAttributes(unsigned int stream) { + std::vector attributes = peer_->GetAttributes(stream); - std::cerr << "Candidates for stream " << stream << "->" - << candidates.size() << std::endl; + std::cerr << "Attributes for stream " << stream << "->" + << attributes.size() << std::endl; - for (const auto& c : candidates) { - std::cerr << "Candidate: " << c << std::endl; + for (const auto& a : attributes) { + std::cerr << "Attribute: " << a << std::endl; } } @@ -1812,7 +1807,9 @@ class WebRtcIceConnectTest : public StunTest { ConnectCallerAndCallee(p1_.get(), p2_.get()); } - void ConnectCallerAndCallee(IceTestPeer* caller, IceTestPeer* callee) { + void ConnectCallerAndCallee(IceTestPeer* caller, + IceTestPeer* callee, + TrickleMode mode = TRICKLE_NONE) { ASSERT_TRUE(caller->ready_ct() == 0); ASSERT_TRUE(caller->ice_connected() == 0); ASSERT_TRUE(caller->ice_reached_checking() == 0); @@ -1824,19 +1821,20 @@ class WebRtcIceConnectTest : public StunTest { // gives them to |this|, meaning that callee->Connect(caller, ...) // simulates caller sending an offer to callee. Order matters here // because it determines which peer is controlling. - callee->Connect(caller, TRICKLE_NONE); - caller->Connect(callee, TRICKLE_NONE); + callee->Connect(caller, mode); + caller->Connect(callee, mode); - ASSERT_TRUE_WAIT(caller->ready_ct() == 1 && callee->ready_ct() == 1, - kDefaultTimeout); - ASSERT_TRUE_WAIT(caller->ice_connected() && callee->ice_connected(), - kDefaultTimeout); + if (mode != TRICKLE_SIMULATE) { + ASSERT_TRUE_WAIT(caller->ready_ct() == 1 && callee->ready_ct() == 1, + kDefaultTimeout); + ASSERT_TRUE_WAIT(caller->ice_connected() && callee->ice_connected(), + kDefaultTimeout); + ASSERT_TRUE(caller->ice_reached_checking()); + ASSERT_TRUE(callee->ice_reached_checking()); - ASSERT_TRUE(caller->ice_reached_checking()); - ASSERT_TRUE(callee->ice_reached_checking()); - - caller->DumpAndCheckActiveCandidates(); - callee->DumpAndCheckActiveCandidates(); + caller->DumpAndCheckActiveCandidates(); + callee->DumpAndCheckActiveCandidates(); + } } void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote, @@ -1941,15 +1939,18 @@ class WebRtcIceConnectTest : public StunTest { size_t previousSent = p1->sent(); size_t previousReceived = p2->received(); - test_utils_->sts_target()->Dispatch( - WrapRunnable(p1, - &IceTestPeer::SendPacket, 0, 1, - reinterpret_cast("TEST"), 4), - NS_DISPATCH_SYNC); if (expect_tx_failure) { + test_utils_->sts_target()->Dispatch( + WrapRunnable(p1, &IceTestPeer::SendFailure, 0, 1), + NS_DISPATCH_SYNC); ASSERT_EQ(previousSent, p1->sent()); } else { + test_utils_->sts_target()->Dispatch( + WrapRunnable(p1, + &IceTestPeer::SendPacket, 0, 1, + reinterpret_cast("TEST"), 4), + NS_DISPATCH_SYNC); ASSERT_EQ(previousSent+1, p1->sent()); } if (expect_rx_failure) { @@ -2036,7 +2037,7 @@ class WebRtcIcePacketFilterTest : public StunTest { StunTest::SetUp(); // Set up enough of the ICE ctx to allow the packet filter to work - ice_ctx_ = NrIceCtxHandler::Create("test", true); + ice_ctx_ = NrIceCtx::Create("test", true); nsCOMPtr udp_handler = do_GetService(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CONTRACTID); @@ -2148,7 +2149,7 @@ class WebRtcIcePacketFilterTest : public StunTest { nsCOMPtr udp_filter_; nsCOMPtr tcp_filter_; - RefPtr ice_ctx_; + RefPtr ice_ctx_; }; } // end namespace @@ -2363,12 +2364,13 @@ TEST_F(WebRtcIceGatherTest, TestGatherDisableComponent) { peer_->AddStream(2); peer_->DisableComponent(1, 2); Gather(); - std::vector candidates = - peer_->GetCandidates(1); + std::vector attributes = peer_->GetAttributes(1); - for (auto& candidate : candidates) { - size_t sp1 = candidate.find(' '); - ASSERT_EQ(0, candidate.compare(sp1+1, 1, "1", 1)); + for (auto& attribute : attributes) { + if (attribute.find("candidate:") != std::string::npos) { + size_t sp1 = attribute.find(' '); + ASSERT_EQ(0, attribute.compare(sp1+1, 1, "1", 1)); + } } } @@ -2494,7 +2496,7 @@ TEST_F(WebRtcIceGatherTest, TestFakeStunServerNatedNoHost) { UseFakeStunUdpServerWithResponse("192.0.2.1", 3333); Gather(0); WaitForGather(); - DumpCandidates(0); + DumpAttributes(0); ASSERT_FALSE(StreamHasMatchingCandidate(0, "host")); ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx")); NrIceCandidate default_candidate; @@ -2511,7 +2513,7 @@ TEST_F(WebRtcIceGatherTest, TestFakeStunServerNoNatNoHost) { UseTestStunServer(); Gather(0); WaitForGather(); - DumpCandidates(0); + DumpAttributes(0); ASSERT_FALSE(StreamHasMatchingCandidate(0, "host")); ASSERT_TRUE(StreamHasMatchingCandidate(0, "srflx")); } @@ -2601,17 +2603,15 @@ TEST_F(WebRtcIceConnectTest, TestConnectRestartIce) { InitPeer(p3_.get()); p3_->AddStream(1); - p2_->AddStream(1); ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get())); std::cout << "-------------------------------------------------" << std::endl; - ConnectCallerAndCallee(p3_.get(), p2_.get()); - SendReceive(p1_.get(), p2_.get()); // p1 and p2 still connected - SendReceive(p3_.get(), p2_.get()); // p3 and p2 are now connected - - p2_->FinalizeIceRestart(); - SendReceive(p3_.get(), p2_.get()); // p3 and p2 are still connected - + ConnectCallerAndCallee(p3_.get(), p2_.get(), TRICKLE_SIMULATE); + SendReceive(p1_.get(), p2_.get()); // p1 and p2 are still connected + SendReceive(p3_.get(), p2_.get(), true, true); // p3 and p2 not yet connected + p2_->SimulateTrickle(0); + p3_->SimulateTrickle(0); SendReceive(p1_.get(), p2_.get(), false, true); // p1 and p2 not connected + SendReceive(p3_.get(), p2_.get()); // p3 and p2 are now connected p3_ = nullptr; } @@ -2633,22 +2633,15 @@ TEST_F(WebRtcIceConnectTest, TestConnectRestartIceThenAbort) { InitPeer(p3_.get()); p3_->AddStream(1); - p2_->AddStream(1); ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get())); std::cout << "-------------------------------------------------" << std::endl; - ConnectCallerAndCallee(p3_.get(), p2_.get()); - SendReceive(p1_.get(), p2_.get()); // p1 and p2 still connected - SendReceive(p3_.get(), p2_.get()); // p3 and p2 are now connected - p2_->RollbackIceRestart(); - SendReceive(p1_.get(), p2_.get()); // p1 and p2 are still connected - - SendReceive(p3_.get(), p2_.get(), false, true); // p3 and p2 not connected - + p2_->Connect(p1_.get(), TRICKLE_NONE); + SendReceive(p1_.get(), p2_.get()); p3_ = nullptr; } -TEST_F(WebRtcIceConnectTest, TestConnectSetControllingAfterIceRestart) { +TEST_F(WebRtcIceConnectTest, TestConnectIceRestartRoleConflict) { AddStream(1); ASSERT_TRUE(Gather()); // Just for fun lets do this with switched rolls @@ -2662,35 +2655,31 @@ TEST_F(WebRtcIceConnectTest, TestConnectSetControllingAfterIceRestart) { p2_->RestartIce(); ASSERT_FALSE(p2_->gathering_complete()); - // ICE restart should allow us to set control role again p2_->SetControlling(NrIceCtx::ICE_CONTROLLED); - ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p2_->GetControlling()); - // But still only allowed to set control role once - p2_->SetControlling(NrIceCtx::ICE_CONTROLLING); - ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p2_->GetControlling()); + ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p2_->GetControlling()) << + "ICE restart should not allow role to change, unless ice-lite happens"; mozilla::UniquePtr p3_; p3_ = MakeUnique("P3", test_utils_, true, false, false, false); InitPeer(p3_.get()); p3_->AddStream(1); - // Set control role for p3 accordingly (w/o role conflict) + // Set control role for p3 accordingly (with role conflict) p3_->SetControlling(NrIceCtx::ICE_CONTROLLING); ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p3_->GetControlling()); - p2_->AddStream(1); ASSERT_TRUE(GatherCallerAndCallee(p2_.get(), p3_.get())); std::cout << "-------------------------------------------------" << std::endl; ConnectCallerAndCallee(p3_.get(), p2_.get()); - // Again connecting should not result in role switch - ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p2_->GetControlling()); - ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p3_->GetControlling()); + auto p2role = p2_->GetControlling(); + ASSERT_NE(p2role, p3_->GetControlling()) << "Conflict should be resolved"; + ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p1_->GetControlling()) + << "P1 should be unaffected by role conflict"; - p2_->FinalizeIceRestart(); // And again we are not allowed to switch roles at this point any more - p2_->SetControlling(NrIceCtx::ICE_CONTROLLING); - ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p2_->GetControlling()); - p3_->SetControlling(NrIceCtx::ICE_CONTROLLED); - ASSERT_EQ(NrIceCtx::ICE_CONTROLLING, p3_->GetControlling()); + p1_->SetControlling(NrIceCtx::ICE_CONTROLLING); + ASSERT_EQ(NrIceCtx::ICE_CONTROLLED, p1_->GetControlling()); + p3_->SetControlling(p2role); + ASSERT_NE(p2role, p3_->GetControlling()); p3_ = nullptr; } diff --git a/media/mtransport/test/multi_tcp_socket_unittest.cpp b/media/mtransport/test/multi_tcp_socket_unittest.cpp index 7eab7d11af43..4a3a4e94e710 100644 --- a/media/mtransport/test/multi_tcp_socket_unittest.cpp +++ b/media/mtransport/test/multi_tcp_socket_unittest.cpp @@ -24,7 +24,7 @@ extern "C" { #include "stunserver.h" -#include "nricectxhandler.h" +#include "nricectx.h" #include "nricemediastream.h" #define GTEST_HAS_RTTI 0 @@ -47,7 +47,7 @@ class MultiTcpSocketTest : public MtransportTest { void SetUp() { MtransportTest::SetUp(); - ice_ctx_ = NrIceCtxHandler::Create("stun", true); + ice_ctx_ = NrIceCtx::Create("stun", true); test_utils_->sts_target()->Dispatch( WrapRunnableNM(&TestStunTcpServer::GetInstance, AF_INET), @@ -108,7 +108,7 @@ class MultiTcpSocketTest : public MtransportTest { stun_server_addr, stun_server_port, kNrIceTransportTcp)); stun_servers.push_back(*server); - ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(stun_servers))); + ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers))); } r = 1; @@ -117,7 +117,7 @@ class MultiTcpSocketTest : public MtransportTest { (char *)"127.0.0.1", EnsureEphemeral(port_s++), IPPROTO_TCP, &local); ASSERT_EQ(0, r); - r = nr_socket_multi_tcp_create(ice_ctx_->ctx()->ctx(), + r = nr_socket_multi_tcp_create(ice_ctx_->ctx(), &local, tcp_type, 1, 2048, sock); } @@ -347,7 +347,7 @@ class MultiTcpSocketTest : public MtransportTest { } std::vector socks; Atomic readable; - RefPtr ice_ctx_; + RefPtr ice_ctx_; }; } diff --git a/media/mtransport/test/test_nr_socket_ice_unittest.cpp b/media/mtransport/test/test_nr_socket_ice_unittest.cpp index 8453e82237ea..8d48005c54de 100644 --- a/media/mtransport/test/test_nr_socket_ice_unittest.cpp +++ b/media/mtransport/test/test_nr_socket_ice_unittest.cpp @@ -104,7 +104,10 @@ public: nr_ice_add_media_stream(ice_ctx_, const_cast(name_.c_str()), + "ufrag", + "pass", 2, &ice_media_stream_); + EXPECT_EQ(2UL, GetStreamAttributes().size()); nr_ice_media_stream_initialize(ice_ctx_, ice_media_stream_); } @@ -144,30 +147,46 @@ public: ASSERT_TRUE(r == 0 || r == R_WOULDBLOCK); } - std::vector GetLocalCandidates() const { - char attr[256]; - std::vector candidates; - nr_ice_component* comp = STAILQ_FIRST(&ice_media_stream_->components); - while(comp){ - if (comp->state != NR_ICE_COMPONENT_DISABLED) { - nr_ice_candidate *cand = TAILQ_FIRST(&comp->candidates); - while(cand){ - int r = nr_ice_format_candidate_attribute(cand, attr, 255); - if (r == 0) { - candidates.push_back(attr); - } + std::vector GetStreamAttributes() { + std::vector attributes; + test_utils_->sts_target()->Dispatch( + WrapRunnableRet(&attributes, + this, + &IcePeer::GetStreamAttributes_s), + NS_DISPATCH_SYNC); + return attributes; + } - cand = TAILQ_NEXT(cand, entry_comp); - } - } + std::vector GetStreamAttributes_s() { - comp = STAILQ_NEXT(comp, entry); + char **attrs = nullptr; + int attrct; + std::vector ret; + + int r = + nr_ice_media_stream_get_attributes(ice_media_stream_, &attrs, &attrct); + EXPECT_EQ(0, r); + + for (int i=0; i GetGlobalAttributes() { + std::vector attributes; + test_utils_->sts_target()->Dispatch( + WrapRunnableRet(&attributes, + this, + &IcePeer::GetGlobalAttributes_s), + NS_DISPATCH_SYNC); + return attributes; + } + + std::vector GetGlobalAttributes_s() { char **attrs = nullptr; int attrct; @@ -203,6 +222,14 @@ public: } void SetRemoteAttributes(std::vector attributes) { + test_utils_->sts_target()->Dispatch( + WrapRunnable(this, + &IcePeer::SetRemoteAttributes_s, + attributes), + NS_DISPATCH_SYNC); + } + + void SetRemoteAttributes_s(std::vector attributes) { int r; std::vector attrs; @@ -329,11 +356,11 @@ TEST_F(TestNrSocketIceUnitTest, TestIcePeer) { ASSERT_NE(peer.ice_ctx_, nullptr); ASSERT_NE(peer.peer_ctx_, nullptr); ASSERT_NE(peer.ice_media_stream_, nullptr); + ASSERT_EQ(2UL, peer.GetStreamAttributes().size()) + << "Should have ice-ufrag and ice-pwd"; peer.Gather(); - std::vector attrs = peer.GetGlobalAttributes(); - ASSERT_NE(attrs.size(), 0UL); - std::vector candidates = peer.GetLocalCandidates(); - ASSERT_NE(candidates.size(), 0UL); + ASSERT_LT(2UL, peer.GetStreamAttributes().size()) + << "Should have ice-ufrag, ice-pwd, and at least one candidate."; } TEST_F(TestNrSocketIceUnitTest, TestIcePeersNoNAT) { @@ -348,13 +375,13 @@ TEST_F(TestNrSocketIceUnitTest, TestIcePeersNoNAT) { peer2.Gather(); std::vector attrs = peer.GetGlobalAttributes(); peer2.ParseGlobalAttributes(attrs); - std::vector candidates = peer.GetLocalCandidates(); - peer2.SetRemoteAttributes(candidates); + std::vector attributes = peer.GetStreamAttributes(); + peer2.SetRemoteAttributes(attributes); attrs = peer2.GetGlobalAttributes(); peer.ParseGlobalAttributes(attrs); - candidates = peer2.GetLocalCandidates(); - peer.SetRemoteAttributes(candidates); + attributes = peer2.GetStreamAttributes(); + peer.SetRemoteAttributes(attributes); peer2.StartChecks(); peer.StartChecks(); @@ -406,13 +433,13 @@ TEST_F(TestNrSocketIceUnitTest, TestIcePeersPacketLoss) { peer2.Gather(); std::vector attrs = peer.GetGlobalAttributes(); peer2.ParseGlobalAttributes(attrs); - std::vector candidates = peer.GetLocalCandidates(); - peer2.SetRemoteAttributes(candidates); + std::vector attributes = peer.GetStreamAttributes(); + peer2.SetRemoteAttributes(attributes); attrs = peer2.GetGlobalAttributes(); peer.ParseGlobalAttributes(attrs); - candidates = peer2.GetLocalCandidates(); - peer.SetRemoteAttributes(candidates); + attributes = peer2.GetStreamAttributes(); + peer.SetRemoteAttributes(attributes); peer2.StartChecks(); peer.StartChecks(); diff --git a/media/mtransport/test/transport_unittests.cpp b/media/mtransport/test/transport_unittests.cpp index 1c0f9a73a7b2..b36fea692737 100644 --- a/media/mtransport/test/transport_unittests.cpp +++ b/media/mtransport/test/transport_unittests.cpp @@ -26,7 +26,7 @@ #include "mediapacket.h" #include "dtlsidentity.h" -#include "nricectxhandler.h" +#include "nricectx.h" #include "nricemediastream.h" #include "transportflow.h" #include "transportlayer.h" @@ -443,8 +443,8 @@ class TransportTestPeer : public sigslot::has_slots<> { lossy_(new TransportLayerLossy()), dtls_(new TransportLayerDtls()), identity_(DtlsIdentity::Generate()), - ice_ctx_(NrIceCtxHandler::Create(name)), - streams_(), candidates_(), + ice_ctx_(NrIceCtx::Create(name)), + streams_(), peer_(nullptr), gathering_complete_(false), enabled_cipersuites_(), @@ -454,7 +454,7 @@ class TransportTestPeer : public sigslot::has_slots<> { UniquePtr server(NrIceStunServer::Create( std::string((char *)"stun.services.mozilla.com"), 3478)); stun_servers.push_back(*server); - EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->ctx()->SetStunServers(stun_servers))); + EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers))); dtls_->SetIdentity(identity_); dtls_->SetRole(offerer_ ? @@ -610,7 +610,7 @@ class TransportTestPeer : public sigslot::has_slots<> { nsresult res; // Attach our slots - ice_ctx_->ctx()->SignalGatheringStateChange. + ice_ctx_->SignalGatheringStateChange. connect(this, &TransportTestPeer::GatheringStateChange); char name[100]; @@ -618,11 +618,10 @@ class TransportTestPeer : public sigslot::has_slots<> { (int)streams_.size()); // Create the media stream - RefPtr stream = - ice_ctx_->CreateStream(static_cast(name), 1); + RefPtr stream = ice_ctx_->CreateStream(name, name, 1); ASSERT_TRUE(stream != nullptr); - ice_ctx_->ctx()->SetStream(name, stream); + stream->SetIceCredentials("ufrag", "pass"); streams_.push_back(stream); // Listen for candidates @@ -646,7 +645,7 @@ class TransportTestPeer : public sigslot::has_slots<> { // Start gathering test_utils_->sts_target()->Dispatch( WrapRunnableRet(&res, - ice_ctx_->ctx(), + ice_ctx_, &NrIceCtx::StartGathering, false, false), @@ -665,7 +664,6 @@ class TransportTestPeer : public sigslot::has_slots<> { // New candidate void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) { std::cerr << "Got candidate " << candidate << std::endl; - candidates_[stream->name()].push_back(candidate); } void GatheringStateChange(NrIceCtx* ctx, @@ -689,23 +687,23 @@ class TransportTestPeer : public sigslot::has_slots<> { // First send attributes test_utils_->sts_target()->Dispatch( - WrapRunnableRet(&res, peer_->ice_ctx_->ctx(), + WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::ParseGlobalAttributes, - ice_ctx_->ctx()->GetGlobalAttributes()), + ice_ctx_->GetGlobalAttributes()), NS_DISPATCH_SYNC); ASSERT_TRUE(NS_SUCCEEDED(res)); for (size_t i=0; ists_target()->Dispatch( - WrapRunnableRet(&res, peer_->streams_[i], &NrIceMediaStream::ParseAttributes, - candidates_[streams_[i]->name()]), NS_DISPATCH_SYNC); + WrapRunnableRet(&res, peer_->streams_[i], &NrIceMediaStream::ConnectToPeer, + "ufrag", "pass", streams_[i]->GetAttributes()), NS_DISPATCH_SYNC); ASSERT_TRUE(NS_SUCCEEDED(res)); } // Start checks on the other peer. test_utils_->sts_target()->Dispatch( - WrapRunnableRet(&res, peer_->ice_ctx_->ctx(), &NrIceCtx::StartChecks, + WrapRunnableRet(&res, peer_->ice_ctx_, &NrIceCtx::StartChecks, offerer_), NS_DISPATCH_SYNC); ASSERT_TRUE(NS_SUCCEEDED(res)); @@ -831,9 +829,8 @@ class TransportTestPeer : public sigslot::has_slots<> { TransportLayerDtls *dtls_; TransportLayerIce *ice_; RefPtr identity_; - RefPtr ice_ctx_; + RefPtr ice_ctx_; std::vector > streams_; - std::map > candidates_; TransportTestPeer *peer_; bool gathering_complete_; unsigned char fingerprint_[TransportLayerDtls::kMaxDigestLength]; diff --git a/media/mtransport/test/turn_unittest.cpp b/media/mtransport/test/turn_unittest.cpp index b651a71dc244..7a88962cb64e 100644 --- a/media/mtransport/test/turn_unittest.cpp +++ b/media/mtransport/test/turn_unittest.cpp @@ -74,8 +74,7 @@ extern "C" { } #include "nricemediastream.h" -#include "nricectxhandler.h" - +#include "nricectx.h" using namespace mozilla; diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c index 7a4ee1d96456..6c80621fd61f 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.c @@ -306,11 +306,7 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp) cand=*candp; - if (cand->state == NR_ICE_CAND_STATE_INITIALIZING) { - /* Make sure the ICE ctx isn't still waiting around for this candidate - * to init. */ - nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED); - } + nr_ice_candidate_stop_gathering(cand); switch(cand->type){ case HOST: @@ -350,12 +346,6 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp) break; } - NR_async_timer_cancel(cand->delay_timer); - NR_async_timer_cancel(cand->ready_cb_timer); - if(cand->resolver_handle){ - nr_resolver_cancel(cand->ctx->resolver,cand->resolver_handle); - } - RFREE(cand->foundation); RFREE(cand->label); RFREE(cand); @@ -363,6 +353,25 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp) return(0); } +void nr_ice_candidate_stop_gathering(nr_ice_candidate *cand) + { + if (cand->state == NR_ICE_CAND_STATE_INITIALIZING) { + /* Make sure the ICE ctx isn't still waiting around for this candidate + * to init. */ + nr_ice_candidate_mark_done(cand, NR_ICE_CAND_STATE_FAILED); + } + + NR_async_timer_cancel(cand->delay_timer); + cand->delay_timer=0; + NR_async_timer_cancel(cand->ready_cb_timer); + cand->ready_cb_timer=0; + + if(cand->resolver_handle){ + nr_resolver_cancel(cand->ctx->resolver,cand->resolver_handle); + cand->resolver_handle=0; + } + } + /* This algorithm is not super-fast, but I don't think we need a hash table just yet and it produces a small foundation string */ static int nr_ice_get_foundation(nr_ice_ctx *ctx,nr_ice_candidate *cand) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h index ce05dc85efb4..d5c806446e97 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate.h @@ -110,6 +110,7 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo void nr_ice_candidate_compute_codeword(nr_ice_candidate *cand); int nr_ice_candidate_process_stun(nr_ice_candidate *cand, UCHAR *msg, int len, nr_transport_addr *faddr); int nr_ice_candidate_destroy(nr_ice_candidate **candp); +void nr_ice_candidate_stop_gathering(nr_ice_candidate *cand); int nr_ice_format_candidate_attribute(nr_ice_candidate *cand, char *attr, int maxlen); int nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *attr,nr_ice_media_stream *stream,nr_ice_candidate **candp); int nr_ice_peer_peer_rflx_candidate_create(nr_ice_ctx *ctx,char *label, nr_ice_component *comp,nr_transport_addr *addr, nr_ice_candidate **candp); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c index ebb4cb0c95af..2a4dfabfe04e 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.c @@ -497,7 +497,7 @@ int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_ return(_status); } -int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state) +void nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state) { if(pair->state != NR_ICE_PAIR_STATE_FAILED){ /* If it's already running we need to terminate the stun */ @@ -510,8 +510,6 @@ int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, i } nr_ice_candidate_pair_set_state(pctx,pair,NR_ICE_PAIR_STATE_CANCELLED); } - - return(0); } int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair) @@ -545,10 +543,8 @@ int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair) return(_status); } -int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state) +void nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state) { - int r,_status; - r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/CAND-PAIR(%s): setting pair to state %s: %s", pctx->label,pair->codeword,nr_ice_cand_pair_states[state],pair->as_string); @@ -580,13 +576,8 @@ int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pai if(pair->state==NR_ICE_PAIR_STATE_FAILED || pair->state==NR_ICE_PAIR_STATE_CANCELLED){ - if(r=nr_ice_component_failed_pair(pair->remote->component, pair)) - ABORT(r); + nr_ice_component_failed_pair(pair->remote->component, pair); } - - _status=0; - abort: - return(_status); } int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h index 1cb418be82c6..e4be06b82104 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_candidate_pair.h @@ -83,9 +83,9 @@ struct nr_ice_cand_pair_ { int nr_ice_candidate_pair_create(nr_ice_peer_ctx *pctx, nr_ice_candidate *lcand,nr_ice_candidate *rcand,nr_ice_cand_pair **pairp); int nr_ice_candidate_pair_unfreeze(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair); int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair); -int nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state); +void nr_ice_candidate_pair_set_state(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair, int state); int nr_ice_candidate_pair_dump_state(nr_ice_cand_pair *pair, FILE *out); -int nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state); +void nr_ice_candidate_pair_cancel(nr_ice_peer_ctx *pctx,nr_ice_cand_pair *pair, int move_to_wait_state); int nr_ice_candidate_pair_select(nr_ice_cand_pair *pair); int nr_ice_candidate_pair_do_triggered_check(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair); int nr_ice_candidate_pair_insert(nr_ice_cand_pair_head *head,nr_ice_cand_pair *pair); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.c b/media/mtransport/third_party/nICEr/src/ice/ice_component.c index 44728f2ae97a..c0b270c5c754 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_component.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.c @@ -657,11 +657,11 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon /* Note: we need to recompute these because we have not yet computed the values in the peer media stream.*/ - lufrag=component->stream->ufrag ? component->stream->ufrag : ctx->ufrag; + lufrag=component->stream->ufrag; assert(lufrag); if (!lufrag) ABORT(R_INTERNAL); - lpwd=component->stream->pwd ? component->stream->pwd :ctx->pwd; + lpwd=component->stream->pwd; assert(lpwd); if (!lpwd) ABORT(R_INTERNAL); @@ -699,6 +699,14 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon return(_status); } +void nr_ice_component_stop_gathering(nr_ice_component *component) + { + nr_ice_candidate *c1,*c2; + TAILQ_FOREACH_SAFE(c1, &component->candidates, entry_comp, c2){ + nr_ice_candidate_stop_gathering(c1); + } + } + static int nr_ice_any_peer_paired(nr_ice_candidate* cand) { nr_ice_peer_ctx* pctx=STAILQ_FIRST(&cand->ctx->peers); while(pctx && pctx->state == NR_ICE_PEER_STATE_UNPAIRED){ @@ -1254,9 +1262,7 @@ static void nr_ice_component_consent_failed(nr_ice_component *comp) } /* We are turning the consent failure into a ICE component failure to * alert the browser via ICE connection state change about this event. */ - if (nr_ice_media_stream_component_failed(comp->stream, comp)) - r_log(LOG_ICE,LOG_ERR,"ICE(%s)/STREAM(%s)/COMP(%d): failed to mark component as failed", - comp->ctx->label, comp->stream->label, comp->component_id); + nr_ice_media_stream_component_failed(comp->stream, comp); } static void nr_ice_component_consent_timeout_cb(NR_SOCKET s, int how, void *cb_arg) @@ -1515,8 +1521,7 @@ int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pa p2->state == NR_ICE_PAIR_STATE_CANCELLED); r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s in trigger check queue because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword); - if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0)) - ABORT(r); + nr_ice_candidate_pair_cancel(pair->pctx,p2,0); } p2=TAILQ_NEXT(p2,triggered_check_queue_entry); @@ -1529,8 +1534,7 @@ int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pa (p2->state == NR_ICE_PAIR_STATE_WAITING))) { r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d)/CAND-PAIR(%s): cancelling FROZEN/WAITING pair %s because CAND-PAIR(%s) was nominated.",comp->stream->pctx->label,comp->stream->label,comp->component_id,p2->codeword,p2->as_string,pair->codeword); - if(r=nr_ice_candidate_pair_cancel(pair->pctx,p2,0)) - ABORT(r); + nr_ice_candidate_pair_cancel(pair->pctx,p2,0); } p2=TAILQ_NEXT(p2,check_queue_entry); @@ -1540,8 +1544,7 @@ int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pa if(r=nr_ice_component_setup_consent(comp)) ABORT(r); - if(r=nr_ice_media_stream_component_nominated(comp->stream,comp)) - ABORT(r); + nr_ice_media_stream_component_nominated(comp->stream,comp); _status=0; abort: @@ -1577,12 +1580,12 @@ static int nr_ice_component_have_all_pairs_failed(nr_ice_component *comp) return(1); } -int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair) +void nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair) { - return nr_ice_component_check_if_failed(comp); + nr_ice_component_check_if_failed(comp); } -int nr_ice_component_check_if_failed(nr_ice_component *comp) +void nr_ice_component_check_if_failed(nr_ice_component *comp) { if (comp->state == NR_ICE_COMPONENT_RUNNING) { /* Don't do anything to streams that aren't currently running */ @@ -1591,11 +1594,9 @@ int nr_ice_component_check_if_failed(nr_ice_component *comp) if (!comp->stream->pctx->trickle_grace_period_timer && nr_ice_component_have_all_pairs_failed(comp)) { r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/STREAM(%s)/COMP(%d): All pairs are failed, and grace period has elapsed. Marking component as failed.",comp->stream->pctx->label,comp->stream->label,comp->component_id); - return nr_ice_media_stream_component_failed(comp->stream,comp); + nr_ice_media_stream_component_failed(comp->stream,comp); } } - - return(0); } int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_component.h b/media/mtransport/third_party/nICEr/src/ice/ice_component.h index 3dc84cfe33e0..ab7cb0b5445d 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_component.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_component.h @@ -86,13 +86,14 @@ typedef STAILQ_HEAD(nr_ice_component_head_,nr_ice_component_) nr_ice_component_h int nr_ice_component_create(struct nr_ice_media_stream_ *stream, int component_id, nr_ice_component **componentp); int nr_ice_component_destroy(nr_ice_component **componentp); int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component); +void nr_ice_component_stop_gathering(nr_ice_component *component); int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned); int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote); int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp, nr_ice_component *pcomp); int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced); int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair); -int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair); -int nr_ice_component_check_if_failed(nr_ice_component *comp); +void nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair); +void nr_ice_component_check_if_failed(nr_ice_component *comp); int nr_ice_component_select_pair(nr_ice_peer_ctx *pctx, nr_ice_component *comp); int nr_ice_component_set_failed(nr_ice_component *comp); int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c index 13bfda3acda5..0642391d3779 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.c @@ -338,28 +338,6 @@ int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out) #define MAXADDRS 100 /* Ridiculously high */ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp) - { - int r,_status; - char *ufrag = 0; - char *pwd = 0; - - if (r=nr_ice_get_new_ice_ufrag(&ufrag)) - ABORT(r); - if (r=nr_ice_get_new_ice_pwd(&pwd)) - ABORT(r); - - if (r=nr_ice_ctx_create_with_credentials(label, flags, ufrag, pwd, ctxp)) - ABORT(r); - - _status=0; - abort: - RFREE(ufrag); - RFREE(pwd); - - return(_status); - } - -int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char *ufrag, char *pwd, nr_ice_ctx **ctxp) { nr_ice_ctx *ctx=0; int r,_status; @@ -375,11 +353,6 @@ int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char *ufrag, ch if(!(ctx->label=r_strdup(label))) ABORT(R_NO_MEMORY); - if(!(ctx->ufrag=r_strdup(ufrag))) - ABORT(r); - if(!(ctx->pwd=r_strdup(pwd))) - ABORT(r); - /* Get the STUN servers */ if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX, (unsigned int *)&ctx->stun_server_ct)||ctx->stun_server_ct==0) { @@ -494,8 +467,6 @@ static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg) RFREE(f1); f1=f2; } - RFREE(ctx->pwd); - RFREE(ctx->ufrag); STAILQ_FOREACH_SAFE(id1, &ctx->ids, entry, id2){ STAILQ_REMOVE(&ctx->ids,id1,nr_ice_stun_id_,entry); @@ -832,11 +803,11 @@ int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg) return(_status); } -int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp) +int nr_ice_add_media_stream(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp) { int r,_status; - if(r=nr_ice_media_stream_create(ctx,label,components,streamp)) + if(r=nr_ice_media_stream_create(ctx,label,ufrag,pwd,components,streamp)) ABORT(r); STAILQ_INSERT_TAIL(&ctx->streams,*streamp,entry); @@ -875,36 +846,9 @@ int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp) int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp) { - char **attrs=0; - int _status; - char *tmp=0; - - if(!(attrs=RCALLOC(sizeof(char *)*2))) - ABORT(R_NO_MEMORY); - - if(!(tmp=RMALLOC(100))) - ABORT(R_NO_MEMORY); - snprintf(tmp,100,"ice-ufrag:%s",ctx->ufrag); - attrs[0]=tmp; - - if(!(tmp=RMALLOC(100))) - ABORT(R_NO_MEMORY); - snprintf(tmp,100,"ice-pwd:%s",ctx->pwd); - attrs[1]=tmp; - - *attrctp=2; - *attrsp=attrs; - - _status=0; - abort: - if (_status){ - if (attrs){ - RFREE(attrs[0]); - RFREE(attrs[1]); - } - RFREE(attrs); - } - return(_status); + *attrctp=0; + *attrsp=0; + return(0); } static int nr_ice_random_string(char *str, int len) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h index 8906fce86866..f95103fe7180 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_ctx.h @@ -123,9 +123,6 @@ struct nr_ice_ctx_ { UINT4 flags; char *label; - char *ufrag; - char *pwd; - UINT4 Ta; nr_ice_stun_server *stun_servers; /* The list of stun servers */ @@ -181,7 +178,7 @@ int nr_ice_set_local_addresses(nr_ice_ctx *ctx, nr_local_addr* stun_addrs, int s int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg); int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand); void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg); -int nr_ice_add_media_stream(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp); +int nr_ice_add_media_stream(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp); int nr_ice_remove_media_stream(nr_ice_ctx *ctx,nr_ice_media_stream **streamp); int nr_ice_get_global_attributes(nr_ice_ctx *ctx,char ***attrsp, int *attrctp); int nr_ice_ctx_deliver_packet(nr_ice_ctx *ctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c index 7239c7594f65..4f55d11fe71e 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c @@ -44,7 +44,7 @@ static char *nr_ice_media_stream_states[]={"INVALID", int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state); -int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ice_media_stream **streamp) +int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp) { int r,_status; nr_ice_media_stream *stream=0; @@ -57,6 +57,12 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ic if(!(stream->label=r_strdup(label))) ABORT(R_NO_MEMORY); + if(!(stream->ufrag=r_strdup(ufrag))) + ABORT(R_NO_MEMORY); + + if(!(stream->pwd=r_strdup(pwd))) + ABORT(R_NO_MEMORY); + stream->ctx=ctx; STAILQ_INIT(&stream->components); @@ -73,6 +79,9 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ic stream->disconnected = 0; stream->component_ct=components; stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED; + stream->obsolete = 0; + stream->r2l_user = 0; + stream->l2r_user = 0; *streamp=stream; _status=0; @@ -143,12 +152,13 @@ int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream) int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp) { - int attrct=0; + int attrct=2; nr_ice_component *comp; char **attrs=0; int index=0; nr_ice_candidate *cand; int r,_status; + char *tmp=0; *attrctp=0; @@ -168,11 +178,6 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr comp=STAILQ_NEXT(comp,entry); } - if(attrct < 1){ - r_log(LOG_ICE,LOG_ERR,"ICE-STREAM(%s): Failed to find any components for stream",stream->label); - ABORT(R_FAILED); - } - /* Make the array we'll need */ if(!(attrs=RCALLOC(sizeof(char *)*attrct))) ABORT(R_NO_MEMORY); @@ -208,6 +213,17 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr comp=STAILQ_NEXT(comp,entry); } + /* Now, ufrag and pwd */ + if(!(tmp=RMALLOC(100))) + ABORT(R_NO_MEMORY); + snprintf(tmp,100,"ice-ufrag:%s",stream->ufrag); + attrs[index++]=tmp; + + if(!(tmp=RMALLOC(100))) + ABORT(R_NO_MEMORY); + snprintf(tmp,100,"ice-pwd:%s",stream->pwd); + attrs[index++]=tmp; + *attrsp=attrs; *attrctp=attrct; @@ -392,6 +408,11 @@ int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream ABORT(R_INTERNAL); } + if (stream->local_stream->obsolete) { + assert(0); + ABORT(R_INTERNAL); + } + /* Even if the stream is completed already remote can still create a new * triggered check request which needs to fire, but not change our stream * state. */ @@ -587,6 +608,42 @@ int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state) return(0); } +void nr_ice_media_stream_stop_checking(nr_ice_media_stream *str) + { + nr_ice_cand_pair *p; + nr_ice_component *comp; + + /* Cancel candidate pairs */ + p=TAILQ_FIRST(&str->check_list); + while(p){ + nr_ice_candidate_pair_cancel(p->pctx,p,0); + p=TAILQ_NEXT(p,check_queue_entry); + } + + if(str->timer) { + NR_async_timer_cancel(str->timer); + str->timer = 0; + } + + /* Cancel consent timers in case it is running already */ + comp=STAILQ_FIRST(&str->components); + while(comp){ + nr_ice_component_consent_destroy(comp); + comp=STAILQ_NEXT(comp,entry); + } + } + +void nr_ice_media_stream_set_obsolete(nr_ice_media_stream *str) + { + nr_ice_component *c1,*c2; + str->obsolete = 1; + + STAILQ_FOREACH_SAFE(c1, &str->components, entry, c2){ + nr_ice_component_stop_gathering(c1); + } + + nr_ice_media_stream_stop_checking(str); + } void nr_ice_media_stream_refresh_consent_all(nr_ice_media_stream *stream) { @@ -626,7 +683,9 @@ void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disco stream->disconnected = disconnected; if (disconnected == NR_ICE_MEDIA_STREAM_DISCONNECTED) { - nr_ice_peer_ctx_disconnected(stream->pctx); + if (!stream->local_stream->obsolete) { + nr_ice_peer_ctx_disconnected(stream->pctx); + } } else { nr_ice_peer_ctx_check_if_connected(stream->pctx); } @@ -658,9 +717,8 @@ int nr_ice_media_stream_check_if_connected(nr_ice_media_stream *stream) /* S OK, this component has a nominated. If every component has a nominated, the stream is ready */ -int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component) +void nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component) { - int r,_status; nr_ice_component *comp; comp=STAILQ_FIRST(&stream->components); @@ -675,7 +733,7 @@ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_c /* At least one un-nominated component */ if(comp) - goto done; + return; /* All done... */ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s)/ICE-STREAM(%s): all active components have nominated candidate pairs",stream->pctx->label,stream->label); @@ -687,25 +745,16 @@ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_c stream->timer=0; } - if (stream->pctx->handler) { + if (stream->pctx->handler && !stream->local_stream->obsolete) { stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,stream->local_stream); } /* Now tell the peer_ctx that we're connected */ - if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx)) - ABORT(r); - - done: - _status=0; - abort: - return(_status); + nr_ice_peer_ctx_check_if_connected(stream->pctx); } -int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component) +void nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component) { - int r,_status; - nr_ice_cand_pair *p2; - component->state=NR_ICE_COMPONENT_FAILED; /* at least one component failed in this media stream, so the entire @@ -713,35 +762,14 @@ int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_comp nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_FAILED); - /* OK, we need to cancel off everything on this component */ - p2=TAILQ_FIRST(&stream->check_list); - while(p2){ - if(r=nr_ice_candidate_pair_cancel(p2->pctx,p2,0)) - ABORT(r); + nr_ice_media_stream_stop_checking(stream); - p2=TAILQ_NEXT(p2,check_queue_entry); - } - - /* Cancel our timer */ - if(stream->timer){ - NR_async_timer_cancel(stream->timer); - stream->timer=0; - } - - /* Cancel consent timers in case it is running already */ - nr_ice_component_consent_destroy(component); - - if (stream->pctx->handler) { + if (stream->pctx->handler && !stream->local_stream->obsolete) { stream->pctx->handler->vtbl->stream_failed(stream->pctx->handler->obj,stream->local_stream); } - /* Now tell the peer_ctx that we're connected */ - if(r=nr_ice_peer_ctx_check_if_connected(stream->pctx)) - ABORT(r); - - _status=0; - abort: - return(_status); + /* Now tell the peer_ctx that we've failed */ + nr_ice_peer_ctx_check_if_connected(stream->pctx); } int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp) diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h index 0730ed34444b..71f84ac6e234 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.h @@ -55,6 +55,10 @@ struct nr_ice_media_stream_ { Data r2l_pass; /* The password for incoming requests */ Data l2r_pass; /* The password for outcoming requests */ int ice_state; + /* The stream is being replaced by another, so it will not continue any ICE + * processing. If this stream is connected already, traffic can continue to + * flow for a limited time while the new stream gets ready. */ + int obsolete; #define NR_ICE_MEDIA_STREAM_UNPAIRED 1 #define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2 @@ -78,7 +82,7 @@ struct nr_ice_media_stream_ { typedef STAILQ_HEAD(nr_ice_media_stream_head_,nr_ice_media_stream_) nr_ice_media_stream_head; -int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,char *label, int components, nr_ice_media_stream **streamp); +int nr_ice_media_stream_create(struct nr_ice_ctx_ *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp); int nr_ice_media_stream_destroy(nr_ice_media_stream **streamp); int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *rstr); int nr_ice_media_stream_initialize(struct nr_ice_ctx_ *ctx, nr_ice_media_stream *stream); @@ -90,13 +94,15 @@ int nr_ice_media_stream_service_pre_answer_requests(nr_ice_peer_ctx *pctx,nr_ice int nr_ice_media_stream_unfreeze_pairs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream); int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, char *foundation); int nr_ice_media_stream_dump_state(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream,FILE *out); -int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component); -int nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component); +void nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_component *component); +void nr_ice_media_stream_component_failed(nr_ice_media_stream *stream,nr_ice_component *component); void nr_ice_media_stream_refresh_consent_all(nr_ice_media_stream *stream); void nr_ice_media_stream_disconnect_all_components(nr_ice_media_stream *stream); void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disconnected); int nr_ice_media_stream_check_if_connected(nr_ice_media_stream *stream); int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state); +void nr_ice_media_stream_stop_checking(nr_ice_media_stream *str); +void nr_ice_media_stream_set_obsolete(nr_ice_media_stream *str); int nr_ice_media_stream_get_best_candidate(nr_ice_media_stream *str, int component, nr_ice_candidate **candp); int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, UCHAR *data, int len); int nr_ice_media_stream_get_active(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component, nr_ice_candidate **local, nr_ice_candidate **remote); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_parser.c b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c index 77e6b6575c43..88964a50219e 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_parser.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_parser.c @@ -380,6 +380,7 @@ nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media if (*str == '\0') ABORT(R_BAD_DATA); + RFREE(stream->ufrag); if ((r=grab_token(&str, &stream->ufrag))) ABORT(r); } @@ -392,6 +393,7 @@ nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media if (*str == '\0') ABORT(R_BAD_DATA); + RFREE(stream->pwd); if ((r=grab_token(&str, &stream->pwd))) ABORT(r); } @@ -490,6 +492,7 @@ nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int } else if (!strncasecmp(str, "ice-lite", 8)) { pctx->peer_lite = 1; + pctx->controlling = 0; fast_forward(&str, 8); } @@ -506,11 +509,6 @@ nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int skip_whitespace(&str); if (*str == '\0') ABORT(R_BAD_DATA); - - RFREE(pctx->peer_ufrag); - pctx->peer_ufrag = 0; - if ((r=grab_token(&str, &pctx->peer_ufrag))) - ABORT(r); } else if (!strncasecmp(str, "ice-pwd:", 8)) { fast_forward(&str, 8); @@ -520,11 +518,6 @@ nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs, int skip_whitespace(&str); if (*str == '\0') ABORT(R_BAD_DATA); - - RFREE(pctx->peer_pwd); - pctx->peer_pwd = 0; - if ((r=grab_token(&str, &pctx->peer_pwd))) - ABORT(r); } else if (!strncasecmp(str, "ice-options:", 12)) { fast_forward(&str, 12); diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c index ea21a9945242..61ec4791cce9 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c +++ b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.c @@ -99,7 +99,7 @@ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_ /* Note: use component_ct from our own stream since components other than this offered by the other side are unusable */ - if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,stream->component_ct,&pstream)) + if(r=nr_ice_media_stream_create(pctx->ctx,stream->label,"","",stream->component_ct,&pstream)) ABORT(r); /* Match up the local and remote components */ @@ -120,12 +120,12 @@ int nr_ice_peer_ctx_parse_stream_attributes(nr_ice_peer_ctx *pctx, nr_ice_media_ /* Now that we have the ufrag and password, compute all the username/password pairs */ - lufrag=stream->ufrag?stream->ufrag:pctx->ctx->ufrag; - lpwd=stream->pwd?stream->pwd:pctx->ctx->pwd; + lufrag=stream->ufrag; + lpwd=stream->pwd; assert(lufrag); assert(lpwd); - rufrag=pstream->ufrag?pstream->ufrag:pctx->peer_ufrag; - rpwd=pstream->pwd?pstream->pwd:pctx->peer_pwd; + rufrag=pstream->ufrag; + rpwd=pstream->pwd; if (!rufrag || !rpwd) ABORT(R_BAD_DATA); @@ -470,8 +470,6 @@ static void nr_ice_peer_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg) NR_async_timer_cancel(pctx->connected_cb_timer); RFREE(pctx->label); - RFREE(pctx->peer_ufrag); - RFREE(pctx->peer_pwd); STAILQ_FOREACH_SAFE(str1, &pctx->peer_streams, entry, str2){ STAILQ_REMOVE(&pctx->peer_streams,str1,nr_ice_media_stream_,entry); @@ -534,10 +532,7 @@ int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first) pctx->connected_cb_timer = 0; pctx->checks_started = 0; - if((r=nr_ice_peer_ctx_check_if_connected(pctx))) { - r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) initial connected check failed",pctx->ctx->label,pctx->label); - ABORT(r); - } + nr_ice_peer_ctx_check_if_connected(pctx); if (pctx->reported_connected) { r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) in %s all streams were done",pctx->ctx->label,pctx->label,__FUNCTION__); @@ -717,29 +712,30 @@ static void nr_ice_peer_ctx_fire_connected(NR_SOCKET s, int how, void *cb_arg) /* Examine all the streams to see if we're maybe miraculously connected */ -int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx) +void nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx) { - int _status; nr_ice_media_stream *str; int failed=0; int succeeded=0; str=STAILQ_FIRST(&pctx->peer_streams); while(str){ - if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED){ - succeeded++; - } - else if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FAILED){ - failed++; - } - else{ - break; + if (!str->local_stream->obsolete){ + if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED){ + succeeded++; + } + else if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FAILED){ + failed++; + } + else{ + break; + } } str=STAILQ_NEXT(str,entry); } if(str) - goto done; /* Something isn't done */ + return; /* Something isn't done */ /* OK, we're finished, one way or another */ r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): all checks completed success=%d fail=%d",pctx->label,succeeded,failed); @@ -752,10 +748,6 @@ int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx) assert(!pctx->connected_cb_timer); NR_ASYNC_TIMER_SET(0,nr_ice_peer_ctx_fire_connected,pctx,&pctx->connected_cb_timer); } - - done: - _status=0; - return(_status); } diff --git a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h index 0f6de9d0eb79..0b0954aa1912 100644 --- a/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h +++ b/media/mtransport/third_party/nICEr/src/ice/ice_peer_ctx.h @@ -52,8 +52,6 @@ struct nr_ice_peer_ctx_ { UCHAR controlling_conflict_resolved; UINT8 tiebreaker; - char *peer_ufrag; - char *peer_pwd; int peer_lite; int peer_ice_mismatch; @@ -89,7 +87,7 @@ void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx); void nr_ice_peer_ctx_connected(nr_ice_peer_ctx *pctx); int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out); int nr_ice_peer_ctx_log_state(nr_ice_peer_ctx *pctx); -int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx); +void nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx); int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp); int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len); int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id); diff --git a/media/mtransport/transportlayerice.cpp b/media/mtransport/transportlayerice.cpp index 048363eca143..3b21aaa43e61 100644 --- a/media/mtransport/transportlayerice.cpp +++ b/media/mtransport/transportlayerice.cpp @@ -85,8 +85,7 @@ namespace mozilla { MOZ_MTLOG_MODULE("mtransport") TransportLayerIce::TransportLayerIce() - : stream_(nullptr), component_(0), - old_stream_(nullptr) + : stream_(nullptr), component_(0) { // setup happens later } @@ -108,17 +107,6 @@ void TransportLayerIce::SetParameters(RefPtr stream, return; } - // If SetParameters is called and we already have a stream_, this means - // we're handling an ICE restart. We need to hold the old stream until - // we know the new stream is working. - if (stream_ && !old_stream_ && (stream_ != stream)) { - // Here we leave the old stream's signals connected until we don't need - // it anymore. They will be disconnected if ice restart is successful. - old_stream_ = stream_; - MOZ_MTLOG(ML_INFO, LAYER_INFO << "SetParameters save old stream(" - << old_stream_->name() << ")"); - } - stream_ = stream; component_ = component; @@ -135,48 +123,11 @@ void TransportLayerIce::PostSetup() { } } -void TransportLayerIce::ResetOldStream() { - if (old_stream_ == nullptr) { - return; // no work to do - } - // ICE restart successful on the new stream, we can forget the old stream now - MOZ_MTLOG(ML_INFO, LAYER_INFO << "ResetOldStream(" << old_stream_->name() - << ")"); - old_stream_->SignalReady.disconnect(this); - old_stream_->SignalFailed.disconnect(this); - old_stream_->SignalPacketReceived.disconnect(this); - old_stream_ = nullptr; -} - -void TransportLayerIce::RestoreOldStream() { - if (old_stream_ == nullptr) { - return; // no work to do - } - // ICE restart rollback, we need to restore the old stream - MOZ_MTLOG(ML_INFO, LAYER_INFO << "RestoreOldStream(" << old_stream_->name() - << ")"); - stream_->SignalReady.disconnect(this); - stream_->SignalFailed.disconnect(this); - stream_->SignalPacketReceived.disconnect(this); - stream_ = old_stream_; - old_stream_ = nullptr; - - if (stream_->state() == NrIceMediaStream::ICE_OPEN) { - IceReady(stream_); - } else if (stream_->state() == NrIceMediaStream::ICE_CLOSED) { - IceFailed(stream_); - } - // No events are fired when the stream is ICE_CONNECTING. If the - // restored stream is ICE_CONNECTING, IceReady/IceFailed will fire - // later. -} - TransportResult TransportLayerIce::SendPacket(MediaPacket& packet) { CheckThread(); - // use old_stream_ until stream_ is ready - nsresult res = (old_stream_?old_stream_:stream_)->SendPacket(component_, - packet.data(), - packet.len()); + nsresult res = stream_->SendPacket(component_, + packet.data(), + packet.len()); if (!NS_SUCCEEDED(res)) { return (res == NS_BASE_STREAM_WOULD_BLOCK) ? diff --git a/media/mtransport/transportlayerice.h b/media/mtransport/transportlayerice.h index 6bb7a87ffa15..262d4bae9fb6 100644 --- a/media/mtransport/transportlayerice.h +++ b/media/mtransport/transportlayerice.h @@ -58,9 +58,6 @@ class TransportLayerIce : public TransportLayer { RefPtr stream_; int component_; - - // used to hold the old stream - RefPtr old_stream_; }; } // close namespace diff --git a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp index 9097984f448a..92ddb6fc362f 100644 --- a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp +++ b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp @@ -81,32 +81,9 @@ public: } protected: struct TransportData { - std::string mIceUfrag; - std::string mIcePwd; - int iceCredentialSerial; std::map > mFingerprints; }; - void - GenerateNewIceCredentials(const JsepSessionImpl& session, - TransportData& tdata) - { - std::ostringstream ostr; - ostr << session.GetName() << "-" << ++tdata.iceCredentialSerial; - - // Values here semi-borrowed from JSEP draft. - tdata.mIceUfrag = ostr.str() + "-ufrag"; - tdata.mIcePwd = ostr.str() + "-1234567890"; - } - - void - ModifyOffererIceCredentials() - { - GenerateNewIceCredentials(*mSessionOff, *mOffererTransport); - mSessionOff->SetIceCredentials(mOffererTransport->mIceUfrag, - mOffererTransport->mIcePwd); - } - void AddDtlsFingerprint(const std::string& alg, JsepSessionImpl& session, TransportData& tdata) @@ -121,9 +98,6 @@ protected: void AddTransportData(JsepSessionImpl& session, TransportData& tdata) { - tdata.iceCredentialSerial = 0; - GenerateNewIceCredentials(session, tdata); - session.SetIceCredentials(tdata.mIceUfrag, tdata.mIcePwd); AddDtlsFingerprint("sha-1", session, tdata); AddDtlsFingerprint("sha-256", session, tdata); } @@ -816,13 +790,6 @@ protected: JsepAnswerOptions options; std::string answer; - // detect ice restart and generate new ice credentials (like - // PeerConnectionImpl does). - if (mSessionAns->RemoteIceIsRestarting()) { - GenerateNewIceCredentials(*mSessionAns, *mAnswererTransport); - mSessionAns->SetIceCredentials(mAnswererTransport->mIceUfrag, - mAnswererTransport->mIcePwd); - } nsresult rv = mSessionAns->CreateAnswer(options, &answer); EXPECT_EQ(NS_OK, rv); @@ -1342,9 +1309,10 @@ protected: const char* replaceStr) const { if (searchStr[0] == '\0') return; - size_t pos; - while ((pos = sdp->find(searchStr)) != std::string::npos) { + size_t pos = 0; + while ((pos = sdp->find(searchStr, pos)) != std::string::npos) { sdp->replace(pos, strlen(searchStr), replaceStr); + pos += strlen(replaceStr); } } @@ -1533,8 +1501,8 @@ private: if (!mSdpHelper.IsBundleSlave(*sdp, i)) { const SdpAttributeList& attrs = msection.GetAttributeList(); - ASSERT_EQ(source.mIceUfrag, attrs.GetIceUfrag()); - ASSERT_EQ(source.mIcePwd, attrs.GetIcePwd()); + ASSERT_FALSE(attrs.GetIceUfrag().empty()); + ASSERT_FALSE(attrs.GetIcePwd().empty()); const SdpFingerprintAttributeList& fps = attrs.GetFingerprint(); for (auto fp = fps.mFingerprints.begin(); fp != fps.mFingerprints.end(); ++fp) { @@ -4286,7 +4254,6 @@ TEST_F(JsepSessionTest, TestIceRestart) JsepOfferOptions options; options.mIceRestart = Some(true); - ModifyOffererIceCredentials(); std::string reoffer = CreateOffer(Some(options)); SetLocalOffer(reoffer, CHECK_SUCCESS); @@ -4333,6 +4300,26 @@ TEST_F(JsepSessionTest, TestIceRestart) reanswerMediaAttrs.GetIcePwd().c_str()); ASSERT_NE(answerMediaAttrs.GetIceUfrag().c_str(), reanswerMediaAttrs.GetIceUfrag().c_str()); + + auto offererTransceivers = mSessionOff->GetTransceivers(); + auto answererTransceivers = mSessionAns->GetTransceivers(); + ASSERT_EQ(reofferMediaAttrs.GetIceUfrag(), + offererTransceivers[0]->mTransport.mLocalUfrag); + ASSERT_EQ(reofferMediaAttrs.GetIceUfrag(), + answererTransceivers[0]->mTransport.mIce->GetUfrag()); + ASSERT_EQ(reofferMediaAttrs.GetIcePwd(), + offererTransceivers[0]->mTransport.mLocalPwd); + ASSERT_EQ(reofferMediaAttrs.GetIcePwd(), + answererTransceivers[0]->mTransport.mIce->GetPassword()); + + ASSERT_EQ(reanswerMediaAttrs.GetIceUfrag(), + answererTransceivers[0]->mTransport.mLocalUfrag); + ASSERT_EQ(reanswerMediaAttrs.GetIceUfrag(), + offererTransceivers[0]->mTransport.mIce->GetUfrag()); + ASSERT_EQ(reanswerMediaAttrs.GetIcePwd(), + answererTransceivers[0]->mTransport.mLocalPwd); + ASSERT_EQ(reanswerMediaAttrs.GetIcePwd(), + offererTransceivers[0]->mTransport.mIce->GetPassword()); } TEST_F(JsepSessionTest, TestAnswererIndicatingIceRestart) @@ -4354,7 +4341,8 @@ TEST_F(JsepSessionTest, TestAnswererIndicatingIceRestart) std::string reanswer = CreateAnswer(); // change the ice pwd and ufrag - ReplaceInSdp(&reanswer, "Answerer-1-", "bad-2-"); + ReplaceInSdp(&reanswer, "a=ice-ufrag:", "a=ice-ufrag:bad-"); + ReplaceInSdp(&reanswer, "a=ice-pwd:", "a=ice-pwd:bad-"); SetLocalAnswer(reanswer, CHECK_SUCCESS); nsresult rv = mSessionOff->SetRemoteDescription(kJsepSdpAnswer, reanswer); ASSERT_NE(NS_OK, rv); // NS_ERROR_INVALID_ARG diff --git a/media/webrtc/signaling/src/jsep/JsepSession.h b/media/webrtc/signaling/src/jsep/JsepSession.h index 00861e487763..2efb275e5efd 100644 --- a/media/webrtc/signaling/src/jsep/JsepSession.h +++ b/media/webrtc/signaling/src/jsep/JsepSession.h @@ -99,13 +99,8 @@ public: } // Set up the ICE And DTLS data. - virtual nsresult SetIceCredentials(const std::string& ufrag, - const std::string& pwd) = 0; - virtual const std::string& GetUfrag() const = 0; - virtual const std::string& GetPwd() const = 0; virtual nsresult SetBundlePolicy(JsepBundlePolicy policy) = 0; virtual bool RemoteIsIceLite() const = 0; - virtual bool RemoteIceIsRestarting() const = 0; virtual std::vector GetIceOptions() const = 0; virtual nsresult AddDtlsFingerprint(const std::string& algorithm, @@ -185,6 +180,7 @@ public: // ICE controlling or controlled virtual bool IsIceControlling() const = 0; virtual bool IsOfferer() const = 0; + virtual bool IsIceRestarting() const = 0; virtual const std::string GetLastError() const diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp index 1fb88e1cde7b..8d3453736ff8 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp @@ -55,6 +55,21 @@ static std::bitset<128> GetForbiddenSdpPayloadTypes() { return forbidden; } +static std::string GetRandomHex() +{ + uint32_t rand; + SECStatus rv = + PK11_GenerateRandom(reinterpret_cast(&rand), sizeof(rand)); + if (rv != SECSuccess) { + MOZ_CRASH(); + return ""; + } + + std::ostringstream os; + os << std::hex << std::setfill('0') << std::setw(8) << rand; + return os.str(); +} + nsresult JsepSessionImpl::Init() { @@ -73,6 +88,8 @@ JsepSessionImpl::Init() mRunSdpComparer = Preferences::GetBool("media.peerconnection.sdp.rust.compare", false); + mIceUfrag = GetRandomHex(); + mIcePwd = GetRandomHex(); return NS_OK; } @@ -112,17 +129,6 @@ JsepSessionImpl::AddTransceiver(RefPtr transceiver) return NS_OK; } -nsresult -JsepSessionImpl::SetIceCredentials(const std::string& ufrag, - const std::string& pwd) -{ - mLastError.clear(); - mIceUfrag = ufrag; - mIcePwd = pwd; - - return NS_OK; -} - nsresult JsepSessionImpl::SetBundlePolicy(JsepBundlePolicy policy) { @@ -420,13 +426,15 @@ JsepSessionImpl::CreateOffer(const JsepOfferOptions& options, std::string* offer) { mLastError.clear(); - mLocalIceIsRestarting = options.mIceRestart.isSome() && *(options.mIceRestart); if (mState != kJsepStateStable) { JSEP_SET_ERROR("Cannot create offer in state " << GetStateStr(mState)); return NS_ERROR_UNEXPECTED; } + // This is one of those places where CreateOffer sets some state. + SetIceRestarting(options.mIceRestart.isSome() && *(options.mIceRestart)); + UniquePtr sdp; // Make the basic SDP that is common to offer/answer. @@ -976,7 +984,7 @@ JsepSessionImpl::SetRemoteDescription(JsepSdpType type, const std::string& sdp) if (NS_SUCCEEDED(rv)) { mRemoteIsIceLite = iceLite; mIceOptions = iceOptions; - mRemoteIceIsRestarting = iceRestarting; + SetIceRestarting(iceRestarting); } return rv; @@ -986,6 +994,10 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(const UniquePtr& local, const UniquePtr& remote) { + // local ufrag/pwd has been negotiated; we will never go back to the old ones + mOldIceUfrag.clear(); + mOldIcePwd.clear(); + bool remoteIceLite = remote->GetAttributeList().HasAttribute(SdpAttribute::kIceLiteAttribute); @@ -1136,13 +1148,14 @@ JsepSessionImpl::EnsureHasOwnTransport(const SdpMediaSection& msection, { JsepTransport& transport = transceiver->mTransport; - // TODO: Detect ICE restart on a per-msection basis. - if (mLocalIceIsRestarting || mRemoteIceIsRestarting || - !transceiver->HasOwnTransport()) { + if (!transceiver->HasOwnTransport()) { // Transceiver didn't own this transport last time, it won't now either transport.Close(); } + transport.mLocalUfrag = msection.GetAttributeList().GetIceUfrag(); + transport.mLocalPwd = msection.GetAttributeList().GetIcePwd(); + transceiver->ClearBundleLevel(); if (mSdpHelper.HasRtcp(msection.GetProtocol())) { @@ -1169,7 +1182,9 @@ JsepSessionImpl::FinalizeTransport(const SdpAttributeList& remote, return NS_OK; } - if (!transport->mIce) { + if (!transport->mIce || + transport->mIce->mUfrag != remote.GetIceUfrag() || + transport->mIce->mPwd != remote.GetIcePwd()) { UniquePtr ice = MakeUnique(); // We do sanity-checking for these in ParseSdp @@ -1254,8 +1269,7 @@ JsepSessionImpl::CopyPreviousTransportParams(const Sdp& oldAnswer, mSdpHelper.AreOldTransportParamsValid(oldAnswer, offerersPreviousSdp, newOffer, - i) && - !mRemoteIceIsRestarting + i) ) { // If newLocal is an offer, this will be the number of components we used // last time, and if it is an answer, this will be the number of @@ -1798,8 +1812,7 @@ JsepSessionImpl::ValidateRemoteDescription(const Sdp& description) bool differ = mSdpHelper.IceCredentialsDiffer(newMsection, oldMsection); - // Detect bad answer ICE restart when offer doesn't request ICE restart - if (mIsOfferer && differ && !mLocalIceIsRestarting) { + if (mIsOfferer && differ && !IsIceRestarting()) { JSEP_SET_ERROR("Remote description indicates ICE restart but offer did not " "request ICE restart (new remote description changes either " "the ice-ufrag or ice-pwd)"); @@ -2366,6 +2379,28 @@ JsepSessionImpl::GetAnswer() const : mCurrentLocalDescription.get(); } +void +JsepSessionImpl::SetIceRestarting(bool restarting) +{ + if (restarting) { + // not restarting -> restarting + if (!IsIceRestarting()) { + // We don't set this more than once, so the old ufrag/pwd is preserved + // even if we CreateOffer({iceRestart:true}) multiple times in a row. + mOldIceUfrag = mIceUfrag; + mOldIcePwd = mIcePwd; + } + mIceUfrag = GetRandomHex(); + mIcePwd = GetRandomHex(); + } else if (IsIceRestarting()) { + // restarting -> not restarting, restore old ufrag/pwd + mIceUfrag = mOldIceUfrag; + mIcePwd = mOldIcePwd; + mOldIceUfrag.clear(); + mOldIcePwd.clear(); + } +} + nsresult JsepSessionImpl::Close() { diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h index a3a3f8f4b443..04d987ff44f8 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h @@ -36,9 +36,7 @@ public: mIsOfferer(false), mWasOffererLastTime(false), mIceControlling(false), - mLocalIceIsRestarting(false), mRemoteIsIceLite(false), - mRemoteIceIsRestarting(false), mBundlePolicy(kBundleBalanced), mSessionId(0), mSessionVersion(0), @@ -54,10 +52,6 @@ public: // Implement JsepSession methods. virtual nsresult Init() override; - virtual nsresult SetIceCredentials(const std::string& ufrag, - const std::string& pwd) override; - virtual const std::string& GetUfrag() const override { return mIceUfrag; } - virtual const std::string& GetPwd() const override { return mIcePwd; } nsresult SetBundlePolicy(JsepBundlePolicy policy) override; virtual bool @@ -66,12 +60,6 @@ public: return mRemoteIsIceLite; } - virtual bool - RemoteIceIsRestarting() const override - { - return mRemoteIceIsRestarting; - } - virtual std::vector GetIceOptions() const override { @@ -160,6 +148,12 @@ public: return mIsOfferer; } + virtual bool + IsIceRestarting() const override + { + return !mOldIceUfrag.empty(); + } + virtual const std::vector>& GetTransceivers() const override { return mTransceivers; @@ -262,6 +256,7 @@ private: mozilla::Sdp* GetParsedRemoteDescription(JsepDescriptionPendingOrCurrent type) const; const Sdp* GetAnswer() const; + void SetIceRestarting(bool restarting); // !!!NOT INDEXED BY LEVEL!!! These are in the order they were created in. The // level mapping is done with JsepTransceiver::mLevel. @@ -274,9 +269,9 @@ private: bool mIceControlling; std::string mIceUfrag; std::string mIcePwd; - bool mLocalIceIsRestarting; + std::string mOldIceUfrag; + std::string mOldIcePwd; bool mRemoteIsIceLite; - bool mRemoteIceIsRestarting; std::vector mIceOptions; JsepBundlePolicy mBundlePolicy; std::vector mDtlsFingerprints; diff --git a/media/webrtc/signaling/src/jsep/JsepTransport.h b/media/webrtc/signaling/src/jsep/JsepTransport.h index 6dfacb6238ef..24c8f0efa786 100644 --- a/media/webrtc/signaling/src/jsep/JsepTransport.h +++ b/media/webrtc/signaling/src/jsep/JsepTransport.h @@ -101,6 +101,8 @@ public: mDtls.reset(orig.mDtls ? new JsepDtlsTransport(*orig.mDtls) : nullptr); mTransportId = orig.mTransportId; mComponents = orig.mComponents; + mLocalUfrag = orig.mLocalUfrag; + mLocalPwd = orig.mLocalPwd; } return *this; } @@ -111,6 +113,8 @@ public: mTransportId.clear(); mIce.reset(); mDtls.reset(); + mLocalUfrag.clear(); + mLocalPwd.clear(); } // Unique identifier for this transport within this call. Group? @@ -122,6 +126,8 @@ public: // Number of required components. size_t mComponents; + std::string mLocalUfrag; + std::string mLocalPwd; }; } // namespace mozilla diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 1930a14bc9a0..27c852f86cd6 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -692,15 +692,6 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver, return res; } - res = mJsepSession->SetIceCredentials(mMedia->ice_ctx()->ufrag(), - mMedia->ice_ctx()->pwd()); - if (NS_FAILED(res)) { - CSFLogError(LOGTAG, "%s: Couldn't set ICE credentials, res=%u", - __FUNCTION__, - static_cast(res)); - return res; - } - res = mJsepSession->SetBundlePolicy(aConfiguration.getBundlePolicy()); if (NS_FAILED(res)) { CSFLogError(LOGTAG, "%s: Couldn't set bundle policy, res=%u, error=%s", @@ -1481,13 +1472,6 @@ NS_IMETHODIMP PeerConnectionImpl::CreateOffer(const JsepOfferOptions& aOptions) { PC_AUTO_ENTER_API_CALL(true); - bool restartIce = aOptions.mIceRestart.isSome() && *(aOptions.mIceRestart); - if (!restartIce && - mMedia->GetIceRestartState() == - PeerConnectionMedia::ICE_RESTART_PROVISIONAL) { - RollbackIceRestart(); - } - RefPtr pco = do_QueryObjectReferent(mPCObserver); if (!pco) { return NS_OK; @@ -1503,36 +1487,7 @@ PeerConnectionImpl::CreateOffer(const JsepOfferOptions& aOptions) CSFLogDebug(LOGTAG, "CreateOffer()"); - bool iceRestartPrimed = false; - nsresult nrv; - if (restartIce && - !mJsepSession->GetLocalDescription(kJsepDescriptionCurrent).empty()) { - // If restart is requested and a restart is already in progress, we - // need to make room for the restart request so we either rollback - // or finalize to "clear" the previous restart. - if (mMedia->GetIceRestartState() == - PeerConnectionMedia::ICE_RESTART_PROVISIONAL) { - // we're mid-restart and can rollback - RollbackIceRestart(); - } else if (mMedia->GetIceRestartState() == - PeerConnectionMedia::ICE_RESTART_COMMITTED) { - // we're mid-restart and can't rollback, finalize restart even - // though we're not really ready yet - FinalizeIceRestart(); - } - - CSFLogInfo(LOGTAG, "Offerer restarting ice"); - nrv = SetupIceRestartCredentials(); - if (NS_FAILED(nrv)) { - CSFLogError(LOGTAG, "%s: SetupIceRestart failed, res=%u", - __FUNCTION__, - static_cast(nrv)); - return nrv; - } - iceRestartPrimed = true; - } - - nrv = ConfigureJsepSessionCodecs(); + nsresult nrv = ConfigureJsepSessionCodecs(); if (NS_FAILED(nrv)) { CSFLogError(LOGTAG, "Failed to configure codecs"); return nrv; @@ -1558,19 +1513,8 @@ PeerConnectionImpl::CreateOffer(const JsepOfferOptions& aOptions) CSFLogError(LOGTAG, "%s: pc = %s, error = %s", __FUNCTION__, mHandle.c_str(), errorString.c_str()); - if (iceRestartPrimed) { - // reset the ice credentials because CreateOffer failed - ResetIceCredentials(); - } - pco->OnCreateOfferError(error, ObString(errorString.c_str()), rv); } else { - // wait until we know CreateOffer succeeds before we actually start - // the ice restart gears turning. - if (iceRestartPrimed) { - BeginIceRestart(); - } - UpdateSignalingState(); pco->OnCreateOfferSuccess(ObString(offer.c_str()), rv); } @@ -1590,32 +1534,13 @@ PeerConnectionImpl::CreateAnswer() CSFLogDebug(LOGTAG, "CreateAnswer()"); - bool iceRestartPrimed = false; - nsresult nrv; - if (mJsepSession->RemoteIceIsRestarting()) { - if (mMedia->GetIceRestartState() == - PeerConnectionMedia::ICE_RESTART_COMMITTED) { - FinalizeIceRestart(); - } else if (!mMedia->IsIceRestarting()) { - CSFLogInfo(LOGTAG, "Answerer restarting ice"); - nrv = SetupIceRestartCredentials(); - if (NS_FAILED(nrv)) { - CSFLogError(LOGTAG, "%s: SetupIceRestart failed, res=%u", - __FUNCTION__, - static_cast(nrv)); - return nrv; - } - iceRestartPrimed = true; - } - } - STAMP_TIMECARD(mTimeCard, "Create Answer"); // TODO(bug 1098015): Once RTCAnswerOptions is standardized, we'll need to // add it as a param to CreateAnswer, and convert it here. JsepAnswerOptions options; std::string answer; - nrv = mJsepSession->CreateAnswer(options, &answer); + nsresult nrv = mJsepSession->CreateAnswer(options, &answer); JSErrorResult rv; if (NS_FAILED(nrv)) { Error error; @@ -1631,19 +1556,8 @@ PeerConnectionImpl::CreateAnswer() CSFLogError(LOGTAG, "%s: pc = %s, error = %s", __FUNCTION__, mHandle.c_str(), errorString.c_str()); - if (iceRestartPrimed) { - // reset the ice credentials because CreateAnswer failed - ResetIceCredentials(); - } - pco->OnCreateAnswerError(error, ObString(errorString.c_str()), rv); } else { - // wait until we know CreateAnswer succeeds before we actually start - // the ice restart gears turning. - if (iceRestartPrimed) { - BeginIceRestart(); - } - UpdateSignalingState(); pco->OnCreateAnswerSuccess(ObString(answer.c_str()), rv); } @@ -1651,82 +1565,6 @@ PeerConnectionImpl::CreateAnswer() return NS_OK; } -nsresult -PeerConnectionImpl::SetupIceRestartCredentials() -{ - if (mMedia->IsIceRestarting()) { - CSFLogError(LOGTAG, "%s: ICE already restarting", - __FUNCTION__); - return NS_ERROR_UNEXPECTED; - } - - std::string ufrag = mMedia->ice_ctx()->GetNewUfrag(); - std::string pwd = mMedia->ice_ctx()->GetNewPwd(); - if (ufrag.empty() || pwd.empty()) { - CSFLogError(LOGTAG, "%s: Bad ICE credentials (ufrag:'%s'/pwd:'%s')", - __FUNCTION__, - ufrag.c_str(), pwd.c_str()); - return NS_ERROR_UNEXPECTED; - } - - // hold on to the current ice creds in case of rollback - mPreviousIceUfrag = mJsepSession->GetUfrag(); - mPreviousIcePwd = mJsepSession->GetPwd(); - - nsresult nrv = mJsepSession->SetIceCredentials(ufrag, pwd); - if (NS_FAILED(nrv)) { - CSFLogError(LOGTAG, "%s: Couldn't set ICE credentials, res=%u", - __FUNCTION__, - static_cast(nrv)); - return nrv; - } - - return NS_OK; -} - -void -PeerConnectionImpl::BeginIceRestart() -{ - mMedia->BeginIceRestart(mJsepSession->GetUfrag(), mJsepSession->GetPwd()); -} - -nsresult -PeerConnectionImpl::ResetIceCredentials() -{ - nsresult nrv = mJsepSession->SetIceCredentials(mPreviousIceUfrag, mPreviousIcePwd); - mPreviousIceUfrag = ""; - mPreviousIcePwd = ""; - - if (NS_FAILED(nrv)) { - CSFLogError(LOGTAG, "%s: Couldn't reset ICE credentials, res=%u", - __FUNCTION__, - static_cast(nrv)); - return nrv; - } - - return NS_OK; -} - -nsresult -PeerConnectionImpl::RollbackIceRestart() -{ - mMedia->RollbackIceRestart(); - ++mIceRollbackCount; - - // put back the previous ice creds - return ResetIceCredentials(); -} - -void -PeerConnectionImpl::FinalizeIceRestart() -{ - mMedia->FinalizeIceRestart(); - // clear the previous ice creds since they are no longer needed - mPreviousIceUfrag = ""; - mPreviousIcePwd = ""; - ++mIceRestartCount; -} - NS_IMETHODIMP PeerConnectionImpl::SetLocalDescription(int32_t aAction, const char* aSDP) { @@ -1750,6 +1588,7 @@ PeerConnectionImpl::SetLocalDescription(int32_t aAction, const char* aSDP) mLocalRequestedSDP = aSDP; + bool wasRestartingIce = mJsepSession->IsIceRestarting(); JsepSdpType sdpType; switch (aAction) { case IPeerConnection::kActionOffer: @@ -1789,6 +1628,9 @@ PeerConnectionImpl::SetLocalDescription(int32_t aAction, const char* aSDP) __FUNCTION__, mHandle.c_str(), errorString.c_str()); pco->OnSetLocalDescriptionError(error, ObString(errorString.c_str()), rv); } else { + if (wasRestartingIce) { + RecordIceRestartStatistics(sdpType); + } UpdateSignalingState(sdpType == mozilla::kJsepSdpRollback); pco->OnSetLocalDescriptionSuccess(rv); } @@ -1849,6 +1691,7 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) STAMP_TIMECARD(mTimeCard, "Set Remote Description"); mRemoteRequestedSDP = aSDP; + bool wasRestartingIce = mJsepSession->IsIceRestarting(); JsepSdpType sdpType; switch (action) { case IPeerConnection::kActionOffer: @@ -1934,6 +1777,9 @@ PeerConnectionImpl::SetRemoteDescription(int32_t action, const char* aSDP) } } + if (wasRestartingIce) { + RecordIceRestartStatistics(sdpType); + } UpdateSignalingState(sdpType == mozilla::kJsepSdpRollback); pco->OnSetRemoteDescriptionSuccess(jrv); @@ -2836,15 +2682,6 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState, mSignalingState = aSignalingState; if (mSignalingState == PCImplSignalingState::SignalingStable) { - if (mMedia->GetIceRestartState() == - PeerConnectionMedia::ICE_RESTART_PROVISIONAL) { - if (rollback) { - RollbackIceRestart(); - } else { - mMedia->CommitIceRestart(); - } - } - // If we're rolling back a local offer, we might need to remove some // transports, and stomp some MediaPipeline setup, but nothing further // needs to be done. @@ -3125,14 +2962,6 @@ void PeerConnectionImpl::IceConnectionStateChange( mIceConnectionState = domState; - if (mIceConnectionState == PCImplIceConnectionState::Connected || - mIceConnectionState == PCImplIceConnectionState::Completed || - mIceConnectionState == PCImplIceConnectionState::Failed) { - if (mMedia->IsIceRestarting()) { - FinalizeIceRestart(); - } - } - // Uncount this connection as active on the inner window upon close. if (mWindow && mActiveOnWindow && mIceConnectionState == PCImplIceConnectionState::Closed) { mWindow->RemovePeerConnection(); @@ -3726,6 +3555,22 @@ PeerConnectionImpl::RecordLongtermICEStatistics() { WebrtcGlobalInformation::StoreLongTermICEStatistics(*this); } +void +PeerConnectionImpl::RecordIceRestartStatistics(JsepSdpType type) +{ + switch (type) { + case mozilla::kJsepSdpOffer: + case mozilla::kJsepSdpPranswer: + break; + case mozilla::kJsepSdpAnswer: + ++mIceRestartCount; + break; + case mozilla::kJsepSdpRollback: + ++mIceRollbackCount; + break; + } +} + void PeerConnectionImpl::IceStreamReady(NrIceMediaStream *aStream) { diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h index c20136c01a15..26f947523d00 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h @@ -687,12 +687,6 @@ private: dom::MediaStreamTrack* aSendTrack, ErrorResult& aRv); - nsresult SetupIceRestartCredentials(); - void BeginIceRestart(); - nsresult ResetIceCredentials(); - nsresult RollbackIceRestart(); - void FinalizeIceRestart(); - static void GetStatsForPCObserver_s( const std::string& pcHandle, nsAutoPtr query); @@ -710,6 +704,8 @@ private: // or other things. void RecordLongtermICEStatistics(); + void RecordIceRestartStatistics(JsepSdpType type); + // Timecard used to measure processing time. This should be the first class // attribute so that we accurately measure the time required to instantiate // any other attributes of this class. @@ -773,8 +769,6 @@ private: // The JSEP negotiation session. mozilla::UniquePtr mUuidGen; mozilla::UniquePtr mJsepSession; - std::string mPreviousIceUfrag; // used during rollback of ice restart - std::string mPreviousIcePwd; // used during rollback of ice restart unsigned long mIceRestartCount; unsigned long mIceRollbackCount; diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 7584075f8d4d..65a27b38b89f 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -98,7 +98,7 @@ PeerConnectionMedia::ProtocolProxyQueryHandler::SetProxyOnPcm( return; } - if (pcm_->mIceCtxHdlr.get()) { + if (pcm_->mIceCtx.get()) { assert(httpsProxyPort >= 0 && httpsProxyPort < (1 << 16)); // Note that this could check if PrivacyRequested() is set on the PC and // remove "webrtc" from the ALPN list. But that would only work if the PC @@ -131,7 +131,7 @@ PeerConnectionMedia::StunAddrsHandler::OnStunAddrsAvailable( // If parent process returns 0 STUN addresses, change ICE connection // state to failed. if (!pcm_->mStunAddrs.Length()) { - pcm_->SignalIceConnectionStateChange(pcm_->mIceCtxHdlr->ctx().get(), + pcm_->SignalIceConnectionStateChange(pcm_->mIceCtx.get(), NrIceCtx::ICE_CTX_FAILED); } @@ -143,13 +143,12 @@ PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent) : mParent(parent), mParentHandle(parent->GetHandle()), mParentName(parent->GetName()), - mIceCtxHdlr(nullptr), + mIceCtx(nullptr), mDNSResolver(new NrIceResolver()), mUuidGen(MakeUnique()), mMainThread(mParent->GetMainThread()), mSTSThread(mParent->GetSTSThread()), mProxyResolveCompleted(false), - mIceRestartState(ICE_RESTART_NONE), mLocalAddrsCompleted(false) { } @@ -253,26 +252,26 @@ nsresult PeerConnectionMedia::Init(const std::vector& stun_serv // setup the stun local addresses IPC async call InitLocalAddrs(); + NrIceCtx::InitializeGlobals(mParent->GetAllowIceLoopback(), + ice_tcp, + mParent->GetAllowIceLinkLocal()); + // TODO(ekr@rtfm.com): need some way to set not offerer later // Looks like a bug in the NrIceCtx API. - mIceCtxHdlr = NrIceCtxHandler::Create("PC:" + mParentName, - mParent->GetAllowIceLoopback(), - ice_tcp, - mParent->GetAllowIceLinkLocal(), - policy); - if(!mIceCtxHdlr) { + mIceCtx = NrIceCtx::Create("PC:" + mParentName, policy); + if(!mIceCtx) { CSFLogError(LOGTAG, "%s: Failed to create Ice Context", __FUNCTION__); return NS_ERROR_FAILURE; } - if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetStunServers(stun_servers))) { + if (NS_FAILED(rv = mIceCtx->SetStunServers(stun_servers))) { CSFLogError(LOGTAG, "%s: Failed to set stun servers", __FUNCTION__); return rv; } // Give us a way to globally turn off TURN support bool disabled = Preferences::GetBool("media.peerconnection.turn.disable", false); if (!disabled) { - if (NS_FAILED(rv = mIceCtxHdlr->ctx()->SetTurnServers(turn_servers))) { + if (NS_FAILED(rv = mIceCtx->SetTurnServers(turn_servers))) { CSFLogError(LOGTAG, "%s: Failed to set turn servers", __FUNCTION__); return rv; } @@ -284,11 +283,11 @@ nsresult PeerConnectionMedia::Init(const std::vector& stun_serv return rv; } if (NS_FAILED(rv = - mIceCtxHdlr->ctx()->SetResolver(mDNSResolver->AllocateResolver()))) { + mIceCtx->SetResolver(mDNSResolver->AllocateResolver()))) { CSFLogError(LOGTAG, "%s: Failed to get dns resolver", __FUNCTION__); return rv; } - ConnectSignals(mIceCtxHdlr->ctx().get()); + ConnectSignals(mIceCtx.get()); return NS_OK; } @@ -303,6 +302,8 @@ PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) WrapRunnable(RefPtr(this), &PeerConnectionMedia::EnsureTransport_s, transceiver->mTransport.mTransportId, + transceiver->mTransport.mLocalUfrag, + transceiver->mTransport.mLocalPwd, transceiver->mTransport.mComponents), NS_DISPATCH_NORMAL); } @@ -313,9 +314,11 @@ PeerConnectionMedia::EnsureTransports(const JsepSession& aSession) void PeerConnectionMedia::EnsureTransport_s(const std::string& aTransportId, + const std::string& aUfrag, + const std::string& aPwd, size_t aComponentCount) { - RefPtr stream(mIceCtxHdlr->ctx()->GetStream(aTransportId)); + RefPtr stream(mIceCtx->GetStream(aTransportId)); if (!stream) { CSFLogDebug(LOGTAG, "%s: Creating ICE media stream=%s components=%u", mParentHandle.c_str(), @@ -324,21 +327,21 @@ PeerConnectionMedia::EnsureTransport_s(const std::string& aTransportId, std::ostringstream os; os << mParentName << " transport-id=" << aTransportId; - RefPtr stream = - mIceCtxHdlr->CreateStream(os.str(), - aComponentCount); + stream = mIceCtx->CreateStream(aTransportId, + os.str(), + aComponentCount); if (!stream) { CSFLogError(LOGTAG, "Failed to create ICE stream."); return; } - stream->SetId(aTransportId); stream->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady_s); stream->SignalCandidate.connect(this, &PeerConnectionMedia::OnCandidateFound_s); - mIceCtxHdlr->ctx()->SetStream(aTransportId, stream); } + // This might begin an ICE restart + stream->SetIceCredentials(aUfrag, aPwd); } nsresult @@ -406,6 +409,8 @@ PeerConnectionMedia::UpdateTransport(const JsepTransceiver& aTransceiver, WrapRunnable(RefPtr(this), &PeerConnectionMedia::ActivateTransport_s, transport.mTransportId, + transport.mLocalUfrag, + transport.mLocalPwd, components, ufrag, pwd, @@ -418,6 +423,8 @@ PeerConnectionMedia::UpdateTransport(const JsepTransceiver& aTransceiver, void PeerConnectionMedia::ActivateTransport_s( const std::string& aTransportId, + const std::string& aLocalUfrag, + const std::string& aLocalPwd, size_t aComponentCount, const std::string& aUfrag, const std::string& aPassword, @@ -425,36 +432,34 @@ PeerConnectionMedia::ActivateTransport_s( MOZ_ASSERT(aComponentCount); - RefPtr stream(mIceCtxHdlr->ctx()->GetStream(aTransportId)); + RefPtr stream(mIceCtx->GetStream(aTransportId)); if (!stream) { MOZ_ASSERT(false); return; } - if (!stream->HasParsedAttributes()) { - CSFLogDebug(LOGTAG, "%s: Activating ICE media stream=%s components=%u", - mParentHandle.c_str(), - aTransportId.c_str(), - static_cast(aComponentCount)); + CSFLogDebug(LOGTAG, "%s: Activating ICE media stream=%s components=%u", + mParentHandle.c_str(), + aTransportId.c_str(), + static_cast(aComponentCount)); - std::vector attrs; - attrs.reserve(aCandidateList.size() + 2 /* ufrag + pwd */); - for (const auto& candidate : aCandidateList) { - attrs.push_back("candidate:" + candidate); - } - attrs.push_back("ice-ufrag:" + aUfrag); - attrs.push_back("ice-pwd:" + aPassword); + std::vector attrs; + attrs.reserve(aCandidateList.size() + 2 /* ufrag + pwd */); + for (const auto& candidate : aCandidateList) { + attrs.push_back("candidate:" + candidate); + } + attrs.push_back("ice-ufrag:" + aUfrag); + attrs.push_back("ice-pwd:" + aPassword); - nsresult rv = stream->ParseAttributes(attrs); - if (NS_FAILED(rv)) { - CSFLogError(LOGTAG, "Couldn't parse ICE attributes, rv=%u", - static_cast(rv)); - } + nsresult rv = stream->ConnectToPeer(aLocalUfrag, aLocalPwd, attrs); + if (NS_FAILED(rv)) { + CSFLogError(LOGTAG, "Couldn't parse ICE attributes, rv=%u", + static_cast(rv)); + } - for (size_t c = aComponentCount; c < stream->components(); ++c) { - // components are 1-indexed - stream->DisableComponent(c + 1); - } + for (size_t c = aComponentCount; c < stream->components(); ++c) { + // components are 1-indexed + stream->DisableComponent(c + 1); } } @@ -462,9 +467,9 @@ void PeerConnectionMedia::RemoveTransportsExcept_s( const std::set& aIds) { - for (const auto& stream : mIceCtxHdlr->ctx()->GetStreams()) { + for (const auto& stream : mIceCtx->GetStreams()) { if (!aIds.count(stream->GetId())) { - mIceCtxHdlr->ctx()->SetStream(stream->GetId(), nullptr); + mIceCtx->DestroyStream(stream->GetId()); } } } @@ -540,18 +545,6 @@ FinalizeTransportFlow_s(RefPtr aPCMedia, aFlow->PushLayer(aSrtpLayer); } -static void -AddNewIceStreamForRestart_s(RefPtr aPCMedia, - RefPtr aFlow, - const std::string& aTransportId, - bool aIsRtcp) -{ - TransportLayerIce* ice = - static_cast(aFlow->GetLayer("ice")); - ice->SetParameters(aPCMedia->ice_media_stream(aTransportId), - aIsRtcp ? 2 : 1); -} - nsresult PeerConnectionMedia::UpdateTransportFlow(bool aIsRtcp, const JsepTransport& aTransport) @@ -572,21 +565,6 @@ PeerConnectionMedia::UpdateTransportFlow(bool aIsRtcp, RefPtr flow = GetTransportFlow(aTransport.mTransportId, aIsRtcp); if (flow) { - if (IsIceRestarting()) { - CSFLogInfo(LOGTAG, "Flow[%s]: detected ICE restart - id: %s rtcp: %d", - flow->id().c_str(), aTransport.mTransportId.c_str(), aIsRtcp); - - RefPtr pcMedia(this); - rv = GetSTSThread()->Dispatch( - WrapRunnableNM(AddNewIceStreamForRestart_s, - pcMedia, flow, aTransport.mTransportId, aIsRtcp), - NS_DISPATCH_NORMAL); - if (NS_FAILED(rv)) { - CSFLogError(LOGTAG, "Failed to dispatch AddNewIceStreamForRestart_s"); - return rv; - } - } - return NS_OK; } @@ -707,154 +685,16 @@ PeerConnectionMedia::StartIceChecks_s( } } - nsresult rv = mIceCtxHdlr->ctx()->ParseGlobalAttributes(attributes); + nsresult rv = mIceCtx->ParseGlobalAttributes(attributes); if (NS_FAILED(rv)) { CSFLogError(LOGTAG, "%s: couldn't parse global parameters", __FUNCTION__ ); } - mIceCtxHdlr->ctx()->SetControlling(aIsControlling ? + mIceCtx->SetControlling(aIsControlling ? NrIceCtx::ICE_CONTROLLING : NrIceCtx::ICE_CONTROLLED); - mIceCtxHdlr->ctx()->StartChecks(aIsOfferer); -} - -bool -PeerConnectionMedia::IsIceRestarting() const -{ - ASSERT_ON_THREAD(mMainThread); - - return (mIceRestartState != ICE_RESTART_NONE); -} - -PeerConnectionMedia::IceRestartState -PeerConnectionMedia::GetIceRestartState() const -{ - ASSERT_ON_THREAD(mMainThread); - - return mIceRestartState; -} - -void -PeerConnectionMedia::BeginIceRestart(const std::string& ufrag, - const std::string& pwd) -{ - ASSERT_ON_THREAD(mMainThread); - if (IsIceRestarting()) { - return; - } - - RefPtr new_ctx = mIceCtxHdlr->CreateCtx(ufrag, pwd); - - RUN_ON_THREAD(GetSTSThread(), - WrapRunnable( - RefPtr(this), - &PeerConnectionMedia::BeginIceRestart_s, - new_ctx), - NS_DISPATCH_NORMAL); - - mIceRestartState = ICE_RESTART_PROVISIONAL; -} - -void -PeerConnectionMedia::BeginIceRestart_s(RefPtr new_ctx) -{ - ASSERT_ON_THREAD(mSTSThread); - - // hold the original context so we can disconnect signals if needed - RefPtr originalCtx = mIceCtxHdlr->ctx(); - - if (mIceCtxHdlr->BeginIceRestart(new_ctx)) { - ConnectSignals(mIceCtxHdlr->ctx().get(), originalCtx.get()); - } -} - -void -PeerConnectionMedia::CommitIceRestart() -{ - ASSERT_ON_THREAD(mMainThread); - if (mIceRestartState != ICE_RESTART_PROVISIONAL) { - return; - } - - mIceRestartState = ICE_RESTART_COMMITTED; -} - -void -PeerConnectionMedia::FinalizeIceRestart() -{ - ASSERT_ON_THREAD(mMainThread); - if (!IsIceRestarting()) { - return; - } - - RUN_ON_THREAD(GetSTSThread(), - WrapRunnable( - RefPtr(this), - &PeerConnectionMedia::FinalizeIceRestart_s), - NS_DISPATCH_NORMAL); - - mIceRestartState = ICE_RESTART_NONE; -} - -void -PeerConnectionMedia::FinalizeIceRestart_s() -{ - ASSERT_ON_THREAD(mSTSThread); - - // reset old streams since we don't need them anymore - for (auto& transportFlow : mTransportFlows) { - RefPtr aFlow = transportFlow.second; - if (!aFlow) continue; - TransportLayerIce* ice = - static_cast(aFlow->GetLayer(TransportLayerIce::ID())); - ice->ResetOldStream(); - } - - mIceCtxHdlr->FinalizeIceRestart(); -} - -void -PeerConnectionMedia::RollbackIceRestart() -{ - ASSERT_ON_THREAD(mMainThread); - if (mIceRestartState != ICE_RESTART_PROVISIONAL) { - return; - } - - RUN_ON_THREAD(GetSTSThread(), - WrapRunnable( - RefPtr(this), - &PeerConnectionMedia::RollbackIceRestart_s), - NS_DISPATCH_NORMAL); - - mIceRestartState = ICE_RESTART_NONE; -} - -void -PeerConnectionMedia::RollbackIceRestart_s() -{ - ASSERT_ON_THREAD(mSTSThread); - - // hold the restart context so we can disconnect signals - RefPtr restartCtx = mIceCtxHdlr->ctx(); - - // restore old streams since we're rolling back - for (auto& transportFlow : mTransportFlows) { - RefPtr aFlow = transportFlow.second; - if (!aFlow) continue; - TransportLayerIce* ice = - static_cast(aFlow->GetLayer(TransportLayerIce::ID())); - ice->RestoreOldStream(); - } - - mIceCtxHdlr->RollbackIceRestart(); - ConnectSignals(mIceCtxHdlr->ctx().get(), restartCtx.get()); - - // Fixup the telemetry by transferring abandoned ctx stats to current ctx. - NrIceStats stats = restartCtx->Destroy(); - restartCtx = nullptr; - mIceCtxHdlr->ctx()->AccumulateStats(stats); + mIceCtx->StartChecks(aIsOfferer); } bool @@ -926,7 +766,7 @@ PeerConnectionMedia::AddIceCandidate(const std::string& candidate, void PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate, const std::string& aTransportId) { - RefPtr stream(mIceCtxHdlr->ctx()->GetStream(aTransportId)); + RefPtr stream(mIceCtx->GetStream(aTransportId)); if (!stream) { CSFLogError(LOGTAG, "No ICE stream for candidate with transport id %s: %s", aTransportId.c_str(), aCandidate.c_str()); @@ -954,7 +794,7 @@ PeerConnectionMedia::UpdateNetworkState(bool online) { void PeerConnectionMedia::UpdateNetworkState_s(bool online) { - mIceCtxHdlr->ctx()->UpdateNetworkState(online); + mIceCtx->UpdateNetworkState(online); } void @@ -999,9 +839,9 @@ void PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly, bool aProxyOnly) { if (mProxyServer) { - mIceCtxHdlr->ctx()->SetProxyServer(*mProxyServer); + mIceCtx->SetProxyServer(*mProxyServer); } else if (aProxyOnly) { - IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(), + IceGatheringStateChange_s(mIceCtx.get(), NrIceCtx::ICE_CTX_GATHER_COMPLETE); return; } @@ -1022,15 +862,15 @@ PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly, // needs to have the proper flags set on ice ctx. For non-e10s, // setting those flags happens in StartGathering. We could probably // just set them here, and only do it here. - mIceCtxHdlr->ctx()->SetCtxFlags(aDefaultRouteOnly, aProxyOnly); + mIceCtx->SetCtxFlags(aDefaultRouteOnly, aProxyOnly); if (mStunAddrs.Length()) { - mIceCtxHdlr->ctx()->SetStunAddrs(mStunAddrs); + mIceCtx->SetStunAddrs(mStunAddrs); } // Start gathering, but only if there are streams - if (!mIceCtxHdlr->ctx()->GetStreams().empty()) { - mIceCtxHdlr->ctx()->StartGathering(aDefaultRouteOnly, aProxyOnly); + if (!mIceCtx->GetStreams().empty()) { + mIceCtx->StartGathering(aDefaultRouteOnly, aProxyOnly); return; } @@ -1040,7 +880,7 @@ PeerConnectionMedia::EnsureIceGathering_s(bool aDefaultRouteOnly, // If there are no streams, we're probably in a situation where we've rolled // back while still waiting for our proxy configuration to come back. Make // sure content knows that the rollback has stuck wrt gathering. - IceGatheringStateChange_s(mIceCtxHdlr->ctx().get(), + IceGatheringStateChange_s(mIceCtx.get(), NrIceCtx::ICE_CTX_GATHER_COMPLETE); } @@ -1103,7 +943,7 @@ PeerConnectionMedia::ShutdownMediaTransport_s() mTransportFlows.clear(); #if !defined(MOZILLA_EXTERNAL_LINKAGE) - NrIceStats stats = mIceCtxHdlr->Destroy(); + NrIceStats stats = mIceCtx->Destroy(); CSFLogDebug(LOGTAG, "Ice Telemetry: stun (retransmits: %d)" " turn (401s: %d 403s: %d 438s: %d)", @@ -1120,7 +960,7 @@ PeerConnectionMedia::ShutdownMediaTransport_s() stats.turn_438s); #endif - mIceCtxHdlr = nullptr; + mIceCtx = nullptr; // we're holding a ref to 'this' that's released by SelfDestruct_m mMainThread->Dispatch(WrapRunnable(this, &PeerConnectionMedia::SelfDestruct_m), @@ -1293,7 +1133,7 @@ PeerConnectionMedia::OnCandidateFound_s(NrIceMediaStream *aStream, ASSERT_ON_THREAD(mSTSThread); MOZ_ASSERT(aStream); MOZ_ASSERT(!aStream->GetId().empty()); - MOZ_RELEASE_ASSERT(mIceCtxHdlr); + MOZ_RELEASE_ASSERT(mIceCtx); CSFLogDebug(LOGTAG, "%s: %s", __FUNCTION__, aStream->name().c_str()); diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 33efde17cfd1..25d7648d7a98 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -28,7 +28,6 @@ class MediaStreamTrack; } } -#include "nricectxhandler.h" #include "nriceresolver.h" #include "nricemediastream.h" @@ -50,11 +49,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { public: explicit PeerConnectionMedia(PeerConnectionImpl *parent); - enum IceRestartState { ICE_RESTART_NONE, - ICE_RESTART_PROVISIONAL, - ICE_RESTART_COMMITTED - }; - PeerConnectionImpl* GetPC() { return mParent; } nsresult Init(const std::vector& stun_servers, const std::vector& turn_servers, @@ -62,12 +56,11 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // WARNING: This destroys the object! void SelfDestruct(); - RefPtr ice_ctx_hdlr() const { return mIceCtxHdlr; } - RefPtr ice_ctx() const { return mIceCtxHdlr->ctx(); } + RefPtr ice_ctx() const { return mIceCtx; } RefPtr ice_media_stream( const std::string& aTransportId) const { - return mIceCtxHdlr->ctx()->GetStream(aTransportId); + return mIceCtx->GetStream(aTransportId); } // Ensure ICE transports exist that we might need when offer/answer concludes @@ -81,19 +74,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Start ICE checks. void StartIceChecks(const JsepSession& session); - bool IsIceRestarting() const; - IceRestartState GetIceRestartState() const; - - // Begin ICE restart - void BeginIceRestart(const std::string& ufrag, - const std::string& pwd); - // Commit ICE Restart - offer/answer complete, no rollback possible - void CommitIceRestart(); - // Finalize ICE restart - void FinalizeIceRestart(); - // Abort ICE restart - void RollbackIceRestart(); - // Process a trickle ICE candidate. void AddIceCandidate(const std::string& candidate, const std::string& aTransportId); @@ -240,8 +220,12 @@ class PeerConnectionMedia : public sigslot::has_slots<> { bool aForceIceTcp); void EnsureTransport_s(const std::string& aTransportId, + const std::string& aUfrag, + const std::string& aPwd, size_t aComponentCount); void ActivateTransport_s(const std::string& aTransportId, + const std::string& aLocalUfrag, + const std::string& aLocalPwd, size_t aComponentCount, const std::string& aUfrag, const std::string& aPassword, @@ -260,9 +244,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { bool aIsIceLite, const std::vector& aIceOptionsList); - void BeginIceRestart_s(RefPtr new_ctx); - void FinalizeIceRestart_s(); - void RollbackIceRestart_s(); bool GetPrefDefaultAddressOnly() const; bool GetPrefProxyOnly() const; @@ -319,7 +300,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> { std::vector> mTransceivers; // ICE objects - RefPtr mIceCtxHdlr; + RefPtr mIceCtx; // DNS RefPtr mDNSResolver; @@ -354,9 +335,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { // Used to store the result of the request. UniquePtr mProxyServer; - // Used to track the state of ice restart - IceRestartState mIceRestartState; - // Used to cancel incoming stun addrs response RefPtr mStunAddrsRequest;