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;