mirror of
https://github.com/jech/galene.git
synced 2024-11-26 02:25:58 +01:00
Replace changed connections.
We used to destroy and recreate connections, we now replace them atomically.
This commit is contained in:
parent
448bb0374d
commit
e175ef0e49
2 changed files with 92 additions and 44 deletions
|
@ -139,14 +139,10 @@ document.getElementById('unpresentbutton').onclick = function(e) {
|
||||||
};
|
};
|
||||||
|
|
||||||
function changePresentation() {
|
function changePresentation() {
|
||||||
let found = false;
|
let id = findUpMedia('local');
|
||||||
for(let id in up) {
|
if(id) {
|
||||||
if(up[id].kind === 'local')
|
addLocalMedia(id);
|
||||||
found = true;
|
|
||||||
}
|
}
|
||||||
delUpMediaKind('local');
|
|
||||||
if(found)
|
|
||||||
addLocalMedia();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisibility(id, visible) {
|
function setVisibility(id, visible) {
|
||||||
|
@ -158,8 +154,8 @@ function setVisibility(id, visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setButtonsVisibility() {
|
function setButtonsVisibility() {
|
||||||
let local = findUpMedia('local');
|
let local = !!findUpMedia('local');
|
||||||
let share = findUpMedia('screenshare')
|
let share = !!findUpMedia('screenshare')
|
||||||
// don't allow multiple presentations
|
// don't allow multiple presentations
|
||||||
setVisibility('presentbutton', permissions.present && !local);
|
setVisibility('presentbutton', permissions.present && !local);
|
||||||
setVisibility('unpresentbutton', local);
|
setVisibility('unpresentbutton', local);
|
||||||
|
@ -344,15 +340,21 @@ async function setMediaChoices() {
|
||||||
mediaChoicesDone = true;
|
mediaChoicesDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addLocalMedia() {
|
async function addLocalMedia(id) {
|
||||||
if(!getUserPass())
|
if(!getUserPass())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let audio = mapMediaOption(document.getElementById('audioselect').value);
|
let audio = mapMediaOption(document.getElementById('audioselect').value);
|
||||||
let video = mapMediaOption(document.getElementById('videoselect').value);
|
let video = mapMediaOption(document.getElementById('videoselect').value);
|
||||||
|
|
||||||
if(!audio && !video)
|
if(!audio && !video) {
|
||||||
|
if(id)
|
||||||
|
delUpMedia(id);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(id)
|
||||||
|
stopUpMedia(id);
|
||||||
|
|
||||||
let constraints = {audio: audio, video: video};
|
let constraints = {audio: audio, video: video};
|
||||||
let stream = null;
|
let stream = null;
|
||||||
|
@ -360,13 +362,16 @@ async function addLocalMedia() {
|
||||||
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
if(id)
|
||||||
|
delUpMedia(id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMediaChoices();
|
setMediaChoices();
|
||||||
|
|
||||||
let id = await newUpStream();
|
id = await newUpStream(id);
|
||||||
let c = up[id];
|
let c = up[id];
|
||||||
|
|
||||||
c.kind = 'local';
|
c.kind = 'local';
|
||||||
c.stream = stream;
|
c.stream = stream;
|
||||||
stream.getTracks().forEach(t => {
|
stream.getTracks().forEach(t => {
|
||||||
|
@ -418,16 +423,32 @@ async function addShareMedia(setup) {
|
||||||
setButtonsVisibility()
|
setButtonsVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stopUpMedia(id) {
|
||||||
|
let c = up[id];
|
||||||
|
if(!c) {
|
||||||
|
console.error('Stopping unknown up media');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!c.stream)
|
||||||
|
return;
|
||||||
|
c.stream.getTracks().forEach(t => {
|
||||||
|
try {
|
||||||
|
t.stop();
|
||||||
|
} catch(e) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function delUpMedia(id) {
|
function delUpMedia(id) {
|
||||||
let c = up[id];
|
let c = up[id];
|
||||||
if(!c) {
|
if(!c) {
|
||||||
console.error("Deleting unknown up media");
|
console.error('Deleting unknown up media');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c.close(true);
|
stopUpMedia(id);
|
||||||
delMedia(id);
|
delMedia(id);
|
||||||
|
c.close(true);
|
||||||
delete(up[id]);
|
delete(up[id]);
|
||||||
|
|
||||||
setButtonsVisibility()
|
setButtonsVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,9 +468,9 @@ function delUpMediaKind(kind) {
|
||||||
function findUpMedia(kind) {
|
function findUpMedia(kind) {
|
||||||
for(let id in up) {
|
for(let id in up) {
|
||||||
if(up[id].kind === kind)
|
if(up[id].kind === kind)
|
||||||
return true;
|
return id;
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function muteLocalTracks(mute) {
|
function muteLocalTracks(mute) {
|
||||||
|
@ -680,6 +701,14 @@ function sendRequest(value) {
|
||||||
|
|
||||||
async function gotOffer(id, labels, offer) {
|
async function gotOffer(id, labels, offer) {
|
||||||
let c = down[id];
|
let c = down[id];
|
||||||
|
if(c) {
|
||||||
|
// a new offer with a known id does not indicate renegotiation,
|
||||||
|
// but a new connection that replaces the old one.
|
||||||
|
delete(down[id])
|
||||||
|
c.close(false);
|
||||||
|
c = null;
|
||||||
|
}
|
||||||
|
|
||||||
if(!c) {
|
if(!c) {
|
||||||
let pc = new RTCPeerConnection({
|
let pc = new RTCPeerConnection({
|
||||||
iceServers: iceServers,
|
iceServers: iceServers,
|
||||||
|
@ -1113,15 +1142,20 @@ function chatResizer(e) {
|
||||||
|
|
||||||
document.getElementById('resizer').addEventListener('mousedown', chatResizer, false);
|
document.getElementById('resizer').addEventListener('mousedown', chatResizer, false);
|
||||||
|
|
||||||
async function newUpStream() {
|
async function newUpStream(id) {
|
||||||
let id = randomid();
|
if(!id) {
|
||||||
if(up[id])
|
id = randomid();
|
||||||
throw new Error('Eek!');
|
if(up[id])
|
||||||
|
throw new Error('Eek!');
|
||||||
|
}
|
||||||
let pc = new RTCPeerConnection({
|
let pc = new RTCPeerConnection({
|
||||||
iceServers: iceServers,
|
iceServers: iceServers,
|
||||||
});
|
});
|
||||||
if(!pc)
|
if(!pc)
|
||||||
throw new Error("Couldn't create peer connection");
|
throw new Error("Couldn't create peer connection");
|
||||||
|
if(up[id]) {
|
||||||
|
up[id].close(false);
|
||||||
|
}
|
||||||
up[id] = new Connection(id, pc);
|
up[id] = new Connection(id, pc);
|
||||||
|
|
||||||
pc.onnegotiationneeded = async e => {
|
pc.onnegotiationneeded = async e => {
|
||||||
|
|
60
webclient.go
60
webclient.go
|
@ -221,10 +221,17 @@ func addUpConn(c *webClient, id string) (*rtpUpConnection, error) {
|
||||||
if c.up == nil {
|
if c.up == nil {
|
||||||
c.up = make(map[string]*rtpUpConnection)
|
c.up = make(map[string]*rtpUpConnection)
|
||||||
}
|
}
|
||||||
if c.up[id] != nil || (c.down != nil && c.down[id] != nil) {
|
if c.down != nil && c.down[id] != nil {
|
||||||
conn.pc.Close()
|
conn.pc.Close()
|
||||||
return nil, errors.New("Adding duplicate connection")
|
return nil, errors.New("Adding duplicate connection")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old := c.up[id]
|
||||||
|
if old != nil {
|
||||||
|
decrementVideoTracks(c, old)
|
||||||
|
old.pc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
c.up[id] = conn
|
c.up[id] = conn
|
||||||
|
|
||||||
conn.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
conn.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||||
|
@ -248,7 +255,21 @@ func delUpConn(c *webClient, id string) bool {
|
||||||
delete(c.up, id)
|
delete(c.up, id)
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
decrementVideoTracks(c, conn)
|
||||||
|
|
||||||
|
go func(clients []client) {
|
||||||
|
for _, c := range clients {
|
||||||
|
c.pushConn(conn.id, nil, nil, "")
|
||||||
|
}
|
||||||
|
}(c.Group().getClients(c))
|
||||||
|
|
||||||
|
conn.pc.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func decrementVideoTracks(c *webClient, conn *rtpUpConnection) {
|
||||||
conn.mu.Lock()
|
conn.mu.Lock()
|
||||||
|
defer conn.mu.Unlock()
|
||||||
for _, track := range conn.tracks {
|
for _, track := range conn.tracks {
|
||||||
if track.track.Kind() == webrtc.RTPCodecTypeVideo {
|
if track.track.Kind() == webrtc.RTPCodecTypeVideo {
|
||||||
count := atomic.AddUint32(&c.group.videoCount,
|
count := atomic.AddUint32(&c.group.videoCount,
|
||||||
|
@ -259,17 +280,6 @@ func delUpConn(c *webClient, id string) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn.mu.Unlock()
|
|
||||||
|
|
||||||
go func(clients []client) {
|
|
||||||
for _, c := range clients {
|
|
||||||
c.pushConn(conn.id, nil, nil, "")
|
|
||||||
}
|
|
||||||
}(c.Group().getClients(c))
|
|
||||||
|
|
||||||
conn.pc.Close()
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDownConn(c *webClient, id string) *rtpDownConnection {
|
func getDownConn(c *webClient, id string) *rtpDownConnection {
|
||||||
|
@ -307,13 +317,18 @@ func addDownConn(c *webClient, id string, remote upConnection) (*rtpDownConnecti
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
if c.up != nil && c.up[id] != nil {
|
||||||
|
conn.pc.Close()
|
||||||
|
return nil, errors.New("Adding duplicate connection")
|
||||||
|
}
|
||||||
|
|
||||||
if c.down == nil {
|
if c.down == nil {
|
||||||
c.down = make(map[string]*rtpDownConnection)
|
c.down = make(map[string]*rtpDownConnection)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.down[id] != nil || (c.up != nil && c.up[id] != nil) {
|
old := c.down[id]
|
||||||
conn.pc.Close()
|
if old != nil {
|
||||||
return nil, errors.New("Adding duplicate connection")
|
old.pc.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
conn.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
|
||||||
|
@ -441,13 +456,9 @@ func sendICE(c *webClient, id string, candidate *webrtc.ICECandidate) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func gotOffer(c *webClient, id string, offer webrtc.SessionDescription, labels map[string]string) error {
|
func gotOffer(c *webClient, id string, offer webrtc.SessionDescription, labels map[string]string) error {
|
||||||
var err error
|
up, err := addUpConn(c, id)
|
||||||
up, ok := c.up[id]
|
if err != nil {
|
||||||
if !ok {
|
return err
|
||||||
up, err = addUpConn(c, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if c.username != "" {
|
if c.username != "" {
|
||||||
up.label = c.username
|
up.label = c.username
|
||||||
|
@ -718,13 +729,16 @@ func clientLoop(c *webClient, conn *websocket.Conn) error {
|
||||||
case a := <-c.actionCh:
|
case a := <-c.actionCh:
|
||||||
switch a := a.(type) {
|
switch a := a.(type) {
|
||||||
case pushConnAction:
|
case pushConnAction:
|
||||||
found := delDownConn(c, a.id)
|
|
||||||
if a.conn == nil {
|
if a.conn == nil {
|
||||||
|
found := delDownConn(c, a.id)
|
||||||
if found {
|
if found {
|
||||||
c.write(clientMessage{
|
c.write(clientMessage{
|
||||||
Type: "close",
|
Type: "close",
|
||||||
Id: a.id,
|
Id: a.id,
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
log.Printf("Deleting unknown " +
|
||||||
|
"down connection")
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue