From f002a838065c9cf90d5724fa73eeab2c923344d0 Mon Sep 17 00:00:00 2001
From: Juliusz Chroboczek <jch@irif.fr>
Date: Sat, 5 Dec 2020 20:27:32 +0100
Subject: [PATCH] Keep track of stream direction.

This simplifies the interface since close does the right thing
without help from the application.  Also improves error checking.
---
 static/protocol.js | 35 ++++++++++++++++++++++++-----------
 static/sfu.js      |  4 ++--
 2 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/static/protocol.js b/static/protocol.js
index 7689334..32ef5d5 100644
--- a/static/protocol.js
+++ b/static/protocol.js
@@ -253,7 +253,7 @@ ServerConnection.prototype.connect = async function(url) {
             for(let id in sc.down) {
                 let c = sc.down[id];
                 delete(sc.down[id]);
-                c.close(false);
+                c.close();
                 if(c.onclose)
                     c.onclose.call(c);
             }
@@ -423,9 +423,9 @@ ServerConnection.prototype.newUpStream = function(id) {
     if(!pc)
         throw new Error("Couldn't create peer connection");
     if(sc.up[id]) {
-        sc.up[id].close(false);
+        sc.up[id].close();
     }
-    let c = new Stream(this, id, pc);
+    let c = new Stream(this, id, pc, true);
     sc.up[id] = c;
 
     pc.onnegotiationneeded = async e => {
@@ -545,15 +545,18 @@ ServerConnection.prototype.gotOffer = async function(id, labels, offer, renegoti
         // Unless the server indicates that this is a renegotiation with
         // all parameters unchanged, tear down the existing connection.
         delete(sc.down[id]);
-        c.close(false);
+        c.close();
         c = null;
     }
 
+    if(sc.up[id])
+        throw new Error('Duplicate connection id');
+
     if(!c) {
         let pc = new RTCPeerConnection({
             iceServers: this.iceServers,
         });
-        c = new Stream(this, id, pc);
+        c = new Stream(this, id, pc, false);
         sc.down[id] = c;
 
         c.pc.onicecandidate = function(e) {
@@ -681,7 +684,7 @@ ServerConnection.prototype.gotClose = function(id) {
     if(!c)
         throw new Error('unknown down stream');
     delete(this.down[id]);
-    c.close(false);
+    c.close();
     if(c.onclose)
         c.onclose.call(c);
 };
@@ -730,7 +733,7 @@ ServerConnection.prototype.gotRemoteIce = async function(id, candidate) {
  *
  * @constructor
  */
-function Stream(sc, id, pc) {
+function Stream(sc, id, pc, up) {
     /**
      * The associated ServerConnection.
      *
@@ -745,6 +748,13 @@ function Stream(sc, id, pc) {
      * @const
      */
     this.id = id;
+    /**
+     * Indicates whether the stream is in the client->server direction.
+     *
+     * @type {boolean}
+     * @const
+     */
+     this.up = up
     /**
      * For up streams, one of "local" or "screenshare".
      *
@@ -884,10 +894,9 @@ function Stream(sc, id, pc) {
 }
 
 /**
- * close closes an up stream.  It should not be called for down streams.
- * @param {boolean} sendclose - whether to send a close message to the server
+ * close closes a stream.
  */
-Stream.prototype.close = function(sendclose) {
+Stream.prototype.close = function() {
     let c = this;
     if(c.statsHandler) {
         clearInterval(c.statsHandler);
@@ -904,7 +913,7 @@ Stream.prototype.close = function(sendclose) {
     }
     c.pc.close();
 
-    if(sendclose) {
+    if(c.up && c.localDescriptionSent) {
         try {
             c.sc.send({
                 type: 'close',
@@ -983,6 +992,8 @@ Stream.prototype.flushRemoteIceCandidates = async function () {
  */
 Stream.prototype.negotiate = async function (restartIce) {
     let c = this;
+    if(!c.up)
+        throw new Error('not an up stream');
 
     let options = {};
     if(restartIce)
@@ -1022,6 +1033,8 @@ Stream.prototype.negotiate = async function (restartIce) {
 
 Stream.prototype.restartIce = function () {
     let c = this;
+    if(!c.up)
+        throw new Error('not an up stream');
 
     if('restartIce' in c.pc) {
         try {
diff --git a/static/sfu.js b/static/sfu.js
index b147154..d9beae2 100644
--- a/static/sfu.js
+++ b/static/sfu.js
@@ -963,7 +963,7 @@ function delUpMedia(c) {
     } catch(e) {
         console.warn(e);
     }
-    c.close(true);
+    c.close();
     delete(serverConnection.up[c.id]);
     setButtonsVisibility()
 }
@@ -978,7 +978,7 @@ function delUpMediaKind(kind) {
         let c = serverConnection.up[id];
         if(kind && c.kind != kind)
             continue
-        c.close(true);
+        c.close();
         delMedia(id);
         delete(serverConnection.up[id]);
     }
