From a3406d3dfed952df70b1090b85e8d38a1cbee112 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 12 Jun 2020 13:21:56 +0200 Subject: [PATCH] openvidu-server: protect concurrent recording start methods --- .../java/io/openvidu/server/core/Session.java | 2 +- .../recording/service/RecordingManager.java | 79 ++++++++++++------- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java index 099574ae..9bad28b6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Session.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Session.java @@ -80,7 +80,7 @@ public class Session implements SessionInterface { /** * This lock protects initialization of ALWAYS recordings upon first user - * publishing + * publishing, as well as POST /api/recordings/start */ public Lock recordingLock = new ReentrantLock(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java index 2f993944..4333f423 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManager.java @@ -230,38 +230,59 @@ public class RecordingManager { } public Recording startRecording(Session session, RecordingProperties properties) throws OpenViduException { - Recording recording = null; try { - switch (properties.outputMode()) { - case COMPOSED: - recording = this.composedRecordingService.startRecording(session, properties); - break; - case INDIVIDUAL: - recording = this.singleStreamRecordingService.startRecording(session, properties); - break; + if (session.recordingLock.tryLock(15, TimeUnit.SECONDS)) { + try { + if (sessionIsBeingRecorded(session.getSessionId())) { + throw new OpenViduException(Code.RECORDING_START_ERROR_CODE, + "Concurrent start of recording for session " + session.getSessionId()); + } else { + Recording recording = null; + try { + switch (properties.outputMode()) { + case COMPOSED: + recording = this.composedRecordingService.startRecording(session, properties); + break; + case INDIVIDUAL: + recording = this.singleStreamRecordingService.startRecording(session, properties); + break; + } + } catch (Exception e) { + throw e; + } + this.recordingFromStartingToStarted(recording); + + this.cdr.recordRecordingStarted(recording); + this.cdr.recordRecordingStatusChanged(recording, null, recording.getCreatedAt(), + io.openvidu.java.client.Recording.Status.started); + + if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) { + // Directly send recording started notification for all cases except for + // COMPOSED recordings with video (will be sent on first RECORDER subscriber) + this.sessionHandler.sendRecordingStartedNotification(session, recording); + } + if (session.getActivePublishers() == 0) { + // Init automatic recording stop if there are now publishers when starting + // recording + log.info("No publisher in session {}. Starting {} seconds countdown for stopping recording", + session.getSessionId(), this.openviduConfig.getOpenviduRecordingAutostopTimeout()); + this.initAutomaticRecordingStopThread(session); + } + return recording; + } + } finally { + session.recordingLock.unlock(); + } + } else { + throw new OpenViduException(Code.RECORDING_START_ERROR_CODE, + "Timeout waiting for recording Session lock to be available for session " + + session.getSessionId()); } - } catch (Exception e) { - throw e; + } catch (InterruptedException e) { + throw new OpenViduException(Code.RECORDING_START_ERROR_CODE, + "InterruptedException waiting for recording Session lock to be available for session " + + session.getSessionId()); } - this.recordingFromStartingToStarted(recording); - - this.cdr.recordRecordingStarted(recording); - this.cdr.recordRecordingStatusChanged(recording, null, recording.getCreatedAt(), - io.openvidu.java.client.Recording.Status.started); - - if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) { - // Directly send recording started notification for all cases except for - // COMPOSED recordings with video (will be sent on first RECORDER subscriber) - this.sessionHandler.sendRecordingStartedNotification(session, recording); - } - if (session.getActivePublishers() == 0) { - // Init automatic recording stop if there are now publishers when starting - // recording - log.info("No publisher in session {}. Starting {} seconds countdown for stopping recording", - session.getSessionId(), this.openviduConfig.getOpenviduRecordingAutostopTimeout()); - this.initAutomaticRecordingStopThread(session); - } - return recording; } public Recording stopRecording(Session session, String recordingId, EndReason reason) {