1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-22 08:35:57 +01:00

Rework the up connection state machine.

It is now more similar to the down connection, using the onclose
callback for resource management.
This commit is contained in:
Juliusz Chroboczek 2021-01-14 14:56:15 +01:00
parent 10ebe0e433
commit 8168c2a9e6
3 changed files with 63 additions and 70 deletions

View file

@ -40,11 +40,10 @@ serverConnection.ondownstream = ...;
``` ```
The `onconnected` callback is called when we connect to the server. The The `onconnected` callback is called when we connect to the server. The
`onclose` callback is called when the socket is closed; you should use it `onclose` callback is called when the socket is closed; all streams will
to close all your up streams (down streams will be closed by the server). have been closed by the time it is called. The `onusermessage` callback
The `onusermessage` callback indicates an application-specific message, indicates an application-specific message, either from another user or
either from another user or from the server; the field `kind` indicates from the server; the field `kind` indicates the kind of message.
the kind of message.
Once you have joined a group (see below), the remaining callbacks may Once you have joined a group (see below), the remaining callbacks may
trigger. The `onuser` callback is used to indicate that a user has joined trigger. The `onuser` callback is used to indicate that a user has joined
@ -126,8 +125,8 @@ a change in the status of the stream; states `connected` and `complete`
indicate a functioning stream; other states indicate that the stream is indicate a functioning stream; other states indicate that the stream is
not working right now but might recover in the future. not working right now but might recover in the future.
The `onclose` callback is called when the stream is destroyed by the The `onclose` callback is called when the stream is destroyed, either by
server. the server or in response to a call to the `close` method.
## Pushing outgoing video streams ## Pushing outgoing video streams

View file

