зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1318180: turn network offline events into ice disconnected event. r=bwc,jib
MozReview-Commit-ID: Kqbicl2goL2 --HG-- extra : rebase_source : 4ed7d1364af8bd1575e2ced1bd8512405e0dd669
This commit is contained in:
Родитель
c7690fb4ef
Коммит
2ca25c39f6
|
@ -182,19 +182,11 @@ GlobalPCList.prototype = {
|
|||
}
|
||||
} else if (topic == "profile-change-net-teardown" ||
|
||||
topic == "network:offline-about-to-go-offline") {
|
||||
// Delete all peerconnections on shutdown - mostly synchronously (we
|
||||
// need them to be done deleting transports and streams before we
|
||||
// return)! All socket operations must be queued to STS thread
|
||||
// before we return to here.
|
||||
// Also kill them if "Work Offline" is selected - more can be created
|
||||
// while offline, but attempts to connect them should fail.
|
||||
for (let winId in this._list) {
|
||||
cleanupWinId(this._list, winId);
|
||||
}
|
||||
// As Necko doesn't prevent us from accessing the network we still need to
|
||||
// monitor the network offline/online state here. See bug 1326483
|
||||
this._networkdown = true;
|
||||
} else if (topic == "network:offline-status-changed") {
|
||||
if (data == "offline") {
|
||||
// this._list shold be empty here
|
||||
this._networkdown = true;
|
||||
} else if (data == "online") {
|
||||
this._networkdown = false;
|
||||
|
@ -1211,9 +1203,11 @@ RTCPeerConnection.prototype = {
|
|||
},
|
||||
|
||||
changeIceConnectionState: function(state) {
|
||||
this._iceConnectionState = state;
|
||||
_globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
|
||||
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
|
||||
if (state != this._iceConnectionState) {
|
||||
this._iceConnectionState = state;
|
||||
_globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
|
||||
this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
|
||||
}
|
||||
},
|
||||
|
||||
getStats: function(selector, onSucc, onErr) {
|
||||
|
@ -1370,35 +1364,25 @@ PeerConnectionObserver.prototype = {
|
|||
//
|
||||
// iceConnectionState:
|
||||
// -------------------
|
||||
// new The ICE Agent is gathering addresses and/or waiting for
|
||||
// remote candidates to be supplied.
|
||||
// new Any of the RTCIceTransports are in the new state and none
|
||||
// of them are in the checking, failed or disconnected state.
|
||||
//
|
||||
// checking The ICE Agent has received remote candidates on at least
|
||||
// one component, and is checking candidate pairs but has not
|
||||
// yet found a connection. In addition to checking, it may
|
||||
// also still be gathering.
|
||||
// checking Any of the RTCIceTransports are in the checking state and
|
||||
// none of them are in the failed or disconnected state.
|
||||
//
|
||||
// connected The ICE Agent has found a usable connection for all
|
||||
// components but is still checking other candidate pairs to
|
||||
// see if there is a better connection. It may also still be
|
||||
// gathering.
|
||||
//
|
||||
// completed The ICE Agent has finished gathering and checking and found
|
||||
// a connection for all components. Open issue: it is not
|
||||
// clear how the non controlling ICE side knows it is in the
|
||||
// connected All RTCIceTransports are in the connected, completed or
|
||||
// closed state and at least one of them is in the connected
|
||||
// state.
|
||||
//
|
||||
// failed The ICE Agent is finished checking all candidate pairs and
|
||||
// failed to find a connection for at least one component.
|
||||
// Connections may have been found for some components.
|
||||
// completed All RTCIceTransports are in the completed or closed state
|
||||
// and at least one of them is in the completed state.
|
||||
//
|
||||
// disconnected Liveness checks have failed for one or more components.
|
||||
// This is more aggressive than failed, and may trigger
|
||||
// intermittently (and resolve itself without action) on a
|
||||
// flaky network.
|
||||
// failed Any of the RTCIceTransports are in the failed state.
|
||||
//
|
||||
// closed The ICE Agent has shut down and is no longer responding to
|
||||
// STUN requests.
|
||||
// disconnected Any of the RTCIceTransports are in the disconnected state
|
||||
// and none of them are in the failed state.
|
||||
//
|
||||
// closed All of the RTCIceTransports are in the closed state.
|
||||
|
||||
handleIceConnectionStateChange: function(iceConnectionState) {
|
||||
let pc = this._dompc;
|
||||
|
|
|
@ -971,6 +971,16 @@ nsresult NrIceCtx::Finalize() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void NrIceCtx::UpdateNetworkState(bool online) {
|
||||
MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): updating network state to " <<
|
||||
(online ? "online" : "offline"));
|
||||
if (online) {
|
||||
nr_ice_peer_ctx_refresh_consent_all_streams(peer_);
|
||||
} else {
|
||||
nr_ice_peer_ctx_disconnect_all_streams(peer_);
|
||||
}
|
||||
}
|
||||
|
||||
void NrIceCtx::SetConnectionState(ConnectionState state) {
|
||||
if (state == connection_state_)
|
||||
return;
|
||||
|
|
|
@ -314,6 +314,9 @@ class NrIceCtx {
|
|||
// Start checking
|
||||
nsresult StartChecks();
|
||||
|
||||
// Notify that the network has gone online/offline
|
||||
void UpdateNetworkState(bool online);
|
||||
|
||||
// Finalize the ICE negotiation. I.e., there will be no
|
||||
// more forking.
|
||||
nsresult Finalize();
|
||||
|
|
|
@ -1366,6 +1366,26 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
void ChangeNetworkState_s(bool online) {
|
||||
ice_ctx_->ctx()->UpdateNetworkState(online);
|
||||
}
|
||||
|
||||
void ChangeNetworkStateToOffline() {
|
||||
test_utils_->sts_target()->Dispatch(
|
||||
WrapRunnable(this,
|
||||
&IceTestPeer::ChangeNetworkState_s,
|
||||
false),
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
void ChangeNetworkStateToOnline() {
|
||||
test_utils_->sts_target()->Dispatch(
|
||||
WrapRunnable(this,
|
||||
&IceTestPeer::ChangeNetworkState_s,
|
||||
true),
|
||||
NS_DISPATCH_SYNC);
|
||||
}
|
||||
|
||||
int trickled() { return trickled_; }
|
||||
|
||||
void SetControlling(NrIceCtx::Controlling controlling) {
|
||||
|
@ -3350,6 +3370,49 @@ TEST_F(WebRtcIceConnectTest, TestConsentDelayed) {
|
|||
SendReceive();
|
||||
}
|
||||
|
||||
TEST_F(WebRtcIceConnectTest, TestNetworkForcedOfflineAndRecovery) {
|
||||
AddStream(1);
|
||||
SetupAndCheckConsent();
|
||||
p1_->ChangeNetworkStateToOffline();
|
||||
ASSERT_TRUE_WAIT(p1_->ice_connected() == 0, kDefaultTimeout);
|
||||
// Next round of consent check should switch it back to online
|
||||
ASSERT_TRUE_WAIT(p1_->ice_connected(), kDefaultTimeout);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcIceConnectTest, TestNetworkForcedOfflineTwice) {
|
||||
AddStream(1);
|
||||
SetupAndCheckConsent();
|
||||
p2_->ChangeNetworkStateToOffline();
|
||||
ASSERT_TRUE_WAIT(p2_->ice_connected() == 0, kDefaultTimeout);
|
||||
p2_->ChangeNetworkStateToOffline();
|
||||
ASSERT_TRUE_WAIT(p2_->ice_connected() == 0, kDefaultTimeout);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcIceConnectTest, TestNetworkOnlineDoesntChangeState) {
|
||||
AddStream(1);
|
||||
SetupAndCheckConsent();
|
||||
p2_->ChangeNetworkStateToOnline();
|
||||
ASSERT_TRUE(p2_->ice_connected());
|
||||
PR_Sleep(1500);
|
||||
p2_->ChangeNetworkStateToOnline();
|
||||
ASSERT_TRUE(p2_->ice_connected());
|
||||
}
|
||||
|
||||
TEST_F(WebRtcIceConnectTest, TestNetworkOnlineTriggersConsent) {
|
||||
// Let's emulate audio + video w/o rtcp-mux
|
||||
AddStream(2);
|
||||
AddStream(2);
|
||||
SetupAndCheckConsent();
|
||||
p1_->ChangeNetworkStateToOffline();
|
||||
p1_->SetBlockStun(true);
|
||||
ASSERT_TRUE_WAIT(p1_->ice_connected() == 0, kDefaultTimeout);
|
||||
PR_Sleep(1500);
|
||||
ASSERT_TRUE(p1_->ice_connected() == 0);
|
||||
p1_->SetBlockStun(false);
|
||||
p1_->ChangeNetworkStateToOnline();
|
||||
ASSERT_TRUE_WAIT(p1_->ice_connected(), 500);
|
||||
}
|
||||
|
||||
TEST_F(WebRtcIceConnectTest, TestConnectTurn) {
|
||||
if (turn_server_.empty())
|
||||
return;
|
||||
|
|
|
@ -1242,13 +1242,22 @@ static void nr_ice_component_consent_timeout_cb(NR_SOCKET s, int how, void *cb_a
|
|||
}
|
||||
|
||||
|
||||
static void nr_ice_component_consent_request_timed_out(nr_ice_component *comp)
|
||||
void nr_ice_component_disconnected(nr_ice_component *comp)
|
||||
{
|
||||
if (!comp->can_send) {
|
||||
return;
|
||||
}
|
||||
|
||||
nr_ice_peer_ctx_disconnected(comp->stream->pctx);
|
||||
if (comp->disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
r_log(LOG_ICE,LOG_WARNING,"ICE(%s)/STREAM(%s)/COMP(%d): component disconnected",
|
||||
comp->ctx->label, comp->stream->label, comp->component_id);
|
||||
comp->disconnected = 1;
|
||||
|
||||
/* a single disconnected component disconnects the stream */
|
||||
nr_ice_media_stream_set_disconnected(comp->stream, NR_ICE_MEDIA_STREAM_DISCONNECTED);
|
||||
}
|
||||
|
||||
static void nr_ice_component_consent_refreshed(nr_ice_component *comp)
|
||||
|
@ -1264,7 +1273,9 @@ static void nr_ice_component_consent_refreshed(nr_ice_component *comp)
|
|||
comp->ctx->label, comp->stream->label, comp->component_id,
|
||||
comp->consent_last_seen.tv_sec);
|
||||
|
||||
nr_ice_peer_ctx_connected(comp->stream->pctx);
|
||||
comp->disconnected = 0;
|
||||
|
||||
nr_ice_media_stream_check_if_connected(comp->stream);
|
||||
|
||||
if (comp->consent_timeout)
|
||||
NR_async_timer_cancel(comp->consent_timeout);
|
||||
|
@ -1297,7 +1308,7 @@ static void nr_ice_component_refresh_consent_cb(NR_SOCKET s, int how, void *cb_a
|
|||
case NR_STUN_CLIENT_STATE_TIMED_OUT:
|
||||
r_log(LOG_ICE, LOG_INFO, "ICE(%s)/STREAM(%s)/COMP(%d): A single consent refresh request timed out",
|
||||
comp->ctx->label, comp->stream->label, comp->component_id);
|
||||
nr_ice_component_consent_request_timed_out(comp);
|
||||
nr_ice_component_disconnected(comp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1340,6 +1351,9 @@ static void nr_ice_component_consent_timer_cb(NR_SOCKET s, int how, void *cb_arg
|
|||
nr_ice_component *comp=cb_arg;
|
||||
int r;
|
||||
|
||||
if (comp->consent_timer) {
|
||||
NR_async_timer_cancel(comp->consent_timer);
|
||||
}
|
||||
comp->consent_timer = 0;
|
||||
|
||||
comp->consent_ctx->params.ice_binding_request.username =
|
||||
|
@ -1361,12 +1375,6 @@ static void nr_ice_component_consent_timer_cb(NR_SOCKET s, int how, void *cb_arg
|
|||
comp)) {
|
||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s)/STREAM(%s)/COMP(%d): Refresh consent failed with %d",
|
||||
comp->ctx->label, comp->stream->label, comp->component_id, r);
|
||||
/* In case our attempt to send the refresh binding request reports an
|
||||
* error we don't have to wait for timeouts, but declare this connection
|
||||
* dead right away. */
|
||||
if (r != R_WOULDBLOCK) {
|
||||
nr_ice_component_consent_failed(comp);
|
||||
}
|
||||
}
|
||||
|
||||
nr_ice_component_consent_schedule_consent_timer(comp);
|
||||
|
@ -1384,6 +1392,11 @@ void nr_ice_component_consent_schedule_consent_timer(nr_ice_component *comp)
|
|||
&comp->consent_timer);
|
||||
}
|
||||
|
||||
void nr_ice_component_refresh_consent_now(nr_ice_component *comp)
|
||||
{
|
||||
nr_ice_component_consent_timer_cb(0, 0, comp);
|
||||
}
|
||||
|
||||
void nr_ice_component_consent_destroy(nr_ice_component *comp)
|
||||
{
|
||||
if (comp->consent_timer) {
|
||||
|
@ -1401,6 +1414,7 @@ void nr_ice_component_consent_destroy(nr_ice_component *comp)
|
|||
}
|
||||
if (comp->consent_ctx) {
|
||||
nr_stun_client_ctx_destroy(&comp->consent_ctx);
|
||||
comp->consent_ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1411,6 +1425,8 @@ int nr_ice_component_setup_consent(nr_ice_component *comp)
|
|||
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s)/STREAM(%s)/COMP(%d): Setting up refresh consent",
|
||||
comp->ctx->label, comp->stream->label, comp->component_id);
|
||||
|
||||
nr_ice_component_consent_destroy(comp);
|
||||
|
||||
if (r=nr_stun_client_ctx_create("consent", comp->active->local->osock,
|
||||
&comp->active->remote->addr, 0,
|
||||
&comp->consent_ctx))
|
||||
|
@ -1423,6 +1439,7 @@ int nr_ice_component_setup_consent(nr_ice_component *comp)
|
|||
ABORT(r);
|
||||
|
||||
comp->can_send = 1;
|
||||
comp->disconnected = 0;
|
||||
nr_ice_component_consent_refreshed(comp);
|
||||
|
||||
nr_ice_component_consent_calc_consent_timer(comp);
|
||||
|
|
|
@ -75,6 +75,7 @@ struct nr_ice_component_ {
|
|||
void *consent_timeout;
|
||||
void *consent_handle;
|
||||
int can_send;
|
||||
int disconnected;
|
||||
struct timeval consent_last_seen;
|
||||
|
||||
STAILQ_ENTRY(nr_ice_component_)entry;
|
||||
|
@ -97,6 +98,8 @@ int nr_ice_component_set_failed(nr_ice_component *comp);
|
|||
int nr_ice_component_finalize(nr_ice_component *lcomp, nr_ice_component *rcomp);
|
||||
int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair);
|
||||
int nr_ice_component_get_default_candidate(nr_ice_component *comp, nr_ice_candidate **candp, int ip_version);
|
||||
void nr_ice_component_refresh_consent_now(nr_ice_component *comp);
|
||||
void nr_ice_component_disconnected(nr_ice_component *comp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ static char *RCSSTRING __UNUSED__="$Id: ice_media_stream.c,v 1.2 2008/04/28 17:5
|
|||
#include "ice_ctx.h"
|
||||
|
||||
static char *nr_ice_media_stream_states[]={"INVALID",
|
||||
"UNPAIRED","FROZEN","ACTIVE","COMPLETED","FAILED"
|
||||
"UNPAIRED","FROZEN","ACTIVE","CONNECTED","FAILED"
|
||||
};
|
||||
|
||||
int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state);
|
||||
|
@ -74,6 +74,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,char *label,int components, nr_ic
|
|||
TAILQ_INIT(&stream->check_list);
|
||||
TAILQ_INIT(&stream->trigger_check_queue);
|
||||
|
||||
stream->disconnected = 0;
|
||||
stream->component_ct=components;
|
||||
stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
|
||||
*streamp=stream;
|
||||
|
@ -339,7 +340,7 @@ static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
|
|||
pair=TAILQ_NEXT(pair,triggered_check_queue_entry);
|
||||
}
|
||||
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
|
||||
if(!pair){
|
||||
/* Find the highest priority WAITING check and move it to RUNNING */
|
||||
pair=TAILQ_FIRST(&stream->check_list);
|
||||
|
@ -392,7 +393,7 @@ int nr_ice_media_stream_start_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream
|
|||
/* 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. */
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED) {
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
|
||||
if(r=nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE)) {
|
||||
ABORT(r);
|
||||
}
|
||||
|
@ -584,6 +585,80 @@ int nr_ice_media_stream_set_state(nr_ice_media_stream *str, int state)
|
|||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void nr_ice_media_stream_refresh_consent_all(nr_ice_media_stream *stream)
|
||||
{
|
||||
nr_ice_component *comp;
|
||||
|
||||
comp=STAILQ_FIRST(&stream->components);
|
||||
while(comp){
|
||||
if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
|
||||
(comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
|
||||
comp->disconnected) {
|
||||
nr_ice_component_refresh_consent_now(comp);
|
||||
}
|
||||
|
||||
comp=STAILQ_NEXT(comp,entry);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ice_media_stream_disconnect_all_components(nr_ice_media_stream *stream)
|
||||
{
|
||||
nr_ice_component *comp;
|
||||
|
||||
comp=STAILQ_FIRST(&stream->components);
|
||||
while(comp){
|
||||
if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
|
||||
(comp->local_component->state != NR_ICE_COMPONENT_DISABLED)) {
|
||||
comp->disconnected = 1;
|
||||
}
|
||||
|
||||
comp=STAILQ_NEXT(comp,entry);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disconnected)
|
||||
{
|
||||
if (stream->disconnected == disconnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream->ice_state != NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED) {
|
||||
return;
|
||||
}
|
||||
stream->disconnected = disconnected;
|
||||
|
||||
if (disconnected == NR_ICE_MEDIA_STREAM_DISCONNECTED) {
|
||||
nr_ice_peer_ctx_disconnected(stream->pctx);
|
||||
} else {
|
||||
nr_ice_peer_ctx_check_if_connected(stream->pctx);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_ice_media_stream_check_if_connected(nr_ice_media_stream *stream)
|
||||
{
|
||||
nr_ice_component *comp;
|
||||
|
||||
comp=STAILQ_FIRST(&stream->components);
|
||||
while(comp){
|
||||
if((comp->state != NR_ICE_COMPONENT_DISABLED) &&
|
||||
(comp->local_component->state != NR_ICE_COMPONENT_DISABLED) &&
|
||||
comp->disconnected)
|
||||
break;
|
||||
|
||||
comp=STAILQ_NEXT(comp,entry);
|
||||
}
|
||||
|
||||
/* At least one disconnected component */
|
||||
if(comp)
|
||||
goto done;
|
||||
|
||||
nr_ice_media_stream_set_disconnected(stream, NR_ICE_MEDIA_STREAM_CONNECTED);
|
||||
|
||||
done:
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@ -607,7 +682,7 @@ int nr_ice_media_stream_component_nominated(nr_ice_media_stream *stream,nr_ice_c
|
|||
|
||||
/* 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);
|
||||
nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED);
|
||||
nr_ice_media_stream_set_state(stream,NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED);
|
||||
|
||||
/* Cancel our timer */
|
||||
if(stream->timer){
|
||||
|
@ -747,8 +822,12 @@ int nr_ice_media_stream_send(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, in
|
|||
2. Use the address on the remote side
|
||||
*/
|
||||
if(r=nr_socket_sendto(comp->active->local->osock,data,len,0,
|
||||
&comp->active->remote->addr))
|
||||
&comp->active->remote->addr)) {
|
||||
if ((r==R_IO_ERROR) || (r==R_EOD)) {
|
||||
nr_ice_component_disconnected(comp);
|
||||
}
|
||||
ABORT(r);
|
||||
}
|
||||
|
||||
_status=0;
|
||||
abort:
|
||||
|
|
|
@ -59,9 +59,14 @@ struct nr_ice_media_stream_ {
|
|||
#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE 3
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED 4
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED 4
|
||||
#define NR_ICE_MEDIA_STREAM_CHECKS_FAILED 5
|
||||
|
||||
int disconnected;
|
||||
|
||||
#define NR_ICE_MEDIA_STREAM_CONNECTED 0
|
||||
#define NR_ICE_MEDIA_STREAM_DISCONNECTED 1
|
||||
|
||||
nr_ice_cand_pair_head check_list;
|
||||
nr_ice_cand_pair_head trigger_check_queue;
|
||||
void *timer; /* Check list periodic timer */
|
||||
|
@ -87,6 +92,10 @@ int nr_ice_media_stream_unfreeze_pairs_foundation(nr_ice_media_stream *stream, c
|
|||
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_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);
|
||||
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);
|
||||
|
|
|
@ -648,12 +648,45 @@ int nr_ice_peer_ctx_dump_state(nr_ice_peer_ctx *pctx,FILE *out)
|
|||
}
|
||||
#endif
|
||||
|
||||
void nr_ice_peer_ctx_refresh_consent_all_streams(nr_ice_peer_ctx *pctx)
|
||||
{
|
||||
nr_ice_media_stream *str;
|
||||
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): refreshing consent on all streams",pctx->label);
|
||||
|
||||
str=STAILQ_FIRST(&pctx->peer_streams);
|
||||
while(str) {
|
||||
nr_ice_media_stream_refresh_consent_all(str);
|
||||
str=STAILQ_NEXT(str,entry);
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx)
|
||||
{
|
||||
if (pctx->reported_connected &&
|
||||
pctx->handler &&
|
||||
pctx->handler->vtbl->ice_disconnected) {
|
||||
pctx->handler->vtbl->ice_disconnected(pctx->handler->obj, pctx);
|
||||
|
||||
pctx->reported_connected = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void nr_ice_peer_ctx_disconnect_all_streams(nr_ice_peer_ctx *pctx)
|
||||
{
|
||||
nr_ice_media_stream *str;
|
||||
|
||||
r_log(LOG_ICE,LOG_INFO,"ICE-PEER(%s): disconnecting all streams",pctx->label);
|
||||
|
||||
str=STAILQ_FIRST(&pctx->peer_streams);
|
||||
while(str) {
|
||||
nr_ice_media_stream_disconnect_all_components(str);
|
||||
|
||||
/* The first stream to be disconnected will cause the peer ctx to signal
|
||||
the disconnect up. */
|
||||
nr_ice_media_stream_set_disconnected(str, NR_ICE_MEDIA_STREAM_DISCONNECTED);
|
||||
|
||||
str=STAILQ_NEXT(str,entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -687,7 +720,7 @@ int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx)
|
|||
|
||||
str=STAILQ_FIRST(&pctx->peer_streams);
|
||||
while(str){
|
||||
if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_COMPLETED){
|
||||
if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED){
|
||||
succeeded++;
|
||||
}
|
||||
else if(str->ice_state==NR_ICE_MEDIA_STREAM_CHECKS_FAILED){
|
||||
|
@ -716,7 +749,6 @@ int nr_ice_peer_ctx_check_if_connected(nr_ice_peer_ctx *pctx)
|
|||
|
||||
done:
|
||||
_status=0;
|
||||
// abort:
|
||||
return(_status);
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,8 @@ int nr_ice_peer_ctx_parse_global_attributes(nr_ice_peer_ctx *pctx, char **attrs,
|
|||
int nr_ice_peer_ctx_start_checks(nr_ice_peer_ctx *pctx);
|
||||
int nr_ice_peer_ctx_start_checks2(nr_ice_peer_ctx *pctx, int allow_non_first);
|
||||
void nr_ice_peer_ctx_stream_started_checks(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream);
|
||||
void nr_ice_peer_ctx_refresh_consent_all_streams(nr_ice_peer_ctx *pctx);
|
||||
void nr_ice_peer_ctx_disconnect_all_streams(nr_ice_peer_ctx *pctx);
|
||||
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);
|
||||
|
|
|
@ -22,9 +22,12 @@
|
|||
#include "nsServiceManagerUtils.h" // do_GetService
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIIOService.h" // NS_IOSERVICE_*
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
#include "nsCRTGlue.h"
|
||||
|
||||
#include "gmp-video-decode.h" // GMP_API_VIDEO_DECODER
|
||||
#include "gmp-video-encode.h" // GMP_API_VIDEO_ENCODER
|
||||
|
||||
|
@ -34,12 +37,12 @@ namespace mozilla {
|
|||
|
||||
using namespace dom;
|
||||
|
||||
class PeerConnectionCtxShutdown : public nsIObserver
|
||||
class PeerConnectionCtxObserver : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
PeerConnectionCtxShutdown() {}
|
||||
PeerConnectionCtxObserver() {}
|
||||
|
||||
void Init()
|
||||
{
|
||||
|
@ -55,6 +58,10 @@ public:
|
|||
NS_XPCOM_SHUTDOWN_OBSERVER_ID,
|
||||
false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
rv = observerService->AddObserver(this,
|
||||
NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
|
||||
false);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
#endif
|
||||
(void) rv;
|
||||
}
|
||||
|
@ -71,34 +78,52 @@ public:
|
|||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = observerService->RemoveObserver(this,
|
||||
NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
rv = observerService->RemoveObserver(this,
|
||||
NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
MOZ_ALWAYS_SUCCEEDS(rv);
|
||||
|
||||
// Make sure we're not deleted while still inside ::Observe()
|
||||
RefPtr<PeerConnectionCtxShutdown> kungFuDeathGrip(this);
|
||||
PeerConnectionCtx::gPeerConnectionCtxShutdown = nullptr;
|
||||
RefPtr<PeerConnectionCtxObserver> kungFuDeathGrip(this);
|
||||
PeerConnectionCtx::gPeerConnectionCtxObserver = nullptr;
|
||||
}
|
||||
if (strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC) == 0) {
|
||||
const nsLiteralString onlineString(u"" NS_IOSERVICE_ONLINE);
|
||||
const nsLiteralString offlineString(u"" NS_IOSERVICE_OFFLINE);
|
||||
if (NS_strcmp(aData, offlineString.get()) == 0) {
|
||||
CSFLogDebug(logTag, "Updating network state to offline");
|
||||
PeerConnectionCtx::UpdateNetworkState(false);
|
||||
} else if(NS_strcmp(aData, onlineString.get()) == 0) {
|
||||
CSFLogDebug(logTag, "Updating network state to online");
|
||||
PeerConnectionCtx::UpdateNetworkState(true);
|
||||
} else {
|
||||
CSFLogDebug(logTag, "Received unsupported network state event");
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~PeerConnectionCtxShutdown()
|
||||
virtual ~PeerConnectionCtxObserver()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
services::GetObserverService();
|
||||
if (observerService)
|
||||
observerService->RemoveObserver(this, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
|
||||
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(PeerConnectionCtxShutdown, nsIObserver);
|
||||
NS_IMPL_ISUPPORTS(PeerConnectionCtxObserver, nsIObserver);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
PeerConnectionCtx* PeerConnectionCtx::gInstance;
|
||||
nsIThread* PeerConnectionCtx::gMainThread;
|
||||
StaticRefPtr<PeerConnectionCtxShutdown> PeerConnectionCtx::gPeerConnectionCtxShutdown;
|
||||
StaticRefPtr<PeerConnectionCtxObserver> PeerConnectionCtx::gPeerConnectionCtxObserver;
|
||||
|
||||
const std::map<const std::string, PeerConnectionImpl *>&
|
||||
PeerConnectionCtx::mGetPeerConnections()
|
||||
|
@ -129,9 +154,9 @@ nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
|
|||
|
||||
gInstance = ctx;
|
||||
|
||||
if (!PeerConnectionCtx::gPeerConnectionCtxShutdown) {
|
||||
PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown();
|
||||
PeerConnectionCtx::gPeerConnectionCtxShutdown->Init();
|
||||
if (!PeerConnectionCtx::gPeerConnectionCtxObserver) {
|
||||
PeerConnectionCtx::gPeerConnectionCtxObserver = new PeerConnectionCtxObserver();
|
||||
PeerConnectionCtx::gPeerConnectionCtxObserver->Init();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,6 +359,17 @@ PeerConnectionCtx::EverySecondTelemetryCallback_m(nsITimer* timer, void *closure
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
PeerConnectionCtx::UpdateNetworkState(bool online) {
|
||||
auto ctx = GetInstance();
|
||||
if (ctx->mPeerConnections.empty()) {
|
||||
return;
|
||||
}
|
||||
for (auto pc : ctx->mPeerConnections) {
|
||||
pc.second->UpdateNetworkState(online);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult PeerConnectionCtx::Initialize() {
|
||||
initGMP();
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "nsIRunnable.h"
|
||||
|
||||
namespace mozilla {
|
||||
class PeerConnectionCtxShutdown;
|
||||
class PeerConnectionCtxObserver;
|
||||
|
||||
namespace dom {
|
||||
class WebrtcGlobalInformation;
|
||||
|
@ -48,6 +48,8 @@ class PeerConnectionCtx {
|
|||
|
||||
bool gmpHasH264();
|
||||
|
||||
static void UpdateNetworkState(bool online);
|
||||
|
||||
// Make these classes friend so that they can access mPeerconnections.
|
||||
friend class PeerConnectionImpl;
|
||||
friend class PeerConnectionWrapper;
|
||||
|
@ -101,7 +103,7 @@ private:
|
|||
static PeerConnectionCtx *gInstance;
|
||||
public:
|
||||
static nsIThread *gMainThread;
|
||||
static mozilla::StaticRefPtr<mozilla::PeerConnectionCtxShutdown> gPeerConnectionCtxShutdown;
|
||||
static mozilla::StaticRefPtr<mozilla::PeerConnectionCtxObserver> gPeerConnectionCtxObserver;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -2297,10 +2297,17 @@ PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, un
|
|||
pco->OnAddIceCandidateError(error, ObString(errorString.c_str()), rv);
|
||||
}
|
||||
|
||||
UpdateSignalingState();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionImpl::UpdateNetworkState(bool online) {
|
||||
if (!mMedia) {
|
||||
return;
|
||||
}
|
||||
mMedia->UpdateNetworkState(online);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
PeerConnectionImpl::CloseStreams() {
|
||||
PC_AUTO_ENTER_API_CALL(false);
|
||||
|
@ -3364,8 +3371,6 @@ PeerConnectionImpl::CandidateReady(const std::string& candidate,
|
|||
CSFLogDebug(logTag, "Passing local candidate to content: %s",
|
||||
candidate.c_str());
|
||||
SendLocalIceCandidateToContent(level, mid, candidate);
|
||||
|
||||
UpdateSignalingState();
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -414,6 +414,8 @@ public:
|
|||
NS_ConvertUTF16toUTF8(aMid).get(), aLevel);
|
||||
}
|
||||
|
||||
void UpdateNetworkState(bool online);
|
||||
|
||||
NS_IMETHODIMP CloseStreams();
|
||||
|
||||
void CloseStreams(ErrorResult &rv)
|
||||
|
|
|
@ -858,6 +858,7 @@ PeerConnectionMedia::AddIceCandidate(const std::string& candidate,
|
|||
aMLine),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate,
|
||||
const std::string& aMid,
|
||||
|
@ -877,6 +878,21 @@ PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::UpdateNetworkState(bool online) {
|
||||
RUN_ON_THREAD(GetSTSThread(),
|
||||
WrapRunnable(
|
||||
RefPtr<PeerConnectionMedia>(this),
|
||||
&PeerConnectionMedia::UpdateNetworkState_s,
|
||||
online),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::UpdateNetworkState_s(bool online) {
|
||||
mIceCtxHdlr->ctx()->UpdateNetworkState(online);
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionMedia::FlushIceCtxOperationQueueIfReady()
|
||||
{
|
||||
|
|
|
@ -292,6 +292,9 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
void AddIceCandidate(const std::string& candidate, const std::string& mid,
|
||||
uint32_t aMLine);
|
||||
|
||||
// Handle notifications of network online/offline events.
|
||||
void UpdateNetworkState(bool online);
|
||||
|
||||
// Handle complete media pipelines.
|
||||
nsresult UpdateMediaPipelines(const JsepSession& session);
|
||||
|
||||
|
@ -491,6 +494,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
|
||||
uint32_t aMLine);
|
||||
|
||||
void UpdateNetworkState_s(bool online);
|
||||
|
||||
// ICE events
|
||||
void IceGatheringStateChange_s(NrIceCtx* ctx,
|
||||
|
|
Загрузка…
Ссылка в новой задаче