diff options
author | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2023-02-16 03:47:13 +0100 |
---|---|---|
committer | Daniel Calviño Sánchez <danxuliu@gmail.com> | 2023-02-20 15:12:05 +0100 |
commit | 32b4fdcbb76c004e00e196f5ff6a4ec20502819a (patch) | |
tree | 9a46afe4863d4ca22c3bbe80860c382abbae0efd /recording | |
parent | 29a442cf86d49b426ecd47776c86ab6f6de5da58 (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.py | 55 | ||||
-rw-r--r-- | recording/src/nextcloud/talk/recording/Service.py | 6 |
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 |