зеркало из https://github.com/mozilla/gecko-dev.git
Bug 935723. Part 1. Decouple ICE state with ICE gathering state r=ekr,abr,jesup
This commit is contained in:
Родитель
aebc089f65
Коммит
67f0c411ba
3
CLOBBER
3
CLOBBER
|
@ -18,5 +18,4 @@
|
|||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
WebIDL dictionary modification requires clobber on Windows (bug 928195), part of
|
||||
bug 906990.
|
||||
Another Windows WebIDL clobber needed due to bug 928195
|
||||
|
|
|
@ -1016,21 +1016,8 @@ PeerConnectionObserver.prototype = {
|
|||
},
|
||||
|
||||
|
||||
// This method is primarily responsible for updating two attributes:
|
||||
// iceGatheringState and iceConnectionState. These states are defined
|
||||
// in the WebRTC specification as follows:
|
||||
//
|
||||
// iceGatheringState:
|
||||
// ------------------
|
||||
// new The object was just created, and no networking has occurred
|
||||
// yet.
|
||||
//
|
||||
// gathering The ICE engine is in the process of gathering candidates for
|
||||
// this RTCPeerConnection.
|
||||
//
|
||||
// complete The ICE engine has completed gathering. Events such as adding
|
||||
// a new interface or a new TURN server will cause the state to
|
||||
// go back to gathering.
|
||||
// This method is primarily responsible for updating iceConnectionState.
|
||||
// This state is defined in the WebRTC specification as follows:
|
||||
//
|
||||
// iceConnectionState:
|
||||
// -------------------
|
||||
|
@ -1064,36 +1051,38 @@ PeerConnectionObserver.prototype = {
|
|||
// closed The ICE Agent has shut down and is no longer responding to
|
||||
// STUN requests.
|
||||
|
||||
handleIceStateChanges: function(iceState) {
|
||||
handleIceConnectionStateChange: function(iceState) {
|
||||
var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
|
||||
|
||||
const STATE_MAP = {
|
||||
IceGathering:
|
||||
{ gathering: "gathering" },
|
||||
IceWaiting:
|
||||
{ connection: "new", gathering: "complete" },
|
||||
IceChecking:
|
||||
{ connection: "checking" },
|
||||
IceConnected:
|
||||
{ connection: "connected", success: true },
|
||||
IceFailed:
|
||||
{ connection: "failed", success: false }
|
||||
};
|
||||
// These are all the allowed inputs.
|
||||
|
||||
let transitions = STATE_MAP[iceState];
|
||||
|
||||
if ("connection" in transitions) {
|
||||
this._dompc.changeIceConnectionState(transitions.connection);
|
||||
if (iceState === 'failed') {
|
||||
histogram.add(false);
|
||||
}
|
||||
if ("gathering" in transitions) {
|
||||
this._dompc.changeIceGatheringState(transitions.gathering);
|
||||
}
|
||||
if ("success" in transitions) {
|
||||
histogram.add(transitions.success);
|
||||
if (this._dompc.iceConnectionState === 'checking' &&
|
||||
(iceState === 'completed' || iceState === 'connected')) {
|
||||
histogram.add(true);
|
||||
}
|
||||
this._dompc.changeIceConnectionState(iceState);
|
||||
},
|
||||
|
||||
if (iceState == "IceWaiting") {
|
||||
// This method is responsible for updating iceGatheringState. This
|
||||
// state is defined in the WebRTC specification as follows:
|
||||
//
|
||||
// iceGatheringState:
|
||||
// ------------------
|
||||
// new The object was just created, and no networking has occurred
|
||||
// yet.
|
||||
//
|
||||
// gathering The ICE engine is in the process of gathering candidates for
|
||||
// this RTCPeerConnection.
|
||||
//
|
||||
// complete The ICE engine has completed gathering. Events such as adding
|
||||
// a new interface or a new TURN server will cause the state to
|
||||
// go back to gathering.
|
||||
//
|
||||
handleIceGatheringStateChange: function(gatheringState) {
|
||||
this._dompc.changeIceGatheringState(gatheringState);
|
||||
|
||||
if (gatheringState === "complete") {
|
||||
if (!this._dompc._trickleIce) {
|
||||
// If we are not trickling, then the queue is in a pending state
|
||||
// waiting for ICE gathering and executeNext frees it
|
||||
|
@ -1115,8 +1104,12 @@ PeerConnectionObserver.prototype = {
|
|||
this._dompc.signalingState);
|
||||
break;
|
||||
|
||||
case "IceState":
|
||||
this.handleIceStateChanges(this._dompc._pc.iceState);
|
||||
case "IceConnectionState":
|
||||
this.handleIceConnectionStateChange(this._dompc._pc.iceState);
|
||||
break;
|
||||
|
||||
case "IceGatheringState":
|
||||
this.handleIceGatheringStateChange(this._dompc._pc.iceGatheringState);
|
||||
break;
|
||||
|
||||
case "SdpState":
|
||||
|
|
|
@ -70,7 +70,8 @@ interface PeerConnectionImpl {
|
|||
readonly attribute DOMString localDescription;
|
||||
readonly attribute DOMString remoteDescription;
|
||||
|
||||
readonly attribute PCImplIceState iceState;
|
||||
readonly attribute PCImplIceConnectionState iceConnectionState;
|
||||
readonly attribute PCImplIceGatheringState iceGatheringState;
|
||||
readonly attribute PCImplReadyState readyState;
|
||||
readonly attribute PCImplSignalingState signalingState;
|
||||
readonly attribute PCImplSipccState sipccState;
|
||||
|
|
|
@ -31,11 +31,20 @@ enum PCImplSipccState {
|
|||
"Started"
|
||||
};
|
||||
|
||||
// TODO(ekr@rtfm.com): make this conform to the specifications
|
||||
enum PCImplIceState {
|
||||
"IceGathering",
|
||||
"IceWaiting",
|
||||
"IceChecking",
|
||||
"IceConnected",
|
||||
"IceFailed"
|
||||
enum PCImplIceConnectionState {
|
||||
"new",
|
||||
"checking",
|
||||
"connected",
|
||||
"completed",
|
||||
"failed",
|
||||
"disconnected",
|
||||
"closed"
|
||||
};
|
||||
|
||||
// Deliberately identical to the values specified in webrtc
|
||||
enum PCImplIceGatheringState {
|
||||
"new",
|
||||
"gathering",
|
||||
"complete"
|
||||
};
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
enum PCObserverStateType {
|
||||
"None",
|
||||
"ReadyState",
|
||||
"IceState",
|
||||
"IceConnectionState",
|
||||
"IceGatheringState",
|
||||
"SdpState",
|
||||
"SipccState",
|
||||
"SignalingState"
|
||||
|
|
|
@ -276,7 +276,7 @@ int NrIceCtx::stream_failed(void *obj, nr_ice_media_stream *stream) {
|
|||
// Streams which do not exist should never fail.
|
||||
MOZ_ASSERT(s);
|
||||
|
||||
ctx->SetState(ICE_CTX_FAILED);
|
||||
ctx->SetConnectionState(ICE_CTX_FAILED);
|
||||
s -> SignalFailed(s);
|
||||
return 0;
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ int NrIceCtx::ice_completed(void *obj, nr_ice_peer_ctx *pctx) {
|
|||
// Get the ICE ctx
|
||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
|
||||
|
||||
ctx->SetState(ICE_CTX_OPEN);
|
||||
ctx->SetConnectionState(ICE_CTX_OPEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ nsresult NrIceCtx::StartGathering() {
|
|||
if (ctx_->state != ICE_CTX_INIT) {
|
||||
MOZ_MTLOG(ML_ERROR, "ICE ctx in the wrong state for gathering: '"
|
||||
<< name_ << "'");
|
||||
SetState(ICE_CTX_FAILED);
|
||||
SetConnectionState(ICE_CTX_FAILED);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -561,11 +561,11 @@ nsresult NrIceCtx::StartGathering() {
|
|||
if (r && r != R_WOULDBLOCK) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't gather ICE candidates for '"
|
||||
<< name_ << "'");
|
||||
SetState(ICE_CTX_FAILED);
|
||||
SetConnectionState(ICE_CTX_FAILED);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SetState(ICE_CTX_GATHERING);
|
||||
SetGatheringState(ICE_CTX_GATHER_STARTED);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -630,7 +630,7 @@ nsresult NrIceCtx::StartChecks() {
|
|||
if (r) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't pair candidates on "
|
||||
<< name_ << "'");
|
||||
SetState(ICE_CTX_FAILED);
|
||||
SetConnectionState(ICE_CTX_FAILED);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -642,11 +642,11 @@ nsresult NrIceCtx::StartChecks() {
|
|||
} else {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks on "
|
||||
<< name_ << "'");
|
||||
SetState(ICE_CTX_FAILED);
|
||||
SetConnectionState(ICE_CTX_FAILED);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
SetState(ICE_CTX_CHECKING);
|
||||
SetConnectionState(ICE_CTX_CHECKING);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -656,7 +656,7 @@ nsresult NrIceCtx::StartChecks() {
|
|||
void NrIceCtx::initialized_cb(NR_SOCKET s, int h, void *arg) {
|
||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
||||
|
||||
ctx->SetState(ICE_CTX_GATHERED);
|
||||
ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
|
||||
}
|
||||
|
||||
nsresult NrIceCtx::Finalize() {
|
||||
|
@ -671,27 +671,26 @@ nsresult NrIceCtx::Finalize() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void NrIceCtx::SetState(State state) {
|
||||
if (state == state_)
|
||||
void NrIceCtx::SetConnectionState(ConnectionState state) {
|
||||
if (state == connection_state_)
|
||||
return;
|
||||
|
||||
MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): state " <<
|
||||
state_ << "->" << state);
|
||||
state_ = state;
|
||||
connection_state_ << "->" << state);
|
||||
connection_state_ = state;
|
||||
|
||||
switch(state_) {
|
||||
case ICE_CTX_GATHERED:
|
||||
SignalGatheringCompleted(this);
|
||||
break;
|
||||
case ICE_CTX_OPEN:
|
||||
SignalCompleted(this);
|
||||
break;
|
||||
case ICE_CTX_FAILED:
|
||||
SignalFailed(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SignalConnectionStateChange(this, state);
|
||||
}
|
||||
|
||||
void NrIceCtx::SetGatheringState(GatheringState state) {
|
||||
if (state == gathering_state_)
|
||||
return;
|
||||
|
||||
MOZ_MTLOG(ML_DEBUG, "NrIceCtx(" << name_ << "): gathering state " <<
|
||||
gathering_state_ << "->" << state);
|
||||
gathering_state_ = state;
|
||||
|
||||
SignalGatheringStateChange(this, state);
|
||||
}
|
||||
|
||||
} // close namespace
|
||||
|
|
|
@ -163,12 +163,15 @@ class NrIceTurnServer : public NrIceStunServer {
|
|||
|
||||
class NrIceCtx {
|
||||
public:
|
||||
enum State { ICE_CTX_INIT,
|
||||
ICE_CTX_GATHERING,
|
||||
ICE_CTX_GATHERED,
|
||||
ICE_CTX_CHECKING,
|
||||
ICE_CTX_OPEN,
|
||||
ICE_CTX_FAILED
|
||||
enum ConnectionState { ICE_CTX_INIT,
|
||||
ICE_CTX_CHECKING,
|
||||
ICE_CTX_OPEN,
|
||||
ICE_CTX_FAILED
|
||||
};
|
||||
|
||||
enum GatheringState { ICE_CTX_GATHER_INIT,
|
||||
ICE_CTX_GATHER_STARTED,
|
||||
ICE_CTX_GATHER_COMPLETE
|
||||
};
|
||||
|
||||
enum Controlling { ICE_CONTROLLING,
|
||||
|
@ -194,7 +197,14 @@ class NrIceCtx {
|
|||
const std::string& name() const { return name_; }
|
||||
|
||||
// Current state
|
||||
State state() const { return state_; }
|
||||
ConnectionState connection_state() const {
|
||||
return connection_state_;
|
||||
}
|
||||
|
||||
// Current state
|
||||
GatheringState gathering_state() const {
|
||||
return gathering_state_;
|
||||
}
|
||||
|
||||
// Get the global attributes
|
||||
std::vector<std::string> GetGlobalAttributes();
|
||||
|
@ -232,11 +242,10 @@ class NrIceCtx {
|
|||
|
||||
// Signals to indicate events. API users can (and should)
|
||||
// register for these.
|
||||
// TODO(ekr@rtfm.com): refactor this to be state change instead
|
||||
// so we don't need to keep adding signals?
|
||||
sigslot::signal1<NrIceCtx *> SignalGatheringCompleted; // Done gathering
|
||||
sigslot::signal1<NrIceCtx *> SignalCompleted; // Done handshaking
|
||||
sigslot::signal1<NrIceCtx *> SignalFailed; // Failure.
|
||||
sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
|
||||
SignalGatheringStateChange;
|
||||
sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
|
||||
SignalConnectionStateChange;
|
||||
|
||||
// The thread to direct method calls to
|
||||
nsCOMPtr<nsIEventTarget> thread() { return sts_target_; }
|
||||
|
@ -246,7 +255,8 @@ class NrIceCtx {
|
|||
private:
|
||||
NrIceCtx(const std::string& name,
|
||||
bool offerer)
|
||||
: state_(ICE_CTX_INIT),
|
||||
: connection_state_(ICE_CTX_INIT),
|
||||
gathering_state_(ICE_CTX_GATHER_INIT),
|
||||
name_(name),
|
||||
offerer_(offerer),
|
||||
streams_(),
|
||||
|
@ -281,9 +291,13 @@ class NrIceCtx {
|
|||
RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream);
|
||||
|
||||
// Set the state
|
||||
void SetState(State state);
|
||||
void SetConnectionState(ConnectionState state);
|
||||
|
||||
State state_;
|
||||
// Set the state
|
||||
void SetGatheringState(GatheringState state);
|
||||
|
||||
ConnectionState connection_state_;
|
||||
GatheringState gathering_state_;
|
||||
const std::string name_;
|
||||
bool offerer_;
|
||||
std::vector<RefPtr<NrIceMediaStream> > streams_;
|
||||
|
|
|
@ -143,9 +143,12 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||
expected_remote_type_(NrIceCandidate::ICE_HOST),
|
||||
trickle_mode_(TRICKLE_NONE),
|
||||
trickled_(0) {
|
||||
ice_ctx_->SignalGatheringCompleted.connect(this,
|
||||
&IceTestPeer::GatheringComplete);
|
||||
ice_ctx_->SignalCompleted.connect(this, &IceTestPeer::IceCompleted);
|
||||
ice_ctx_->SignalGatheringStateChange.connect(
|
||||
this,
|
||||
&IceTestPeer::GatheringStateChange);
|
||||
ice_ctx_->SignalConnectionStateChange.connect(
|
||||
this,
|
||||
&IceTestPeer::ConnectionStateChange);
|
||||
}
|
||||
|
||||
~IceTestPeer() {
|
||||
|
@ -426,7 +429,13 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||
}
|
||||
|
||||
// Handle events
|
||||
void GatheringComplete(NrIceCtx *ctx) {
|
||||
void GatheringStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::GatheringState state) {
|
||||
(void)ctx;
|
||||
if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "Gathering complete for " << name_ << std::endl;
|
||||
gathering_complete_ = true;
|
||||
|
||||
|
@ -598,7 +607,12 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||
DumpCandidatePairs(stream);
|
||||
}
|
||||
|
||||
void IceCompleted(NrIceCtx *ctx) {
|
||||
void ConnectionStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::ConnectionState state) {
|
||||
(void)ctx;
|
||||
if (state != NrIceCtx::ICE_CTX_OPEN) {
|
||||
return;
|
||||
}
|
||||
std::cerr << "ICE completed " << name_ << std::endl;
|
||||
ice_complete_ = true;
|
||||
}
|
||||
|
|
|
@ -237,8 +237,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
|
|||
nsresult res;
|
||||
|
||||
// Attach our slots
|
||||
ice_ctx_->SignalGatheringCompleted.
|
||||
connect(this, &TransportTestPeer::GatheringComplete);
|
||||
ice_ctx_->SignalGatheringStateChange.
|
||||
connect(this, &TransportTestPeer::GatheringStateChange);
|
||||
|
||||
char name[100];
|
||||
snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
|
||||
|
@ -285,7 +285,7 @@ class TransportTestPeer : public sigslot::has_slots<> {
|
|||
|
||||
// If gathering is already complete, push the candidates over
|
||||
if (gathering_complete_)
|
||||
GatheringComplete(ice_ctx_);
|
||||
GatheringComplete();
|
||||
}
|
||||
|
||||
// New candidate
|
||||
|
@ -294,9 +294,17 @@ class TransportTestPeer : public sigslot::has_slots<> {
|
|||
candidates_[stream->name()].push_back(candidate);
|
||||
}
|
||||
|
||||
void GatheringStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::GatheringState state) {
|
||||
(void)ctx;
|
||||
if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
|
||||
GatheringComplete();
|
||||
}
|
||||
}
|
||||
|
||||
// Gathering complete, so send our candidates and start
|
||||
// connecting on the other peer.
|
||||
void GatheringComplete(NrIceCtx *ctx) {
|
||||
void GatheringComplete() {
|
||||
nsresult res;
|
||||
|
||||
// Don't send to the other side
|
||||
|
|
|
@ -456,7 +456,8 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
|
|||
, mInternal(new Internal())
|
||||
, mReadyState(PCImplReadyState::New)
|
||||
, mSignalingState(PCImplSignalingState::SignalingStable)
|
||||
, mIceState(PCImplIceState::IceGathering)
|
||||
, mIceConnectionState(PCImplIceConnectionState::New)
|
||||
, mIceGatheringState(PCImplIceGatheringState::New)
|
||||
, mWindow(nullptr)
|
||||
, mIdentity(nullptr)
|
||||
, mSTSThread(nullptr)
|
||||
|
@ -753,9 +754,12 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
|||
mMedia = new PeerConnectionMedia(this);
|
||||
|
||||
// Connect ICE slots.
|
||||
mMedia->SignalIceGatheringCompleted.connect(this, &PeerConnectionImpl::IceGatheringCompleted);
|
||||
mMedia->SignalIceCompleted.connect(this, &PeerConnectionImpl::IceCompleted);
|
||||
mMedia->SignalIceFailed.connect(this, &PeerConnectionImpl::IceFailed);
|
||||
mMedia->SignalIceGatheringStateChange.connect(
|
||||
this,
|
||||
&PeerConnectionImpl::IceGatheringStateChange);
|
||||
mMedia->SignalIceConnectionStateChange.connect(
|
||||
this,
|
||||
&PeerConnectionImpl::IceConnectionStateChange);
|
||||
|
||||
// Initialize the media object.
|
||||
res = mMedia->Init(aConfiguration->getStunServers(),
|
||||
|
@ -1418,12 +1422,22 @@ PeerConnectionImpl::SipccState(PCImplSipccState* aState)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PeerConnectionImpl::IceState(PCImplIceState* aState)
|
||||
PeerConnectionImpl::IceConnectionState(PCImplIceConnectionState* aState)
|
||||
{
|
||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||
MOZ_ASSERT(aState);
|
||||
|
||||
*aState = mIceState;
|
||||
*aState = mIceConnectionState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PeerConnectionImpl::IceGatheringState(PCImplIceGatheringState* aState)
|
||||
{
|
||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||
MOZ_ASSERT(aState);
|
||||
|
||||
*aState = mIceGatheringState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1432,7 +1446,7 @@ PeerConnectionImpl::CheckApiState(bool assert_ice_ready) const
|
|||
{
|
||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||
MOZ_ASSERT(mTrickle || !assert_ice_ready ||
|
||||
(mIceState != PCImplIceState::IceGathering));
|
||||
(mIceGatheringState == PCImplIceGatheringState::Complete));
|
||||
|
||||
if (mReadyState == PCImplReadyState::Closed)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1630,72 +1644,97 @@ PeerConnectionImpl::GetHandle()
|
|||
return mHandle;
|
||||
}
|
||||
|
||||
static mozilla::dom::PCImplIceConnectionState
|
||||
toDomIceConnectionState(NrIceCtx::ConnectionState state) {
|
||||
switch (state) {
|
||||
case NrIceCtx::ICE_CTX_INIT:
|
||||
return PCImplIceConnectionState::New;
|
||||
case NrIceCtx::ICE_CTX_CHECKING:
|
||||
return PCImplIceConnectionState::Checking;
|
||||
case NrIceCtx::ICE_CTX_OPEN:
|
||||
return PCImplIceConnectionState::Connected;
|
||||
case NrIceCtx::ICE_CTX_FAILED:
|
||||
return PCImplIceConnectionState::Failed;
|
||||
}
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
static mozilla::dom::PCImplIceGatheringState
|
||||
toDomIceGatheringState(NrIceCtx::GatheringState state) {
|
||||
switch (state) {
|
||||
case NrIceCtx::ICE_CTX_GATHER_INIT:
|
||||
return PCImplIceGatheringState::New;
|
||||
case NrIceCtx::ICE_CTX_GATHER_STARTED:
|
||||
return PCImplIceGatheringState::Gathering;
|
||||
case NrIceCtx::ICE_CTX_GATHER_COMPLETE:
|
||||
return PCImplIceGatheringState::Complete;
|
||||
}
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
// This is called from the STS thread and so we need to thunk
|
||||
// to the main thread.
|
||||
void
|
||||
PeerConnectionImpl::IceGatheringCompleted(NrIceCtx *aCtx)
|
||||
{
|
||||
(void) aCtx;
|
||||
void PeerConnectionImpl::IceConnectionStateChange(
|
||||
NrIceCtx* ctx,
|
||||
NrIceCtx::ConnectionState state) {
|
||||
(void)ctx;
|
||||
// Do an async call here to unwind the stack. refptr keeps the PC alive.
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::IceStateChange_m,
|
||||
PCImplIceState::IceWaiting),
|
||||
&PeerConnectionImpl::IceConnectionStateChange_m,
|
||||
toDomIceConnectionState(state)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionImpl::IceCompleted(NrIceCtx *aCtx)
|
||||
PeerConnectionImpl::IceGatheringStateChange(
|
||||
NrIceCtx* ctx,
|
||||
NrIceCtx::GatheringState state)
|
||||
{
|
||||
(void) aCtx;
|
||||
(void)ctx;
|
||||
// Do an async call here to unwind the stack. refptr keeps the PC alive.
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::IceStateChange_m,
|
||||
PCImplIceState::IceConnected),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionImpl::IceFailed(NrIceCtx *aCtx)
|
||||
{
|
||||
(void) aCtx;
|
||||
// Do an async call here to unwind the stack. refptr keeps the PC alive.
|
||||
nsRefPtr<PeerConnectionImpl> pc(this);
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pc,
|
||||
&PeerConnectionImpl::IceStateChange_m,
|
||||
PCImplIceState::IceFailed),
|
||||
&PeerConnectionImpl::IceGatheringStateChange_m,
|
||||
toDomIceGatheringState(state)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::IceStateChange_m(PCImplIceState aState)
|
||||
PeerConnectionImpl::IceConnectionStateChange_m(PCImplIceConnectionState aState)
|
||||
{
|
||||
PC_AUTO_ENTER_API_CALL(false);
|
||||
|
||||
CSFLogDebug(logTag, "%s", __FUNCTION__);
|
||||
|
||||
mIceState = aState;
|
||||
mIceConnectionState = aState;
|
||||
|
||||
switch (mIceState) {
|
||||
case PCImplIceState::IceGathering:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: gathering");
|
||||
// Would be nice if we had a means of converting one of these dom enums
|
||||
// to a string that wasn't almost as much text as this switch statement...
|
||||
switch (mIceConnectionState) {
|
||||
case PCImplIceConnectionState::New:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: new");
|
||||
break;
|
||||
case PCImplIceState::IceWaiting:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: waiting");
|
||||
break;
|
||||
case PCImplIceState::IceChecking:
|
||||
case PCImplIceConnectionState::Checking:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: checking");
|
||||
break;
|
||||
case PCImplIceState::IceConnected:
|
||||
case PCImplIceConnectionState::Connected:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: connected");
|
||||
break;
|
||||
case PCImplIceState::IceFailed:
|
||||
case PCImplIceConnectionState::Completed:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: completed");
|
||||
break;
|
||||
case PCImplIceConnectionState::Failed:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: failed");
|
||||
break;
|
||||
case PCImplIceConnectionState::Disconnected:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: disconnected");
|
||||
break;
|
||||
case PCImplIceConnectionState::Closed:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: closed");
|
||||
break;
|
||||
}
|
||||
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
|
@ -1706,7 +1745,44 @@ PeerConnectionImpl::IceStateChange_m(PCImplIceState aState)
|
|||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pco,
|
||||
&PeerConnectionObserver::OnStateChange,
|
||||
PCObserverStateType::IceState,
|
||||
PCObserverStateType::IceConnectionState,
|
||||
rv, static_cast<JSCompartment*>(nullptr)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionImpl::IceGatheringStateChange_m(PCImplIceGatheringState aState)
|
||||
{
|
||||
PC_AUTO_ENTER_API_CALL(false);
|
||||
|
||||
CSFLogDebug(logTag, "%s", __FUNCTION__);
|
||||
|
||||
mIceGatheringState = aState;
|
||||
|
||||
// Would be nice if we had a means of converting one of these dom enums
|
||||
// to a string that wasn't almost as much text as this switch statement...
|
||||
switch (mIceGatheringState) {
|
||||
case PCImplIceGatheringState::New:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice gathering state: new");
|
||||
break;
|
||||
case PCImplIceGatheringState::Gathering:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice gathering state: gathering");
|
||||
break;
|
||||
case PCImplIceGatheringState::Complete:
|
||||
STAMP_TIMECARD(mTimeCard, "Ice state: complete");
|
||||
break;
|
||||
}
|
||||
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return NS_OK;
|
||||
}
|
||||
WrappableJSErrorResult rv;
|
||||
RUN_ON_THREAD(mThread,
|
||||
WrapRunnable(pco,
|
||||
&PeerConnectionObserver::OnStateChange,
|
||||
PCObserverStateType::IceGatheringState,
|
||||
rv, static_cast<JSCompartment*>(nullptr)),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_OK;
|
||||
|
|
|
@ -222,9 +222,10 @@ public:
|
|||
virtual const std::string& GetHandle();
|
||||
|
||||
// ICE events
|
||||
void IceGatheringCompleted(NrIceCtx *aCtx);
|
||||
void IceCompleted(NrIceCtx *aCtx);
|
||||
void IceFailed(NrIceCtx *aCtx);
|
||||
void IceConnectionStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::ConnectionState state);
|
||||
void IceGatheringStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::GatheringState state);
|
||||
void IceStreamReady(NrIceMediaStream *aStream);
|
||||
|
||||
static void ListenThread(void *aData);
|
||||
|
@ -290,12 +291,14 @@ public:
|
|||
NS_IMETHODIMP CreateAnswer(const MediaConstraintsExternal& aConstraints);
|
||||
|
||||
NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);
|
||||
|
||||
void SetLocalDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
|
||||
{
|
||||
rv = SetLocalDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SetRemoteDescription (int32_t aAction, const char* aSDP);
|
||||
|
||||
void SetRemoteDescription (int32_t aAction, const nsAString& aSDP, ErrorResult &rv)
|
||||
{
|
||||
rv = SetRemoteDescription(aAction, NS_ConvertUTF16toUTF8(aSDP).get());
|
||||
|
@ -316,6 +319,7 @@ public:
|
|||
|
||||
NS_IMETHODIMP AddIceCandidate(const char* aCandidate, const char* aMid,
|
||||
unsigned short aLevel);
|
||||
|
||||
void AddIceCandidate(const nsAString& aCandidate, const nsAString& aMid,
|
||||
unsigned short aLevel, ErrorResult &rv)
|
||||
{
|
||||
|
@ -324,6 +328,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP CloseStreams();
|
||||
|
||||
void CloseStreams(ErrorResult &rv)
|
||||
{
|
||||
rv = CloseStreams();
|
||||
|
@ -342,6 +347,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP GetLocalDescription(char** aSDP);
|
||||
|
||||
void GetLocalDescription(nsAString& aSDP)
|
||||
{
|
||||
char *tmp;
|
||||
|
@ -351,6 +357,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP GetRemoteDescription(char** aSDP);
|
||||
|
||||
void GetRemoteDescription(nsAString& aSDP)
|
||||
{
|
||||
char *tmp;
|
||||
|
@ -360,6 +367,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP ReadyState(mozilla::dom::PCImplReadyState* aState);
|
||||
|
||||
mozilla::dom::PCImplReadyState ReadyState()
|
||||
{
|
||||
mozilla::dom::PCImplReadyState state;
|
||||
|
@ -368,6 +376,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP SignalingState(mozilla::dom::PCImplSignalingState* aState);
|
||||
|
||||
mozilla::dom::PCImplSignalingState SignalingState()
|
||||
{
|
||||
mozilla::dom::PCImplSignalingState state;
|
||||
|
@ -376,6 +385,7 @@ public:
|
|||
}
|
||||
|
||||
NS_IMETHODIMP SipccState(mozilla::dom::PCImplSipccState* aState);
|
||||
|
||||
mozilla::dom::PCImplSipccState SipccState()
|
||||
{
|
||||
mozilla::dom::PCImplSipccState state;
|
||||
|
@ -383,15 +393,28 @@ public:
|
|||
return state;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP IceState(mozilla::dom::PCImplIceState* aState);
|
||||
mozilla::dom::PCImplIceState IceState()
|
||||
NS_IMETHODIMP IceConnectionState(
|
||||
mozilla::dom::PCImplIceConnectionState* aState);
|
||||
|
||||
mozilla::dom::PCImplIceConnectionState IceConnectionState()
|
||||
{
|
||||
mozilla::dom::PCImplIceState state;
|
||||
IceState(&state);
|
||||
mozilla::dom::PCImplIceConnectionState state;
|
||||
IceConnectionState(&state);
|
||||
return state;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP IceGatheringState(
|
||||
mozilla::dom::PCImplIceGatheringState* aState);
|
||||
|
||||
mozilla::dom::PCImplIceGatheringState IceGatheringState()
|
||||
{
|
||||
mozilla::dom::PCImplIceGatheringState state;
|
||||
IceGatheringState(&state);
|
||||
return state;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Close();
|
||||
|
||||
void Close(ErrorResult &rv)
|
||||
{
|
||||
rv = Close();
|
||||
|
@ -489,7 +512,10 @@ private:
|
|||
void ShutdownMedia();
|
||||
|
||||
// ICE callbacks run on the right thread.
|
||||
nsresult IceStateChange_m(mozilla::dom::PCImplIceState aState);
|
||||
nsresult IceConnectionStateChange_m(
|
||||
mozilla::dom::PCImplIceConnectionState aState);
|
||||
nsresult IceGatheringStateChange_m(
|
||||
mozilla::dom::PCImplIceGatheringState aState);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
// Fills in an RTCStatsReportInternal. Must be run on STS.
|
||||
|
@ -521,7 +547,8 @@ private:
|
|||
mozilla::dom::PCImplSignalingState mSignalingState;
|
||||
|
||||
// ICE State
|
||||
mozilla::dom::PCImplIceState mIceState;
|
||||
mozilla::dom::PCImplIceConnectionState mIceConnectionState;
|
||||
mozilla::dom::PCImplIceGatheringState mIceGatheringState;
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
// TODO: Remove if we ever properly wire PeerConnection for cycle-collection.
|
||||
|
|
|
@ -178,12 +178,12 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
|
|||
CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__);
|
||||
return rv;
|
||||
}
|
||||
mIceCtx->SignalGatheringCompleted.connect(this,
|
||||
&PeerConnectionMedia::IceGatheringCompleted);
|
||||
mIceCtx->SignalCompleted.connect(this,
|
||||
&PeerConnectionMedia::IceCompleted);
|
||||
mIceCtx->SignalFailed.connect(this,
|
||||
&PeerConnectionMedia::IceFailed);
|
||||
mIceCtx->SignalGatheringStateChange.connect(
|
||||
this,
|
||||
&PeerConnectionMedia::IceGatheringStateChange);
|
||||
mIceCtx->SignalConnectionStateChange.connect(
|
||||
this,
|
||||
&PeerConnectionMedia::IceConnectionStateChange);
|
||||
|
||||
// Create three streams to start with.
|
||||
// One each for audio, video and DataChannel
|
||||
|
@ -424,24 +424,17 @@ PeerConnectionMedia::AddRemoteStreamHint(int aIndex, bool aIsVideo)
|
|||
|
||||
|
||||
void
|
||||
PeerConnectionMedia::IceGatheringCompleted(NrIceCtx *aCtx)
|
||||
PeerConnectionMedia::IceGatheringStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::GatheringState state)
|
||||
{
|
||||
MOZ_ASSERT(aCtx);
|
||||
SignalIceGatheringCompleted(aCtx);
|
||||
SignalIceGatheringStateChange(ctx, state);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::IceCompleted(NrIceCtx *aCtx)
|
||||
PeerConnectionMedia::IceConnectionStateChange(NrIceCtx* ctx,
|
||||
NrIceCtx::ConnectionState state)
|
||||
{
|
||||
MOZ_ASSERT(aCtx);
|
||||
SignalIceCompleted(aCtx);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::IceFailed(NrIceCtx *aCtx)
|
||||
{
|
||||
MOZ_ASSERT(aCtx);
|
||||
SignalIceFailed(aCtx);
|
||||
SignalIceConnectionStateChange(ctx, state);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -334,9 +334,10 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
}
|
||||
|
||||
// ICE state signals
|
||||
sigslot::signal1<mozilla::NrIceCtx *> SignalIceGatheringCompleted; // Done gathering
|
||||
sigslot::signal1<mozilla::NrIceCtx *> SignalIceCompleted; // Done handshaking
|
||||
sigslot::signal1<mozilla::NrIceCtx *> SignalIceFailed; // Self explanatory
|
||||
sigslot::signal2<mozilla::NrIceCtx*, mozilla::NrIceCtx::GatheringState>
|
||||
SignalIceGatheringStateChange;
|
||||
sigslot::signal2<mozilla::NrIceCtx*, mozilla::NrIceCtx::ConnectionState>
|
||||
SignalIceConnectionStateChange;
|
||||
|
||||
private:
|
||||
// Shutdown media transport. Must be called on STS thread.
|
||||
|
@ -347,9 +348,10 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
void SelfDestruct_m();
|
||||
|
||||
// ICE events
|
||||
void IceGatheringCompleted(mozilla::NrIceCtx *aCtx);
|
||||
void IceCompleted(mozilla::NrIceCtx *aCtx);
|
||||
void IceFailed(mozilla::NrIceCtx *aCtx);
|
||||
void IceGatheringStateChange(mozilla::NrIceCtx* ctx,
|
||||
mozilla::NrIceCtx::GatheringState state);
|
||||
void IceConnectionStateChange(mozilla::NrIceCtx* ctx,
|
||||
mozilla::NrIceCtx::ConnectionState state);
|
||||
void IceStreamReady(mozilla::NrIceMediaStream *aStream);
|
||||
|
||||
// The parent PC
|
||||
|
|
|
@ -416,7 +416,8 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
|
|||
{
|
||||
nsresult rv;
|
||||
PCImplReadyState gotready;
|
||||
PCImplIceState gotice;
|
||||
PCImplIceConnectionState gotice;
|
||||
PCImplIceGatheringState goticegathering;
|
||||
PCImplSipccState gotsipcc;
|
||||
PCImplSignalingState gotsignaling;
|
||||
|
||||
|
@ -431,13 +432,21 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
|
|||
<< PCImplReadyStateValues::strings[int(gotready)].value
|
||||
<< std::endl;
|
||||
break;
|
||||
case PCObserverStateType::IceState:
|
||||
rv = pc->IceState(&gotice);
|
||||
case PCObserverStateType::IceConnectionState:
|
||||
rv = pc->IceConnectionState(&gotice);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
std::cout << "ICE State: "
|
||||
<< PCImplIceStateValues::strings[int(gotice)].value
|
||||
std::cout << "ICE Connection State: "
|
||||
<< PCImplIceConnectionStateValues::strings[int(gotice)].value
|
||||
<< std::endl;
|
||||
break;
|
||||
case PCObserverStateType::IceGatheringState:
|
||||
rv = pc->IceGatheringState(&goticegathering);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
std::cout
|
||||
<< "ICE Gathering State: "
|
||||
<< PCImplIceGatheringStateValues::strings[int(goticegathering)].value
|
||||
<< std::endl;
|
||||
break;
|
||||
case PCObserverStateType::SdpState:
|
||||
std::cout << "SDP State: " << std::endl;
|
||||
// NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -458,6 +467,7 @@ TestObserver::OnStateChange(PCObserverStateType state_type, ER&, void*)
|
|||
break;
|
||||
default:
|
||||
// Unknown State
|
||||
MOZ_CRASH("Unknown state change type.");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -759,16 +769,19 @@ class SignalingAgent {
|
|||
}
|
||||
|
||||
void WaitForGather() {
|
||||
ASSERT_TRUE_WAIT(ice_state() == PCImplIceState::IceWaiting, 5000);
|
||||
ASSERT_TRUE_WAIT(ice_gathering_state() == PCImplIceGatheringState::Complete,
|
||||
5000);
|
||||
|
||||
std::cout << name << ": Init Complete" << std::endl;
|
||||
}
|
||||
|
||||
bool WaitForGatherAllowFail() {
|
||||
EXPECT_TRUE_WAIT(ice_state() == PCImplIceState::IceWaiting ||
|
||||
ice_state() == PCImplIceState::IceFailed, 5000);
|
||||
EXPECT_TRUE_WAIT(
|
||||
ice_gathering_state() == PCImplIceGatheringState::Complete ||
|
||||
ice_connection_state() == PCImplIceConnectionState::Failed,
|
||||
5000);
|
||||
|
||||
if (ice_state() == PCImplIceState::IceFailed) {
|
||||
if (ice_connection_state() == PCImplIceConnectionState::Failed) {
|
||||
std::cout << name << ": Init Failed" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
@ -782,9 +795,14 @@ class SignalingAgent {
|
|||
return pc->SipccState();
|
||||
}
|
||||
|
||||
PCImplIceState ice_state()
|
||||
PCImplIceConnectionState ice_connection_state()
|
||||
{
|
||||
return pc->IceState();
|
||||
return pc->IceConnectionState();
|
||||
}
|
||||
|
||||
PCImplIceGatheringState ice_gathering_state()
|
||||
{
|
||||
return pc->IceGatheringState();
|
||||
}
|
||||
|
||||
PCImplSignalingState signaling_state()
|
||||
|
@ -1041,7 +1059,7 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
|||
|
||||
|
||||
bool IceCompleted() {
|
||||
return pc->IceState() == PCImplIceState::IceConnected;
|
||||
return pc->IceConnectionState() == PCImplIceConnectionState::Connected;
|
||||
}
|
||||
|
||||
void AddIceCandidate(const char* candidate, const char* mid, unsigned short level,
|
||||
|
|
Загрузка…
Ссылка в новой задаче