Commit 9bb2499b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Rework flushing of ICE candidates.

We now treat local and remote candidates differently, and flush
local candidates immediately after sending an offer.
parent 96e5030d
...@@ -600,7 +600,7 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti ...@@ -600,7 +600,7 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti
sc.ondownstream.call(sc, c); sc.ondownstream.call(sc, c);
await c.pc.setRemoteDescription(offer); await c.pc.setRemoteDescription(offer);
await c.flushIceCandidates(); await c.flushRemoteIceCandidates()
let answer = await c.pc.createAnswer(); let answer = await c.pc.createAnswer();
if(!answer) if(!answer)
throw new Error("Didn't create answer"); throw new Error("Didn't create answer");
...@@ -610,6 +610,8 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti ...@@ -610,6 +610,8 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti
id: id, id: id,
answer: answer, answer: answer,
}); });
c.localDescriptionSent = true;
c.flushLocalIceCandidates();
if(c.onnegotiationcompleted) if(c.onnegotiationcompleted)
c.onnegotiationcompleted.call(c); c.onnegotiationcompleted.call(c);
}; };
...@@ -648,7 +650,7 @@ ServerConnection.prototype.gotAnswer = async function(id, answer) { ...@@ -648,7 +650,7 @@ ServerConnection.prototype.gotAnswer = async function(id, answer) {
c.onerror.call(c, e); c.onerror.call(c, e);
return; return;
} }
await c.flushIceCandidates(); await c.flushRemoteIceCandidates();
if(c.onnegotiationcompleted) if(c.onnegotiationcompleted)
c.onnegotiationcompleted.call(c); c.onnegotiationcompleted.call(c);
}; };
...@@ -779,27 +781,26 @@ function Stream(sc, id, pc) { ...@@ -779,27 +781,26 @@ function Stream(sc, id, pc) {
* @type {Object<string,string>} * @type {Object<string,string>}
*/ */
this.labelsByMid = {}; this.labelsByMid = {};
/**
* Indicates whether we have already sent a local description.
*
* @type {boolean}
*/
this.localDescriptionSent = false;
/** /**
* Buffered local ICE candidates. This will be flushed by * Buffered local ICE candidates. This will be flushed by
* flushIceCandidates when the PC becomes stable. * flushLocalIceCandidates after we send a local description.
* *
* @type {RTCIceCandidate[]} * @type {RTCIceCandidate[]}
*/ */
this.localIceCandidates = []; this.localIceCandidates = [];
/** /**
* Buffered remote ICE candidates. This will be flushed by * Buffered remote ICE candidates. This will be flushed by
* flushIceCandidates when the PC becomes stable. * flushRemoteIceCandidates when we get a remote SDP description.
* *
* @type {RTCIceCandidate[]} * @type {RTCIceCandidate[]}
*/ */
this.remoteIceCandidates = []; this.remoteIceCandidates = [];
/**
* Indicates whether it is legal to renegotiate at this point. If
* this is false, a new connection must be negotiated.
*
* @type {boolean}
*/
this.renegotiate = false;
/** /**
* The statistics last computed by the stats handler. This is * The statistics last computed by the stats handler. This is
* a dictionary indexed by track id, with each value a dictionary of * a dictionary indexed by track id, with each value a dictionary of
...@@ -921,7 +922,7 @@ Stream.prototype.close = function(sendclose) { ...@@ -921,7 +922,7 @@ Stream.prototype.close = function(sendclose) {
*/ */
Stream.prototype.gotLocalIce = function(candidate) { Stream.prototype.gotLocalIce = function(candidate) {
let c = this; let c = this;
if(c.pc.remoteDescription) if(c.localDescriptionSent)
c.sc.send({type: 'ice', c.sc.send({type: 'ice',
id: c.id, id: c.id,
candidate: candidate, candidate: candidate,
...@@ -931,13 +932,15 @@ Stream.prototype.gotLocalIce = function(candidate) { ...@@ -931,13 +932,15 @@ Stream.prototype.gotLocalIce = function(candidate) {
} }
/** /**
* flushIceCandidates flushes any buffered ICE candidates. It is called * flushLocalIceCandidates flushes any buffered local ICE candidates.
* automatically when the connection reaches a stable state. * It is called when we send an offer.
* @function * @function
*/ */
Stream.prototype.flushIceCandidates = async function () { Stream.prototype.flushLocalIceCandidates = function () {
let c = this; let c = this;
c.localIceCandidates.forEach(candidate => { let candidates = c.localIceCandidates;
c.localIceCandidates = [];
candidates.forEach(candidate => {
try { try {
c.sc.send({type: 'ice', c.sc.send({type: 'ice',
id: c.id, id: c.id,
...@@ -947,13 +950,23 @@ Stream.prototype.flushIceCandidates = async function () { ...@@ -947,13 +950,23 @@ Stream.prototype.flushIceCandidates = async function () {
console.warn(e); console.warn(e);
} }
}); });
c.localIceCandidates = [];
}
/**
* flushRemoteIceCandidates flushes any buffered remote ICE candidates. It is
* called automatically when we get a remote description.
* @function
*/
Stream.prototype.flushRemoteIceCandidates = async function () {
let c = this;
let candidates = c.remoteIceCandidates;
c.remoteIceCandidates = [];
/** @type {Array.<Promise<void>>} */ /** @type {Array.<Promise<void>>} */
let promises = []; let promises = [];
c.remoteIceCandidates.forEach(candidate => { candidates.forEach(candidate => {
promises.push(this.pc.addIceCandidate(candidate).catch(console.warn)); promises.push(c.pc.addIceCandidate(candidate).catch(console.warn));
}); });
c.remoteIceCandidates = [];
return await Promise.all(promises); return await Promise.all(promises);
}; };
...@@ -990,12 +1003,13 @@ Stream.prototype.negotiate = async function (restartIce) { ...@@ -990,12 +1003,13 @@ Stream.prototype.negotiate = async function (restartIce) {
c.sc.send({ c.sc.send({
type: 'offer', type: 'offer',
kind: this.renegotiate ? 'renegotiate' : '', kind: this.localDescriptionSent ? 'renegotiate' : '',
id: c.id, id: c.id,
labels: c.labelsByMid, labels: c.labelsByMid,
offer: offer, offer: offer,
}); });
this.renegotiate = true; this.localDescriptionSent = true;
c.flushLocalIceCandidates();
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment