Browse Source

Try to recover from (some) lost p2p connection state.

When the ICE connection state changes to "disconnected"/"failed",
these calls are marked and get re-called for conferences once the
connection is back and are allowed to send an "Offer" again.
This works in cases where the complete connectivity is lost for one
client while being in a conference once it comes back afterwards
for him.
Doesn't work reliably on Firefox as no "disconnected"/"failed" is
triggered there.
pull/294/head
Joachim Bauch 9 years ago
parent
commit
c8763deb58
  1. 36
      static/js/mediastream/peerconference.js
  2. 30
      static/js/mediastream/webrtc.js

36
static/js/mediastream/peerconference.js

@ -36,6 +36,9 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
this.callsCount = 0; this.callsCount = 0;
this.callStates = {}; this.callStates = {};
this.connectedCalls = {}; this.connectedCalls = {};
// Ids of calls that "seem" to be disconnected (i.e. had a p2p state
// change of "disconnected" without a "Bye").
this.disconnectedCalls = {};
this.conferenceMode = false; this.conferenceMode = false;
this.e = $({}); this.e = $({});
@ -70,9 +73,13 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
}; };
PeerConference.prototype._addCallWithState = function(id, call, state) { PeerConference.prototype._addCallWithState = function(id, call, state) {
if (this.calls.hasOwnProperty(id)) { var oldcall = this.calls[id];
console.warn("Already has a call for", id); if (oldcall) {
return false; if (!this.disconnectedCalls[id]) {
console.warn("Already has a call for", id);
return false;
}
oldcall.close(); // This will remove the call from the conference.
} }
this.calls[id] = call; this.calls[id] = call;
@ -101,6 +108,9 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
}; };
PeerConference.prototype.getCall = function(id) { PeerConference.prototype.getCall = function(id) {
if (this.disconnectedCalls[id]) {
return null;
}
return this.calls[id] || null; return this.calls[id] || null;
}; };
@ -121,10 +131,23 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
delete this.calls[id]; delete this.calls[id];
delete this.callStates[id]; delete this.callStates[id];
delete this.connectedCalls[id]; delete this.connectedCalls[id];
delete this.disconnectedCalls[id];
this.callsCount -= 1; this.callsCount -= 1;
return call; return call;
}; };
PeerConference.prototype.markDisconnected = function(id) {
this.disconnectedCalls[id] = true;
};
PeerConference.prototype.isDisconnected = function(id) {
return this.disconnectedCalls[id] || false;
};
PeerConference.prototype.getDisconnectedIds = function(id) {
return _.keys(this.disconnectedCalls);
};
PeerConference.prototype.close = function() { PeerConference.prototype.close = function() {
var api = this.webrtc.api; var api = this.webrtc.api;
@ -161,13 +184,18 @@ define(['jquery', 'underscore', 'mediastream/peercall'], function($, _, PeerCall
}; };
PeerConference.prototype.pushUpdate = function() { PeerConference.prototype.pushUpdate = function(forceAll) {
if (this.webrtc.isConferenceRoom()) { if (this.webrtc.isConferenceRoom()) {
// Conference is managed on the server. // Conference is managed on the server.
return; return;
} }
var ids = _.keys(this.connectedCalls); var ids = _.keys(this.connectedCalls);
if (forceAll) {
// Include "disconnected" calls to try to recover from a previous
// lost connection.
ids = _.union(ids, this.getDisconnectedIds());
}
if (ids.length > 1) { if (ids.length > 1) {
ids.push(this.webrtc.api.id); ids.push(this.webrtc.api.id);
console.log("Calls in conference:", ids); console.log("Calls in conference:", ids);

30
static/js/mediastream/webrtc.js

@ -161,6 +161,17 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
}; };
WebRTC.prototype.receivedRoom = function(event, room) { WebRTC.prototype.receivedRoom = function(event, room) {
if (this.currentroom && room && this.currentroom.Name == room.Name) {
// No room change, usually happens on reconnect.
var ids = this.conference.getDisconnectedIds();
if (ids.length > 1 && this.conference.id) {
// User was in a conference before, try to re-establish.
console.log("Re-establishing conference", this.conference.id, ids);
this.conference.pushUpdate(true);
}
return;
}
if (this.isConferenceRoom()) { if (this.isConferenceRoom()) {
// Switching from a conference room closes all current connections. // Switching from a conference room closes all current connections.
_.defer(_.bind(function() { _.defer(_.bind(function() {
@ -288,7 +299,7 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
// Clean own internal data before feeding into browser. // Clean own internal data before feeding into browser.
delete data._conference; delete data._conference;
autoaccept = true; autoaccept = true;
} else if (this.conference.hasCalls()) { } else if (this.conference.hasCalls() && !this.conference.isDisconnected(from)) {
// TODO(fancycode): support joining callers to currently active conference. // TODO(fancycode): support joining callers to currently active conference.
console.warn("Received Offer while already in a call -> busy.", from); console.warn("Received Offer while already in a call -> busy.", from);
this.api.sendBye(from, "busy"); this.api.sendBye(from, "busy");
@ -360,8 +371,11 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
console.warn("Received Conference for unknown call -> ignore.", to, data); console.warn("Received Conference for unknown call -> ignore.", to, data);
return; return;
} else if (ids.length == 1) { } else if (ids.length == 1) {
// Peer-to-peer call will be upgraded to conference. // Peer-to-peer call will be upgraded to conference. Only is allowed
if (data.indexOf(ids[0]) === -1) { // if currently active call is in the list of conference participants
// and the "Conference" is received from him. Upgrading is always
// allowed for server-managed conference rooms.
if ((from !== ids[0] || data.indexOf(ids[0]) === -1) && !this.isConferenceRoom()) {
console.warn("Received Conference for unknown call -> ignore.", to, data); console.warn("Received Conference for unknown call -> ignore.", to, data);
return; return;
} }
@ -450,6 +464,14 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
call.e.on("closed", _.bind(function() { call.e.on("closed", _.bind(function() {
this.conference.removeCall(id); this.conference.removeCall(id);
}, this)); }, this));
call.e.on("connectionStateChange", _.bind(function(event, state, currentcall) {
switch (state) {
case "disconnected":
case "failed":
this.conference.markDisconnected(currentcall.id);
break;
}
}, this));
return call; return call;
}; };
@ -755,6 +777,8 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
}, this)); }, this));
this.stop(); this.stop();
} else if (calls.length === 1) { } else if (calls.length === 1) {
// Downgraded to peer-to-peer again.
this.conference.id = null;
this.e.triggerHandler("peerconference", [null]); this.e.triggerHandler("peerconference", [null]);
this.e.triggerHandler("peercall", [calls[0]]); this.e.triggerHandler("peercall", [calls[0]]);
} }

Loading…
Cancel
Save