From 9f237d138923f5a2b32e2bfbf5366c7e0e0f9708 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20D=C3=B6ring?= <simon.doering@stud.hs-bochum.de>
Date: Tue, 16 Feb 2021 11:56:42 +0100
Subject: [PATCH] Add feature to change janus room pin

---
 README.md                                     |   8 +-
 .../io-interface/handlers/input-handlers.ts   | 126 +++++++++++-------
 camera-server/src/janus/janus-api.ts          |  18 +++
 camera-server/src/janus/janus-room.ts         |  29 ++++
 4 files changed, 130 insertions(+), 51 deletions(-)

diff --git a/README.md b/README.md
index b26eb1d..905df5b 100644
--- a/README.md
+++ b/README.md
@@ -114,10 +114,16 @@ For the syntax of the commands the following convention is used in this document
 
 * `<a | b>` is a parameter that is required and has to hold either the value `a` or `b`.
 
-* `[param]` is a parameter that is optional
+* `[param]` is a parameter that is optional.
 
 This is the list of the available commands:
 
+### Room Control Commands
+
+| Command                           | Description
+| --------------------------------- | -----------
+| `edit_pin`                        | Changes the pin of the Janus room. This pin is required to join the room as a viewer or sender. Note that this does not automatically kick the current participants of the Janus room. The noVNC pin also needs to be changed accordingly as it is expected to equal the Janus room pin. <br/><br/> **Usage**: `edit_pin <pin>`
+
 ### Slot Control Commands
 
 | Command                           | Description
diff --git a/camera-server/src/io-interface/handlers/input-handlers.ts b/camera-server/src/io-interface/handlers/input-handlers.ts
index 4522f7f..76caf87 100644
--- a/camera-server/src/io-interface/handlers/input-handlers.ts
+++ b/camera-server/src/io-interface/handlers/input-handlers.ts
@@ -9,6 +9,7 @@ import {
     emitControllerBitrateLimit
 } from '../../socket-io/handlers/sender-handlers';
 import { setBitrate } from '../../janus/handlers';
+import { room } from '../../janus/janus-room';
 import { config } from '../../config/config';
 
 const visibilityCommands = ['hide', 'show'];
@@ -16,7 +17,7 @@ const geometryCommands = [
     'set_geometry_relative_to_window',
     'set_geometry_relative_to_canvas'
 ];
