summaryrefslogtreecommitdiffstats
path: root/recording
diff options
context:
space:
mode:
authorDaniel Calviño Sánchez <danxuliu@gmail.com>2023-02-16 03:47:13 +0100
committerDaniel Calviño Sánchez <danxuliu@gmail.com>2023-02-20 15:12:05 +0100
commit32b4fdcbb76c004e00e196f5ff6a4ec20502819a (patch)
tree9a46afe4863d4ca22c3bbe80860c382abbae0efd /recording
parent29a442cf86d49b426ecd47776c86ab6f6de5da58 (diff)
Use internal client of signaling server for recording
The recording participant now uses an internal client rather than a guest participant. Internal clients are specific to the signaling server and do not have a counterpart Nextcloud user/session. Authentication is done with a random string and a token, which is the random string hashed with the internal secret of the signaling server. Due to its special nature an internal client is able to join any call, so using an internal client makes possible to record calls other than public ones. Besides that, this also fixes stopping a recording when the last participant leaves, as the recording participant is no longer a regular participant known to Nextcloud and therefore does not prevent the call from ending when the rest left. Finally, the recording participant is no longer shown in the call either for the rest of participants, as internal clients are not shown in the UI (or, at least, they should not be; this may need to be adjusted in the mobile apps). Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Diffstat (limited to 'recording')
-rw-r--r--recording/src/nextcloud/talk/recording/Participant.py55
-rw-r--r--recording/src/nextcloud/talk/recording/Service.py6
2 files changed, 50 insertions, 11 deletions
diff --git a/recording/src/nextcloud/talk/recording/Participant.py b/recording/src/nextcloud/talk/recording/Participant.py
index 9a0b3842e..c6d697fb9 100644
--- a/recording/src/nextcloud/talk/recording/Participant.py
+++ b/recording/src/nextcloud/talk/recording/Participant.py
@@ -21,12 +21,15 @@
Module to join a call with a browser.
"""
+import hashlib
+import hmac
import json
import logging
import threading
import websocket
from datetime import datetime
+from secrets import token_urlsafe
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service as FirefoxService
@@ -34,6 +37,8 @@ from selenium.webdriver.support.wait import WebDriverWait
from shutil import disk_usage
from time import sleep
+from .Config import config
+
class BiDiLogsHelper:
"""
Helper class to get browser logs using the BiDi protocol.
@@ -414,22 +419,56 @@ class Participant():
def joinCall(self, token):
"""
- Joins (or starts) the call in the room with the given token.
+ Joins the call in the room with the given token.
- The participant will join as a guest.
+ The participant will join as an internal client of the signaling server.
:param token: the token of the room to join.
"""
self.seleniumHelper.driver.get(self.nextcloudUrl + '/index.php/call/' + token + '/recording')
- def leaveCall(self):
- """
- Leaves the current call.
+ secret = config.getBackendSecret(self.nextcloudUrl)
+ if secret == None:
+ raise Exception(f"No configured backend secret for {self.nextcloudUrl}")
+
+ random = token_urlsafe(64)
+ hmacValue = hmac.new(secret.encode(), random.encode(), hashlib.sha256)
+
+ # If there are several signaling servers configured in Nextcloud the
+ # signaling settings can change between different calls, so they need to
+ # be got just once. The scripts are executed in their own scope, so
+ # values have to be stored in the window object to be able to use them
+ # later in another script.
+ settings = self.seleniumHelper.executeAsync(f'''
+ window.signalingSettings = await OCA.Talk.signalingGetSettingsForRecording('{token}', '{random}', '{hmacValue.hexdigest()}')
+ returnValue = window.signalingSettings
+ ''')
- The call must have been joined first.
+ secret = config.getSignalingSecret(settings['server'])
+ if secret == None:
+ raise Exception(f"No configured signaling secret for {settings['server']}")
+
+ random = token_urlsafe(64)
+ hmacValue = hmac.new(secret.encode(), random.encode(), hashlib.sha256)
+
+ self.seleniumHelper.execute(f'''
+ OCA.Talk.signalingJoinCallForRecording(
+ '{token}',
+ window.signalingSettings,
+ {{
+ random: '{random}',
+ token: '{hmacValue.hexdigest()}',
+ backend: '{self.nextcloudUrl}',
+ }}
+ )
+ ''')
+
+ def disconnect(self):
+ """
+ Disconnects from the signaling server.
"""
- self.seleniumHelper.executeAsync('''
- await OCA.Talk.SimpleWebRTC.connection.leaveCurrentCall()
+ self.seleniumHelper.execute('''
+ OCA.Talk.signalingKill()
''')
diff --git a/recording/src/nextcloud/talk/recording/Service.py b/recording/src/nextcloud/talk/recording/Service.py
index 258ff1cb9..0bb1519f5 100644
--- a/recording/src/nextcloud/talk/recording/Service.py
+++ b/recording/src/nextcloud/talk/recording/Service.py
@@ -284,11 +284,11 @@ class Service:
self._process = None
if self._participant:
- self._logger.debug("Leaving call")
+ self._logger.debug("Disconnecting from signaling server")
try:
- self._participant.leaveCall()
+ self._participant.disconnect()
except:
- self._logger.exception("Error when leaving call")
+ self._logger.exception("Error when disconnecting from signaling server")
finally:
self._participant = None