@ -309,7 +309,6 @@ function gotConnected() {
* @param {string} reason * @param {string} reason
*/ */
function gotClose(code, reason) { function gotClose(code, reason) {
delUpMediaKind(null);
setConnected(false); setConnected(false);
if(code != 1000) { if(code != 1000) {
console.warn('Socket close', code, reason); console.warn('Socket close', code, reason);
@ -374,7 +373,7 @@ getButtonElement('presentbutton').onclick = async function(e) {
getButtonElement('unpresentbutton').onclick = function(e) { getButtonElement('unpresentbutton').onclick = function(e) {
e.preventDefault(); e.preventDefault();
delUpMediaKind('local'); closeUpMediaKind('local');
resizePeers(); resizePeers();
}; };
@ -482,13 +481,13 @@ document.getElementById('sharebutton').onclick = function(e) {
document.getElementById('unsharebutton').onclick = function(e) { document.getElementById('unsharebutton').onclick = function(e) {
e.preventDefault(); e.preventDefault();
delUpMediaKind('screenshare'); closeUpMediaKind('screenshare');
resizePeers(); resizePeers();
}; };
document.getElementById('stopvideobutton').onclick = function(e) { document.getElementById('stopvideobutton').onclick = function(e) {
e.preventDefault(); e.preventDefault();
delUpMediaKind('video'); closeUpMediaKind('video');
resizePeers(); resizePeers();
}; };
@ -757,10 +756,6 @@ function newUpStream(id) {
c.onerror = function(e) { c.onerror = function(e) {
console.error(e); console.error(e);
displayError(e); displayError(e);
delUpMedia(c);
};
c.onabort = function() {
delUpMedia(c);
}; };
c.onnegotiationcompleted = function() { c.onnegotiationcompleted = function() {
setMaxVideoThroughput(c, getMaxVideoThroughput()); setMaxVideoThroughput(c, getMaxVideoThroughput());
@ -928,23 +923,16 @@ function setFilter(c, f) {
c.userdata.filter.stop(); c.userdata.filter.stop();
c.userdata.filter = null; c.userdata.filter = null;
} }
if(!c.onclose) {
console.warn("onclose not set, this shouldn't happen");
c.onclose = null;
}
return return
} }
if(c.userdata.filter) if(c.userdata.filter)
setFilter(c, null); setFilter(c, null);
if(c.onclose)
throw new Error('onclose already taken');
if(f.inputStream != c.stream) if(f.inputStream != c.stream)
throw new Error('Setting filter for wrong stream'); throw new Error('Setting filter for wrong stream');
c.stream = f.outputStream; c.stream = f.outputStream;
c.userdata.filter = f; c.userdata.filter = f;
c.onclose = () => setFilter(c, null);
} }
/** /**
@ -1028,13 +1016,10 @@ async function addLocalMedia(id) {
if(!audio && !video) { if(!audio && !video) {
if(old) if(old)
delUpMedia(old); old.close();
return; return;
} }
if(old)
stopUpMedia(old);
let constraints = {audio: audio, video: video}; let constraints = {audio: audio, video: video};
/** @type {MediaStream} */ /** @type {MediaStream} */
let stream = null; let stream = null;
@ -1043,7 +1028,7 @@ async function addLocalMedia(id) {
} catch(e) { } catch(e) {
displayError(e); displayError(e);
if(old) if(old)
delUpMedia(old); old.close();
return; return;
} }
@ -1058,8 +1043,22 @@ async function addLocalMedia(id) {
try { try {
let f = new Filter(stream, filter); let f = new Filter(stream, filter);
setFilter(c, f); setFilter(c, f);
c.onclose = () => {
stopStream(stream);
setFilter(c, null);
delMedia(c.id);
}
} catch(e) { } catch(e) {
displayWarning(e); displayWarning(e);
c.onclose = () => {
stopStream(c.stream);
delMedia(c.id);
}
}
} else {
c.onclose = () => {
stopStream(c.stream);
delMedia(c.id);
} }
} }
@ -1110,11 +1109,13 @@ async function addShareMedia() {
let c = newUpStream(); let c = newUpStream();
c.kind = 'screenshare'; c.kind = 'screenshare';
c.stream = stream; c.stream = stream;
c.onclose = () => {
stopStream(stream);
delMedia(c.id);
}
stream.getTracks().forEach(t => { stream.getTracks().forEach(t => {
c.pc.addTrack(t, stream); c.pc.addTrack(t, stream);
t.onended = e => { t.onended = e => c.close();
delUpMedia(c);
};
c.labels[t.id] = 'screenshare'; c.labels[t.id] = 'screenshare';
}); });
c.onstats = gotUpStats; c.onstats = gotUpStats;
@ -1144,12 +1145,14 @@ async function addFileMedia(file) {
c.kind = 'video'; c.kind = 'video';
c.stream = stream; c.stream = stream;
c.onclose = function() { c.onclose = function() {
stopStream(c.stream);
let media = /** @type{HTMLVideoElement} */ let media = /** @type{HTMLVideoElement} */
(document.getElementById('media-' + this.id)); (document.getElementById('media-' + this.id));
if(media && media.src) { if(media && media.src) {
URL.revokeObjectURL(media.src); URL.revokeObjectURL(media.src);
media.src = null; media.src = null;
} }
delMedia(c.id);
} }
stream.onaddtrack = function(e) { stream.onaddtrack = function(e) {
@ -1186,7 +1189,7 @@ async function addFileMedia(file) {
if(Object.keys(c.labels).length === 0) { if(Object.keys(c.labels).length === 0) {
stream.onaddtrack = null; stream.onaddtrack = null;
stream.onremovetrack = null; stream.onremovetrack = null;
delUpMedia(c); c.close();
} }
}; };
await setMedia(c, true, false, video); await setMedia(c, true, false, video);
@ -1195,13 +1198,10 @@ async function addFileMedia(file) {
} }
/** /**
* @param {Stream} c * @param {MediaStream} s
*/ */
function stopUpMedia(c) { function stopStream(s) {
setFilter(c, null); s.getTracks().forEach(t => {
if(!c.stream)
return;
c.stream.getTracks().forEach(t => {
try { try {
t.stop(); t.stop();
} catch(e) { } catch(e) {
@ -1211,31 +1211,18 @@ function stopUpMedia(c) {
} }
/** /**
* @param {Stream} c * closeUpMediaKind closes all up connections that correspond to a given
*/ * kind of media. If kind is null, it closes all up connections.
function delUpMedia(c) { *
stopUpMedia(c);
c.close();
delMedia(c.id);
delete(serverConnection.up[c.id]);
setButtonsVisibility();
}
/**
* delUpMediaKind reoves all up media of the given kind. If kind is
* falseish, it removes all up media.
* @param {string} kind * @param {string} kind
*/ */
function delUpMediaKind(kind) { function closeUpMediaKind(kind) {
for(let id in serverConnection.up) { for(let id in serverConnection.up) {
let c = serverConnection.up[id]; let c = serverConnection.up[id];
if(kind && c.kind != kind) if(kind && c.kind != kind)
continue continue
delUpMedia(c); c.close();
} }
setButtonsVisibility();
hideVideo();
} }
/** /**
@ -1501,6 +1488,7 @@ function delMedia(id) {
media.srcObject = null; media.srcObject = null;
mediadiv.removeChild(peer); mediadiv.removeChild(peer);
setButtonsVisibility();
resizePeers(); resizePeers();
hideVideo(); hideVideo();
} }

View file

@ -238,12 +238,10 @@ ServerConnection.prototype.connect = async function(url) {
sc.permissions = {}; sc.permissions = {};
for(let id in sc.up) { for(let id in sc.up) {
let c = sc.up[id]; let c = sc.up[id];
delete(sc.up[id]);
c.close(); c.close();
} }
for(let id in sc.down) { for(let id in sc.down) {
let c = sc.down[id]; let c = sc.down[id];
delete(sc.down[id]);
c.close(); c.close();
} }
if(sc.group && sc.onjoined) if(sc.group && sc.onjoined)
@ -408,9 +406,9 @@ ServerConnection.prototype.newUpStream = function(id) {
let pc = new RTCPeerConnection(sc.rtcConfiguration); let pc = new RTCPeerConnection(sc.rtcConfiguration);
if(!pc) if(!pc)
throw new Error("Couldn't create peer connection"); throw new Error("Couldn't create peer connection");
if(sc.up[id]) { if(sc.up[id])
sc.up[id].close(); sc.up[id].close();
}
let c = new Stream(this, id, pc, true); let c = new Stream(this, id, pc, true);
sc.up[id] = c; sc.up[id] = c;
@ -530,7 +528,6 @@ ServerConnection.prototype.gotOffer = async function(id, labels, source, usernam
// SDP is rather inflexible as to what can be renegotiated. // SDP is rather inflexible as to what can be renegotiated.
// Unless the server indicates that this is a renegotiation with // Unless the server indicates that this is a renegotiation with
// all parameters unchanged, tear down the existing connection. // all parameters unchanged, tear down the existing connection.
delete(sc.down[id]);
c.close(true); c.close(true);
c = null; c = null;
} }
@ -669,7 +666,6 @@ ServerConnection.prototype.gotClose = function(id) {
let c = this.down[id]; let c = this.down[id];
if(!c) if(!c)
throw new Error('unknown down stream'); throw new Error('unknown down stream');
delete(this.down[id]);
c.close(); c.close();
}; };
@ -888,19 +884,17 @@ function Stream(sc, id, pc, up) {
*/ */
Stream.prototype.close = function(nocallback) { Stream.prototype.close = function(nocallback) {
let c = this; let c = this;
if(!c.sc) {
console.warn('Closing closed stream');
return;
}
if(c.statsHandler) { if(c.statsHandler) {
clearInterval(c.statsHandler); clearInterval(c.statsHandler);
c.statsHandler = null; c.statsHandler = null;
} }
if(c.stream) {
c.stream.getTracks().forEach(t => {
try {
t.stop();
} catch(e) {
}
});
}
c.pc.close(); c.pc.close();
if(c.up && c.localDescriptionSent) { if(c.up && c.localDescriptionSent) {
@ -913,9 +907,21 @@ Stream.prototype.close = function(nocallback) {
} }
} }
if(c.up) {
if(c.sc.up[c.id] === c)
delete(c.sc.up[c.id]);
else
console.warn('Closing unknown stream');
} else {
if(c.sc.down[c.id] === c)
delete(c.sc.down[c.id]);
else
console.warn('Closing unknown stream');
}
c.sc = null;
if(!nocallback && c.onclose) if(!nocallback && c.onclose)
c.onclose.call(c); c.onclose.call(c);
c.sc = null;
}; };
/** /**