-const internalCommands = [
+const internalSlotCommands = [
     'activate_slot',
     'deactivate_slot',
     'refresh_token',
@@ -24,6 +25,7 @@ const internalCommands = [
     'remove_annotation',
     'set_bitrate_limit'
 ];
+const internalRoomCommands = ['edit_pin'];
 
 const setAnnotation = (slot: number, annotation: string) => {
     console.log(`Setting annotation of slot ${slot} to ${annotation}`);
@@ -33,7 +35,7 @@ const setAnnotation = (slot: number, annotation: string) => {
     }
 };
 
-const handleInternalCommand = (
+const handleInternalSlotCommand = (
     command: string,
     slot: number,
     params: string[]
@@ -155,7 +157,28 @@ const handleInternalCommand = (
             break;
         default:
             console.log(
-                'Error: handleInternalCommand got unknown command ' + command
+                'Error: handleInternalSlotCommand got unknown command ' +
+                    command
+            );
+            break;
+    }
+};
+
+const handleInternalRoomCommand = (command: string, params: string[]) => {
+    switch (command) {
+        case 'edit_pin':
+            const newPin = params[0];
+            if (newPin === null) {
+                console.log(
+                    'Tried to edit janus room pin without providing one'
+                );
+                return;
+            }
+            room.editPin(newPin);
+            break;
+        default:
+            console.log(
+                `Error: handleInternalRoomCommand got unknown command ${command}`
             );
             break;
     }
@@ -173,58 +196,61 @@ export const handleCommand = (line: string) => {
         return;
     }
 
-    const slotStr = params.shift();
-    if (slotStr == null) {
-        console.log('Error: Got no slot to apply the command on');
-        return;
-    }
-
-    const slot = parseInt(slotStr);
-    if (isNaN(slot)) {
-        console.log(
-            'Error: Could not parse slot ' + slotStr + ' to an integer'
-        );
-        return;
-    }
-    if (slot < 0 || slot > cameraSlotState.length - 1) {
-        console.log(
-            `Error: Got invalid slot number ${slot}. There are ${cameraSlotState.length} camera slots.`
-        );
-        return;
-    }
-
     console.log('command:', command);
-    console.log('slot:', slot);
     console.log('params:', params);
 
-    const currentCameraState = cameraSlotState[slot];
-
-    if (visibilityCommands.includes(command)) {
-        currentCameraState.visibility = {
-            command,
-            params
-        };
-        emitCommand = true;
-    } else if (geometryCommands.includes(command)) {
-        currentCameraState.geometry = {
-            command,
-            params
-        };
-        emitCommand = true;
-    } else if (internalCommands.includes(command)) {
-        handleInternalCommand(command, slot, params);
+    if (internalRoomCommands.includes(command)) {
+        handleInternalRoomCommand(command, params);
     } else {
-        console.log('Command "' + command + '" is not a valid command');
-        return;
-    }
+        const slotStr = params.shift();
+        if (slotStr == null) {
+            console.log('Error: Got no slot to apply the command on');
+            return;
+        }
+
+        const slot = parseInt(slotStr);
+        if (isNaN(slot)) {
+            console.log(
+                'Error: Could not parse slot ' + slotStr + ' to an integer'
+            );
+            return;
+        }
+        if (slot < 0 || slot > cameraSlotState.length - 1) {
+            console.log(
+                `Error: Got invalid slot number ${slot}. There are ${cameraSlotState.length} camera slots.`
+            );
+            return;
+        }
+
+        const currentCameraState = cameraSlotState[slot];
+
+        if (visibilityCommands.includes(command)) {
+            currentCameraState.visibility = {
+                command,
+                params
+            };
+            emitCommand = true;
+        } else if (geometryCommands.includes(command)) {
+            currentCameraState.geometry = {
+                command,
+                params
+            };
+            emitCommand = true;
+        } else if (internalSlotCommands.includes(command)) {
+            handleInternalSlotCommand(command, slot, params);
+        } else {
+            console.log('Command "' + command + '" is not a valid command');
+            return;
+        }
 
-    console.log('new cameraState:', currentCameraState);
+        console.log('new cameraState:', currentCameraState);
 
-    if (currentCameraState.feedActive && emitCommand) {
-        socketIO.emit('command', {
-            slot,
-            command,
-            params
-        });
+        if (currentCameraState.feedActive && emitCommand) {
+            socketIO.emit('command', {
+                slot,
+                command,
+                params
+            });
+        }
     }
 };
diff --git a/camera-server/src/janus/janus-api.ts b/camera-server/src/janus/janus-api.ts
index 7328277..33e92c5 100644
--- a/camera-server/src/janus/janus-api.ts
+++ b/camera-server/src/janus/janus-api.ts
@@ -113,3 +113,21 @@ export const destroyRoom = (
         }
     });
 };
+
+export const editRoomPin = (
+    sessionId: number,
+    videoroomId: number,
+    room: number,
+    secret: string,
+    newPin: string
+) => {
+    return postRequest(`/${sessionId}/${videoroomId}`, {
+        janus: 'message',
+        body: {
+            request: 'edit',
+            room,
+            secret,
+            new_pin: newPin
+        }
+    });
+};
diff --git a/camera-server/src/janus/janus-room.ts b/camera-server/src/janus/janus-room.ts
index 8836eba..64ee1fb 100644
--- a/camera-server/src/janus/janus-room.ts
+++ b/camera-server/src/janus/janus-room.ts
@@ -149,6 +149,35 @@ class JanusRoom {
         }
     }
 
+    async editPin(newPin: string) {
+        console.log(`Changing janus room pin to ${newPin}`);
+        if (!this._sessionAlive) {
+            console.log("Error: Janus session timed out - can't send request");
+            return;
+        }
+        const { data } = await janusAPI.editRoomPin(
+            this.sessionId,
+            this.videoroomId,
+            config.janusRoom,
+            config.janusRoomSecret,
+            newPin
+        );
+        if (
+            data?.janus === 'success' &&
+            data.plugindata?.data?.videoroom === 'edited'
+        ) {
+            console.log('Changed janus room pin');
+        } else {
+            console.log(
+                `Error: Could not change janus room pin. Janus response: ${JSON.stringify(
+                    data,
+                    null,
+                    2
+                )}`
+            );
+        }
+    }
+
     async cleaup() {
         console.log(`Cleaning up janus room ${config.janusRoom}`);
         if (this._sessionAlive) {
-- 
GitLab