From 5da1a8292354543076d297259bd705e740c21bb4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 10:55:02 +0200 Subject: [PATCH 001/435] Recording scripts new flag --disabled-dev-shm-size for google-chrome process --- openvidu-server/docker/openvidu-recording/scripts/composed.sh | 2 +- .../docker/openvidu-recording/scripts/composed_quick_start.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/docker/openvidu-recording/scripts/composed.sh b/openvidu-server/docker/openvidu-recording/scripts/composed.sh index fe70c076..78e6b41a 100644 --- a/openvidu-server/docker/openvidu-recording/scripts/composed.sh +++ b/openvidu-server/docker/openvidu-recording/scripts/composed.sh @@ -47,7 +47,7 @@ fi touch xvfb.log chmod 777 xvfb.log - xvfb-run --auto-servernum --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome --kiosk --start-maximized --test-type --no-sandbox --disable-infobars --disable-gpu --disable-popup-blocking --window-size=$WIDTH,$HEIGHT --window-position=0,0 --no-first-run --ignore-certificate-errors --autoplay-policy=no-user-gesture-required $DEBUG_CHROME_FLAGS $URL &> xvfb.log & + xvfb-run --auto-servernum --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome --kiosk --start-maximized --test-type --no-sandbox --disable-infobars --disable-gpu --disable-popup-blocking --window-size=$WIDTH,$HEIGHT --window-position=0,0 --no-first-run --ignore-certificate-errors --disable-dev-shm-usage --autoplay-policy=no-user-gesture-required $DEBUG_CHROME_FLAGS $URL &> xvfb.log & touch stop chmod 777 /recordings diff --git a/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh b/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh index 68fd2aab..9ded1ae6 100644 --- a/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh +++ b/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh @@ -30,7 +30,7 @@ if [[ -z "${COMPOSED_QUICK_START_ACTION}" ]]; then touch xvfb.log chmod 777 xvfb.log - xvfb-run --auto-servernum --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome --kiosk --start-maximized --test-type --no-sandbox --disable-infobars --disable-gpu --disable-popup-blocking --window-size=$WIDTH,$HEIGHT --window-position=0,0 --no-first-run --ignore-certificate-errors --autoplay-policy=no-user-gesture-required --enable-logging --v=1 $DEBUG_CHROME_FLAGS $URL &> xvfb.log & + xvfb-run --auto-servernum --server-args="-ac -screen 0 ${RESOLUTION}x24 -noreset" google-chrome --kiosk --start-maximized --test-type --no-sandbox --disable-infobars --disable-gpu --disable-popup-blocking --window-size=$WIDTH,$HEIGHT --window-position=0,0 --no-first-run --ignore-certificate-errors --disable-dev-shm-usage --autoplay-policy=no-user-gesture-required --enable-logging --v=1 $DEBUG_CHROME_FLAGS $URL &> xvfb.log & chmod 777 /recordings until pids=$(pidof Xvfb) From ec03629c880b79031373a85baaa2bde9ca58b21e Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 12:00:02 +0200 Subject: [PATCH 002/435] openvidu-server: mandatory alphanumeric recording names --- .../server/rest/SessionRestController.java | 18 +++++++++++++----- .../openvidu/server/utils/FormatChecker.java | 11 +++++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 28da7b54..91472a44 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -144,7 +144,7 @@ public class SessionRestController { if (customSessionId != null && !customSessionId.isEmpty()) { if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) { return this.generateErrorResponse( - "Parameter \"customSessionId\" is wrong. Must be an alphanumeric string", + "Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", "/api/sessions", HttpStatus.BAD_REQUEST); } builder = builder.customSessionId(customSessionId); @@ -485,28 +485,36 @@ public class SessionRestController { HttpStatus.BAD_REQUEST); } + if (name != null && !name.isEmpty()) { + if (!sessionManager.formatChecker.isValidRecordingName(name)) { + return this.generateErrorResponse( + "Parameter 'name' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", "/api/sessions", + HttpStatus.BAD_REQUEST); + } + } + OutputMode finalOutputMode = OutputMode.COMPOSED; RecordingLayout recordingLayout = null; if (outputModeString != null && !outputModeString.isEmpty()) { try { finalOutputMode = OutputMode.valueOf(outputModeString); } catch (Exception e) { - return this.generateErrorResponse("Type error in some parameter", "/api/recordings/start", + return this.generateErrorResponse("Type error in parameter 'outputMode'", "/api/recordings/start", HttpStatus.BAD_REQUEST); } } if (RecordingUtils.IS_COMPOSED(finalOutputMode)) { if (resolution != null && !sessionManager.formatChecker.isAcceptableRecordingResolution(resolution)) { return this.generateErrorResponse( - "Wrong \"resolution\" parameter. Acceptable values from 100 to 1999 for both width and height", + "Wrong 'resolution' parameter. Acceptable values from 100 to 1999 for both width and height", "/api/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); } if (recordingLayoutString != null && !recordingLayoutString.isEmpty()) { try { recordingLayout = RecordingLayout.valueOf(recordingLayoutString); } catch (Exception e) { - return this.generateErrorResponse("Type error in some parameter", "/api/recordings/start", - HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in parameter 'recordingLayout'", + "/api/recordings/start", HttpStatus.BAD_REQUEST); } } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java b/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java index 05748411..267d8f9f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/FormatChecker.java @@ -30,8 +30,15 @@ public class FormatChecker { } public boolean isValidCustomSessionId(String customSessionId) { - // Alphanumeric string - return customSessionId.matches("[a-zA-Z0-9_-]+"); + return isValidAlphanumeric(customSessionId); + } + + public boolean isValidRecordingName(String recodingName) { + return isValidAlphanumeric(recodingName); + } + + private boolean isValidAlphanumeric(String str) { + return str.matches("[a-zA-Z0-9_-]+"); } } From 1d48c918a9026b7805dee15e78f08173db92144c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 13:44:20 +0200 Subject: [PATCH 003/435] openvidu-server: fixed ComposedQuickStartRecordingServer dead code --- .../recording/service/ComposedQuickStartRecordingService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java index 3f529772..7bd09037 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java @@ -97,7 +97,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService log.info("Stopping COMPOSED_QUICK_START ({}) recording {} of session {}. Reason: {}", recording.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId(), RecordingManager.finalReason(reason)); - log.info("Container for session {} still being ready for new recordings", session.getSessionId()); + log.info("Container for session {} still being ready for new recordings", recording.getSessionId()); String containerId = this.sessionsContainers.get(recording.getSessionId()); From b1836df20ba7ffa346200be165c29f260216f879 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 14:01:45 +0200 Subject: [PATCH 004/435] openvidu-testapp: openvidu-node-client dependency updated --- openvidu-testapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-testapp/package.json b/openvidu-testapp/package.json index bf2e5bbe..65c58b8d 100644 --- a/openvidu-testapp/package.json +++ b/openvidu-testapp/package.json @@ -16,7 +16,7 @@ "core-js": "3.4.7", "hammerjs": "2.0.8", "openvidu-browser": "2.15.0", - "openvidu-node-client": "2.11.0", + "openvidu-node-client": "2.15.0", "rxjs": "6.5.3", "zone.js": "0.10.2" }, From 401fc3d7fa976fb22c05620c16ca6803301895c2 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 14:42:45 +0200 Subject: [PATCH 005/435] openvidu-server: seal stopped metadata file before posting CDR/Webhook event --- .../service/ComposedQuickStartRecordingService.java | 5 +---- .../recording/service/ComposedRecordingService.java | 5 +---- .../server/recording/service/RecordingManager.java | 2 ++ .../server/recording/service/RecordingService.java | 9 +++++++++ .../recording/service/SingleStreamRecordingService.java | 1 - 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java index 7bd09037..c5325740 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java @@ -119,10 +119,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService recording = updateRecordingAttributes(recording); - final String folderPath = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"; - final String metadataFilePath = folderPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId(); - this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(), - metadataFilePath); + this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(), getMetadataFilePath(recording)); cleanRecordingMaps(recording); final long timestamp = System.currentTimeMillis(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java index a645e6d2..8ecc5c1d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java @@ -103,7 +103,6 @@ public class ComposedRecordingService extends RecordingService { @Override public Recording stopRecording(Session session, Recording recording, EndReason reason) { - recording = this.sealRecordingMetadataFileAsStopped(recording); if (recording.hasVideo()) { return this.stopRecordingWithVideo(session, recording, reason); } else { @@ -297,10 +296,8 @@ public class ComposedRecordingService extends RecordingService { stopAndRemoveRecordingContainer(recording, containerId, 30); recording = updateRecordingAttributes(recording); - final String folderPath = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"; - final String metadataFilePath = folderPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId(); this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(), - metadataFilePath); + getMetadataFilePath(recording)); cleanRecordingMaps(recording); final long timestamp = System.currentTimeMillis(); 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 41b901f7..57d41d1b 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 @@ -310,6 +310,8 @@ public class RecordingManager { recording = this.sessionsRecordings.get(session.getSessionId()); } + recording = ((RecordingService) singleStreamRecordingService).sealRecordingMetadataFileAsStopped(recording); + final long timestamp = System.currentTimeMillis(); this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, Status.stopped); cdr.recordRecordingStopped(recording, reason, timestamp); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java index 15317a07..385899e3 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java @@ -175,6 +175,10 @@ public abstract class RecordingService { protected OpenViduException failStartRecording(Session session, Recording recording, String errorMessage) { log.error("Recording start failed for session {}: {}", session.getSessionId(), errorMessage); recording.setStatus(io.openvidu.java.client.Recording.Status.failed); + + sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(), + getMetadataFilePath(recording)); + this.recordingManager.startingRecordings.remove(recording.getId()); this.recordingManager.sessionsRecordingsStarting.remove(session.getSessionId()); this.stopRecording(session, recording, null); @@ -186,6 +190,11 @@ public abstract class RecordingService { this.recordingManager.startedRecordings.remove(recording.getId()); } + protected String getMetadataFilePath(Recording recording) { + final String folderPath = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"; + return folderPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId(); + } + /** * Simple wrapper for returning update RecordingProperties and a free * recordingId when starting a new recording diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java index 0e246e34..404ca521 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java @@ -139,7 +139,6 @@ public class SingleStreamRecordingService extends RecordingService { @Override public Recording stopRecording(Session session, Recording recording, EndReason reason) { - recording = this.sealRecordingMetadataFileAsStopped(recording); return this.stopRecording(session, recording, reason, 0); } From e37e5b79220c6cf32bcc6f81b195327863c4e1b1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 20:09:51 +0200 Subject: [PATCH 006/435] openvidu-test-e2e: print out streamPropertyChanged events --- .../test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 865621e0..9dcbdb88 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -937,6 +937,7 @@ public class OpenViduTestAppE2eTest { // Unpublish video final CountDownLatch latch1 = new CountDownLatch(2); user.getEventManager().on("streamPropertyChanged", (event) -> { + System.out.println(event.toString()); threadAssertions.add("videoActive".equals(event.get("changedProperty").getAsString())); threadAssertions.add(!event.get("newValue").getAsBoolean()); latch1.countDown(); @@ -960,6 +961,7 @@ public class OpenViduTestAppE2eTest { // Unpublish audio final CountDownLatch latch2 = new CountDownLatch(2); user.getEventManager().on("streamPropertyChanged", (event) -> { + System.out.println(event.toString()); threadAssertions.add("audioActive".equals(event.get("changedProperty").getAsString())); threadAssertions.add(!event.get("newValue").getAsBoolean()); latch2.countDown(); From 7b2c9f91181412220e2d82519e10588125f9e70d Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 21:41:13 +0200 Subject: [PATCH 007/435] openvidu-test-e2e: fix streamPropertyChanged --- .../openvidu/test/e2e/OpenViduTestAppE2eTest.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 9dcbdb88..6f472109 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -994,9 +994,11 @@ public class OpenViduTestAppE2eTest { + "}"; System.out.println("Publisher dimensions: " + event.get("newValue").getAsJsonObject().toString()); System.out.println("Real dimensions of viewport: " + expectedDimensions); - threadAssertions.add("videoDimensions".equals(event.get("changedProperty").getAsString())); - threadAssertions.add(expectedDimensions.equals(event.get("newValue").getAsJsonObject().toString())); - latch3.countDown(); + if ("videoDimensions".equals(event.get("changedProperty").getAsString())) { + if (expectedDimensions.equals(event.get("newValue").getAsJsonObject().toString())) { + latch3.countDown(); + } + } }); user.getDriver().manage().window().setSize(new Dimension(newWidth, newHeight)); @@ -1011,7 +1013,7 @@ public class OpenViduTestAppE2eTest { user.getEventManager().waitUntilEventReaches("streamPropertyChanged", 6); - if (!latch3.await(5000, TimeUnit.MILLISECONDS)) { + if (!latch3.await(6000, TimeUnit.MILLISECONDS)) { gracefullyLeaveParticipants(2); fail(); return; @@ -1020,11 +1022,6 @@ public class OpenViduTestAppE2eTest { System.out.println(getBase64Screenshot(user)); user.getEventManager().off("streamPropertyChanged"); - log.info("Thread assertions: {}", threadAssertions.toString()); - for (Iterator iter = threadAssertions.iterator(); iter.hasNext();) { - Assert.assertTrue("Some Event property was wrong", iter.next()); - iter.remove(); - } gracefullyLeaveParticipants(2); } From 8f1512f965a1fb24a7e22085a9379bef82ca9589 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 3 Sep 2020 22:13:20 +0200 Subject: [PATCH 008/435] openvidu-test-e2e: fix streamPropertyChanged test --- .../test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 6f472109..d114b130 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -934,6 +934,9 @@ public class OpenViduTestAppE2eTest { user.getEventManager().waitUntilEventReaches("streamCreated", 2); user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + // Give some time for the screen sharing warning to stop resizing the viewport + Thread.sleep(3000); + // Unpublish video final CountDownLatch latch1 = new CountDownLatch(2); user.getEventManager().on("streamPropertyChanged", (event) -> { From 557a2e764ab6516ad56557ffbbf082532c30a482 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 9 Sep 2020 12:40:26 +0200 Subject: [PATCH 009/435] Updated Jenkinsfile to support openvidu-browser, openvidu-node-client commit selection --- openvidu-test-e2e/jenkins/Jenkinsfile | 40 +++++++++++++++++++++------ 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 762d0aa7..dd4cfdfe 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -18,13 +18,13 @@ node('container') { sh 'cd openvidu && git fetch origin && git checkout $OPENVIDU_COMMIT' sh(script: '''#!/bin/bash if $KURENTO_JAVA_SNAPSHOT ; then - git clone https://github.com/Kurento/kurento-java.git - cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION + git clone https://github.com/Kurento/kurento-java.git + cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION fi '''.stripIndent()) sh(script: '''#!/bin/bash @@ -44,10 +44,32 @@ node('container') { sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } stage('OpenVidu Browser build') { - sh 'cd openvidu/openvidu-browser && npm install --unsafe-perm && npm run build && npm link' + sh(script: '''#!/bin/bash + if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then + cd openvidu + git checkout $OPENVIDU_BROWSER_COMMIT + cd openvidu-browser + npm install --unsafe-perm && npm run build && npm link + cd .. + git checkout $OPENVIDU_COMMIT + else + cd openvidu/openvidu-browser && npm install --unsafe-perm && npm run build && npm link + fi + '''.stripIndent()) } stage('OpenVidu Node Client build') { - sh 'cd openvidu/openvidu-node-client && npm install --unsafe-perm && npm run build && npm link' + sh(script: '''#!/bin/bash + if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then + cd openvidu + git checkout $OPENVIDU_NODE_CLIENT_COMMIT + cd openvidu-node-client + npm install --unsafe-perm && npm run build && npm link + cd .. + git checkout $OPENVIDU_COMMIT + else + cd openvidu/openvidu-node-client && npm install --unsafe-perm && npm run build && npm link + fi + '''.stripIndent()) } stage('OpenVidu TestApp build') { sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm link openvidu-browser && npm link openvidu-node-client && export NG_CLI_ANALYTICS=ci && ./node_modules/@angular/cli/bin/ng build --prod' From 7acb8e328df25ddb74fe765d80626ba36031c8df Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 9 Sep 2020 13:06:50 +0200 Subject: [PATCH 010/435] Jenkinsfile updated to support openvidu-server commit selection --- openvidu-test-e2e/jenkins/Jenkinsfile | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index dd4cfdfe..e8cb0432 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -3,8 +3,9 @@ node('container') { docker.image('selenium/standalone-chrome:latest').pull() docker.image('selenium/standalone-firefox:latest').pull() docker.image('selenium/standalone-chrome:latest').withRun('-p 6666:4444 --name chrome --shm-size=1g -v /opt/openvidu:/opt/openvidu') { c -> - sh 'rm -rf /opt/openvidu/barcode.* && wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' - sh 'rm -rf /opt/openvidu/fakeaudio.* && wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' + sh 'rm -rf /opt/openvidu/* || true' + sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' + sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() @@ -13,7 +14,6 @@ node('container') { sh 'rm -rf ~/.m2 || true' sh 'rm -rf openvidu || true' sh 'rm -rf kurento-java || true' - sh 'rm -rf /opt/openvidu/recordings/* || true' sh 'git clone https://github.com/OpenVidu/openvidu.git' sh 'cd openvidu && git fetch origin && git checkout $OPENVIDU_COMMIT' sh(script: '''#!/bin/bash @@ -81,8 +81,17 @@ node('container') { sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' } stage('OpenVidu Server build') { - sh 'cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm link openvidu-browser && export NG_CLI_ANALYTICS=ci && npm run build-prod' - sh 'cd openvidu/openvidu-server && mvn --batch-mode clean compile package' + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_SERVER_COMMIT != "default" ]]; then + git checkout $OPENVIDU_SERVER_COMMIT + fi + cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm link openvidu-browser && export NG_CLI_ANALYTICS=ci && npm run build-prod + cd ../.. && mvn --batch-mode clean compile package + cp target/openvidu-server*.jar /opt/openvidu + cd .. + git checkout $OPENVIDU_COMMIT + '''.stripIndent()) } stage ('Environment Launch') { sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' @@ -92,10 +101,10 @@ node('container') { sh(script: '''#!/bin/bash if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - cd openvidu/openvidu-server/target && java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook openvidu-server-*.jar &> openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> /opt/openvidu/openvidu-server.log & else echo "Using default openvidu-recording tag" - cd openvidu/openvidu-server/target && java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook openvidu-server-*.jar &> openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> /opt/openvidu/openvidu-server.log & fi '''.stripIndent()) sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' @@ -106,7 +115,7 @@ node('container') { cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ test if [[ "$?" -ne 0 ]] ; then echo "ERROR RUNNING TESTS" - cat openvidu/openvidu-server/target/openvidu-server.log + cat /opt/openvidu/openvidu-server.log fi '''.stripIndent()) } From 7602e8f51dcfbf2d6417741b3eb26f9b169b5698 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 9 Sep 2020 14:26:47 +0200 Subject: [PATCH 011/435] Jenkinsfile updated to pack npm libraries --- openvidu-test-e2e/jenkins/Jenkinsfile | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index e8cb0432..dacb3c2d 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -45,34 +45,34 @@ node('container') { } stage('OpenVidu Browser build') { sh(script: '''#!/bin/bash + cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - cd openvidu git checkout $OPENVIDU_BROWSER_COMMIT - cd openvidu-browser - npm install --unsafe-perm && npm run build && npm link - cd .. - git checkout $OPENVIDU_COMMIT - else - cd openvidu/openvidu-browser && npm install --unsafe-perm && npm run build && npm link fi + cd openvidu-browser + npm install --unsafe-perm && npm run build + npm pack + cp openvidu-browser-*.tgz /opt/openvidu + cd .. + git checkout $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu Node Client build') { sh(script: '''#!/bin/bash + cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - cd openvidu git checkout $OPENVIDU_NODE_CLIENT_COMMIT - cd openvidu-node-client - npm install --unsafe-perm && npm run build && npm link - cd .. - git checkout $OPENVIDU_COMMIT - else - cd openvidu/openvidu-node-client && npm install --unsafe-perm && npm run build && npm link fi + cd openvidu-node-client + npm install --unsafe-perm && npm run build + npm pack + cp openvidu-node-client-*.tgz /opt/openvidu + cd .. + git checkout $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu TestApp build') { - sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm link openvidu-browser && npm link openvidu-node-client && export NG_CLI_ANALYTICS=ci && ./node_modules/@angular/cli/bin/ng build --prod' + sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && npm install /opt/openvidu/openvidu-node-client-*.tgz && export NG_CLI_ANALYTICS=ci && ./node_modules/@angular/cli/bin/ng build --prod' } stage('OpenVidu Server unit tests') { sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' @@ -86,7 +86,7 @@ node('container') { if [[ $OPENVIDU_SERVER_COMMIT != "default" ]]; then git checkout $OPENVIDU_SERVER_COMMIT fi - cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm link openvidu-browser && export NG_CLI_ANALYTICS=ci && npm run build-prod + cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS=ci && npm run build-prod cd ../.. && mvn --batch-mode clean compile package cp target/openvidu-server*.jar /opt/openvidu cd .. From db5f58f5ca67df82fa5b8fde436cb6527b8aefa2 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 9 Sep 2020 14:34:11 +0200 Subject: [PATCH 012/435] Jenkinsfile updated to force checkouts --- openvidu-test-e2e/jenkins/Jenkinsfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index dacb3c2d..ff9dc3f0 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -47,28 +47,28 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout $OPENVIDU_BROWSER_COMMIT + git checkout -f $OPENVIDU_BROWSER_COMMIT fi cd openvidu-browser npm install --unsafe-perm && npm run build npm pack cp openvidu-browser-*.tgz /opt/openvidu cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu Node Client build') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout $OPENVIDU_NODE_CLIENT_COMMIT + git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT fi cd openvidu-node-client npm install --unsafe-perm && npm run build npm pack cp openvidu-node-client-*.tgz /opt/openvidu cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu TestApp build') { @@ -84,13 +84,13 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_SERVER_COMMIT != "default" ]]; then - git checkout $OPENVIDU_SERVER_COMMIT + git checkout -f $OPENVIDU_SERVER_COMMIT fi cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS=ci && npm run build-prod cd ../.. && mvn --batch-mode clean compile package cp target/openvidu-server*.jar /opt/openvidu cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage ('Environment Launch') { From 35e62f3c2c40a8f0f4fd883ccd805dbcae28c8e1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 9 Sep 2020 16:29:41 +0200 Subject: [PATCH 013/435] Jenkinsfile updated to avoid npm build terminal query --- openvidu-node-client/.gitignore | 4 +++- openvidu-test-e2e/jenkins/Jenkinsfile | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openvidu-node-client/.gitignore b/openvidu-node-client/.gitignore index 51757794..3cdfcc6e 100644 --- a/openvidu-node-client/.gitignore +++ b/openvidu-node-client/.gitignore @@ -45,4 +45,6 @@ Thumbs.db /lib/ docs/ -lib/ \ No newline at end of file +lib/ + +*.tgz diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index ff9dc3f0..11f92a0d 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -72,7 +72,7 @@ node('container') { '''.stripIndent()) } stage('OpenVidu TestApp build') { - sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && npm install /opt/openvidu/openvidu-node-client-*.tgz && export NG_CLI_ANALYTICS=ci && ./node_modules/@angular/cli/bin/ng build --prod' + sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && npm install /opt/openvidu/openvidu-node-client-*.tgz && export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod' } stage('OpenVidu Server unit tests') { sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' @@ -86,7 +86,7 @@ node('container') { if [[ $OPENVIDU_SERVER_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_SERVER_COMMIT fi - cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS=ci && npm run build-prod + cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. && mvn --batch-mode clean compile package cp target/openvidu-server*.jar /opt/openvidu cd .. @@ -95,7 +95,7 @@ node('container') { } stage ('Environment Launch') { sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' - sh 'cd openvidu/openvidu-testapp/dist && http-server -S -p 4200 &> /testapp.log &' + sh 'cd openvidu/openvidu-testapp/dist && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' sh(script: '''#!/bin/bash From e3c61b1707b56a328fd3b3fe410c20826e79c4ce Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 10 Sep 2020 13:56:20 +0200 Subject: [PATCH 014/435] Jenkinsfile updated to avoid openvidu-java-client overwrite when checking out --- openvidu-test-e2e/jenkins/Jenkinsfile | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 11f92a0d..043e5bb4 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -38,11 +38,6 @@ node('container') { fi '''.stripIndent()) } - stage('OpenVidu parent build') { - sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' - sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=1.0.0-TEST' - sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' - } stage('OpenVidu Browser build') { sh(script: '''#!/bin/bash cd openvidu @@ -74,6 +69,11 @@ node('container') { stage('OpenVidu TestApp build') { sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && npm install /opt/openvidu/openvidu-node-client-*.tgz && export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod' } + stage('OpenVidu parent build') { + sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' + sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=1.0.0-TEST' + sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' + } stage('OpenVidu Server unit tests') { sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' } @@ -82,15 +82,9 @@ node('container') { } stage('OpenVidu Server build') { sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_SERVER_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_SERVER_COMMIT - fi - cd openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod + cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. && mvn --batch-mode clean compile package cp target/openvidu-server*.jar /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage ('Environment Launch') { From 11dbc750c6b2767f7b30348c080003fdea61aa29 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 10 Sep 2020 14:31:29 +0200 Subject: [PATCH 015/435] Jenkinsfile updated with fixed openvidu-server.log artifact --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 043e5bb4..bbcfe2d0 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -115,7 +115,7 @@ node('container') { } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' - archiveArtifacts artifacts: '**/openvidu-server.log' + archiveArtifacts artifacts: '/opt/openvidu/openvidu-server.log' } } } From 343e4ec2005f69fcbfa3a4f90852fbd9b50e17f5 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 10 Sep 2020 17:21:46 +0200 Subject: [PATCH 016/435] Jenkinsfile updated to fix openvidu-server.log --- openvidu-test-e2e/jenkins/Jenkinsfile | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index bbcfe2d0..7c656b54 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -88,34 +88,28 @@ node('container') { '''.stripIndent()) } stage ('Environment Launch') { - sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' + sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' sh 'cd openvidu/openvidu-testapp/dist && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' sh(script: '''#!/bin/bash if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> /opt/openvidu/openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & else echo "Using default openvidu-recording tag" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> /opt/openvidu/openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & fi '''.stripIndent()) sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' } stage ('OpenVidu E2E tests') { try { - sh(script: '''#!/bin/bash - cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ test - if [[ "$?" -ne 0 ]] ; then - echo "ERROR RUNNING TESTS" - cat /opt/openvidu/openvidu-server.log - fi - '''.stripIndent()) + sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ test' } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' - archiveArtifacts artifacts: '/opt/openvidu/openvidu-server.log' + archiveArtifacts artifacts: '**/openvidu-server.log' } } } From a2daa6baa049584467caac3c33ef4a4155b95d3b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 11 Sep 2020 12:35:42 +0200 Subject: [PATCH 017/435] Jenkinsfile updated to not overwrite branch changes --- openvidu-test-e2e/jenkins/Jenkinsfile | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 7c656b54..37073784 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -15,7 +15,7 @@ node('container') { sh 'rm -rf openvidu || true' sh 'rm -rf kurento-java || true' sh 'git clone https://github.com/OpenVidu/openvidu.git' - sh 'cd openvidu && git fetch origin && git checkout $OPENVIDU_COMMIT' + sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' sh(script: '''#!/bin/bash if $KURENTO_JAVA_SNAPSHOT ; then git clone https://github.com/Kurento/kurento-java.git @@ -42,28 +42,26 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_BROWSER_COMMIT + git checkout $OPENVIDU_BROWSER_COMMIT fi cd openvidu-browser - npm install --unsafe-perm && npm run build - npm pack + npm install --unsafe-perm && npm run build && npm pack cp openvidu-browser-*.tgz /opt/openvidu cd .. - git checkout -f $OPENVIDU_COMMIT + git checkout $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu Node Client build') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT + git checkout $OPENVIDU_NODE_CLIENT_COMMIT fi cd openvidu-node-client - npm install --unsafe-perm && npm run build - npm pack + npm install --unsafe-perm && npm run build && npm pack cp openvidu-node-client-*.tgz /opt/openvidu cd .. - git checkout -f $OPENVIDU_COMMIT + git checkout $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu TestApp build') { From 0fdbcaac90c32f492d8dd5a0d505dc3d6d19427f Mon Sep 17 00:00:00 2001 From: Saul Pablo Labajo Izquierdo Date: Sat, 12 Sep 2020 09:57:33 +0200 Subject: [PATCH 018/435] Added network cache param to IP cameras --- .../io/openvidu/server/cdr/CDREventWebrtcConnection.java | 1 + .../server/kurento/core/KurentoMediaOptions.java | 8 +++++++- .../openvidu/server/kurento/endpoint/MediaEndpoint.java | 3 +++ .../io/openvidu/server/rest/SessionRestController.java | 9 ++++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java index 4536c9a2..e3ff0024 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java @@ -69,6 +69,7 @@ public class CDREventWebrtcConnection extends CDREventEnd implements Comparable< if (kMediaOptions.rtspUri != null) { json.addProperty("rtspUri", kMediaOptions.rtspUri); json.addProperty("adaptativeBitrate", kMediaOptions.adaptativeBitrate); + json.addProperty("networkCache", kMediaOptions.network_cache); json.addProperty("onlyPlayWithSubscribers", kMediaOptions.onlyPlayWithSubscribers); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java index 7684b821..fa5feddc 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java @@ -32,6 +32,7 @@ public class KurentoMediaOptions extends MediaOptions { public String rtspUri; public Boolean adaptativeBitrate; public Boolean onlyPlayWithSubscribers; + public Integer network_cache; public KurentoMediaOptions(boolean isOffer, String sdpOffer, Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, String typeOfVideo, Integer frameRate, String videoDimensions, @@ -45,7 +46,7 @@ public class KurentoMediaOptions extends MediaOptions { public KurentoMediaOptions(boolean isOffer, String sdpOffer, Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, String typeOfVideo, Integer frameRate, String videoDimensions, KurentoFilter filter, boolean doLoopback, String rtspUri, Boolean adaptativeBitrate, - Boolean onlyPlayWithSubscribers) { + Boolean onlyPlayWithSubscribers, Integer network_cache) { super(hasAudio, hasVideo, audioActive, videoActive, typeOfVideo, frameRate, videoDimensions, filter); this.isOffer = isOffer; this.sdpOffer = sdpOffer; @@ -53,6 +54,7 @@ public class KurentoMediaOptions extends MediaOptions { this.rtspUri = rtspUri; this.adaptativeBitrate = adaptativeBitrate; this.onlyPlayWithSubscribers = onlyPlayWithSubscribers; + this.network_cache = network_cache; } public KurentoMediaOptions(Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, @@ -65,6 +67,7 @@ public class KurentoMediaOptions extends MediaOptions { this.rtspUri = streamProperties.rtspUri; this.adaptativeBitrate = streamProperties.adaptativeBitrate; this.onlyPlayWithSubscribers = streamProperties.onlyPlayWithSubscribers; + this.network_cache = streamProperties.network_cache; } @Override @@ -76,6 +79,9 @@ public class KurentoMediaOptions extends MediaOptions { if (onlyPlayWithSubscribers != null) { json.addProperty("onlyPlayWithSubscribers", onlyPlayWithSubscribers); } + if (network_cache != null) { + json.addProperty("networkCache", network_cache); + } return json; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java index f4159ed3..bf634138 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java @@ -364,6 +364,9 @@ public abstract class MediaEndpoint { if (!mediaOptions.adaptativeBitrate) { playerBuilder = playerBuilder.useEncodedMedia(); } + if (mediaOptions.network_cache != null) { + playerBuilder = playerBuilder.withNetworkCache(mediaOptions.network_cache); + } playerBuilder.buildAsync(new Continuation() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 28da7b54..5ce98fb2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -755,12 +755,19 @@ public class SessionRestController { String rtspUri; Boolean adaptativeBitrate; Boolean onlyPlayWithSubscribers; + String network_cache_str; + Integer network_cache; String data; try { type = (String) params.get("type"); rtspUri = (String) params.get("rtspUri"); adaptativeBitrate = (Boolean) params.get("adaptativeBitrate"); onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers"); + network_cache_str = (String) params.get("networkCache"); + if (network_cache_str != null) + network_cache = Integer.parseInt(network_cache_str); + else + network_cache = null; data = (String) params.get("data"); } catch (ClassCastException e) { return this.generateErrorResponse("Type error in some parameter", @@ -785,7 +792,7 @@ public class SessionRestController { String videoDimensions = null; KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive, videoActive, typeOfVideo, frameRate, videoDimensions, null, false, rtspUri, adaptativeBitrate, - onlyPlayWithSubscribers); + onlyPlayWithSubscribers, network_cache); // While closing a session IP cameras can't be published if (session.closingLock.readLock().tryLock()) { From 7ceba5e0988a57c72eea3d055cb7e9411512780c Mon Sep 17 00:00:00 2001 From: Saul Pablo Labajo Izquierdo Date: Sat, 12 Sep 2020 14:37:45 +0200 Subject: [PATCH 019/435] Respected Java naming conventions --- .../server/cdr/CDREventWebrtcConnection.java | 2 +- .../server/kurento/core/KurentoMediaOptions.java | 12 ++++++------ .../server/kurento/endpoint/MediaEndpoint.java | 4 ++-- .../server/rest/SessionRestController.java | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java index e3ff0024..eaa8e9a5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventWebrtcConnection.java @@ -69,7 +69,7 @@ public class CDREventWebrtcConnection extends CDREventEnd implements Comparable< if (kMediaOptions.rtspUri != null) { json.addProperty("rtspUri", kMediaOptions.rtspUri); json.addProperty("adaptativeBitrate", kMediaOptions.adaptativeBitrate); - json.addProperty("networkCache", kMediaOptions.network_cache); + json.addProperty("networkCache", kMediaOptions.networkCache); json.addProperty("onlyPlayWithSubscribers", kMediaOptions.onlyPlayWithSubscribers); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java index fa5feddc..1e477356 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoMediaOptions.java @@ -32,7 +32,7 @@ public class KurentoMediaOptions extends MediaOptions { public String rtspUri; public Boolean adaptativeBitrate; public Boolean onlyPlayWithSubscribers; - public Integer network_cache; + public Integer networkCache; public KurentoMediaOptions(boolean isOffer, String sdpOffer, Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, String typeOfVideo, Integer frameRate, String videoDimensions, @@ -46,7 +46,7 @@ public class KurentoMediaOptions extends MediaOptions { public KurentoMediaOptions(boolean isOffer, String sdpOffer, Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, String typeOfVideo, Integer frameRate, String videoDimensions, KurentoFilter filter, boolean doLoopback, String rtspUri, Boolean adaptativeBitrate, - Boolean onlyPlayWithSubscribers, Integer network_cache) { + Boolean onlyPlayWithSubscribers, Integer networkCache) { super(hasAudio, hasVideo, audioActive, videoActive, typeOfVideo, frameRate, videoDimensions, filter); this.isOffer = isOffer; this.sdpOffer = sdpOffer; @@ -54,7 +54,7 @@ public class KurentoMediaOptions extends MediaOptions { this.rtspUri = rtspUri; this.adaptativeBitrate = adaptativeBitrate; this.onlyPlayWithSubscribers = onlyPlayWithSubscribers; - this.network_cache = network_cache; + this.networkCache = networkCache; } public KurentoMediaOptions(Boolean hasAudio, Boolean hasVideo, Boolean audioActive, Boolean videoActive, @@ -67,7 +67,7 @@ public class KurentoMediaOptions extends MediaOptions { this.rtspUri = streamProperties.rtspUri; this.adaptativeBitrate = streamProperties.adaptativeBitrate; this.onlyPlayWithSubscribers = streamProperties.onlyPlayWithSubscribers; - this.network_cache = streamProperties.network_cache; + this.networkCache = streamProperties.networkCache; } @Override @@ -79,8 +79,8 @@ public class KurentoMediaOptions extends MediaOptions { if (onlyPlayWithSubscribers != null) { json.addProperty("onlyPlayWithSubscribers", onlyPlayWithSubscribers); } - if (network_cache != null) { - json.addProperty("networkCache", network_cache); + if (networkCache != null) { + json.addProperty("networkCache", networkCache); } return json; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java index bf634138..77b216f2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java @@ -364,8 +364,8 @@ public abstract class MediaEndpoint { if (!mediaOptions.adaptativeBitrate) { playerBuilder = playerBuilder.useEncodedMedia(); } - if (mediaOptions.network_cache != null) { - playerBuilder = playerBuilder.withNetworkCache(mediaOptions.network_cache); + if (mediaOptions.networkCache != null) { + playerBuilder = playerBuilder.withNetworkCache(mediaOptions.networkCache); } playerBuilder.buildAsync(new Continuation() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 5ce98fb2..a22db8c1 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -755,19 +755,19 @@ public class SessionRestController { String rtspUri; Boolean adaptativeBitrate; Boolean onlyPlayWithSubscribers; - String network_cache_str; - Integer network_cache; + String networkCacheStr; + Integer networkCache; String data; try { type = (String) params.get("type"); rtspUri = (String) params.get("rtspUri"); adaptativeBitrate = (Boolean) params.get("adaptativeBitrate"); onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers"); - network_cache_str = (String) params.get("networkCache"); - if (network_cache_str != null) - network_cache = Integer.parseInt(network_cache_str); + networkCacheStr = (String) params.get("networkCache"); + if (networkCacheStr != null) + networkCache = Integer.parseInt(networkCacheStr); else - network_cache = null; + networkCache = null; data = (String) params.get("data"); } catch (ClassCastException e) { return this.generateErrorResponse("Type error in some parameter", @@ -792,7 +792,7 @@ public class SessionRestController { String videoDimensions = null; KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive, videoActive, typeOfVideo, frameRate, videoDimensions, null, false, rtspUri, adaptativeBitrate, - onlyPlayWithSubscribers, network_cache); + onlyPlayWithSubscribers, networkCache); // While closing a session IP cameras can't be published if (session.closingLock.readLock().tryLock()) { From 08f4b895c051cea2ed135f55c7a7e13e67e1dc87 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 14 Sep 2020 14:37:44 +0200 Subject: [PATCH 020/435] Delete aws market env variables --- .../deployments/ce/aws/createAMI.sh | 10 +---- .../deployments/ce/aws/replicate_amis.sh | 4 -- .../deployments/pro/aws/createAMIs.sh | 38 +++---------------- .../deployments/pro/aws/replicate_amis.sh | 7 ++-- 4 files changed, 10 insertions(+), 49 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/createAMI.sh b/openvidu-server/deployments/ce/aws/createAMI.sh index adeb10d7..06474c41 100755 --- a/openvidu-server/deployments/ce/aws/createAMI.sh +++ b/openvidu-server/deployments/ce/aws/createAMI.sh @@ -1,20 +1,14 @@ #!/bin/bash -x set -eu -o pipefail -CF_OVP_TARGET=${CF_OVP_TARGET:-nomarket} CF_RELEASE=${CF_RELEASE:-false} if [[ $CF_RELEASE == "true" ]]; then git checkout v$OPENVIDU_VERSION fi -if [ ${CF_OVP_TARGET} == "market" ]; then - export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} - export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} - export AWS_DEFAULT_REGION=us-east-1 -else - export AWS_DEFAULT_REGION=eu-west-1 -fi +export AWS_DEFAULT_REGION=eu-west-1 + DATESTAMP=$(date +%s) TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json) diff --git a/openvidu-server/deployments/ce/aws/replicate_amis.sh b/openvidu-server/deployments/ce/aws/replicate_amis.sh index 838da435..e201bef4 100755 --- a/openvidu-server/deployments/ce/aws/replicate_amis.sh +++ b/openvidu-server/deployments/ce/aws/replicate_amis.sh @@ -9,10 +9,6 @@ set -eu -o pipefail # OV_AMI_ID OpenVidu AMI ID export AWS_DEFAULT_REGION=eu-west-1 -if [ ${CF_OVP_TARGET} == "market" ]; then - export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} - export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} -fi echo "Making original AMI public" aws ec2 wait image-exists --image-ids ${OV_AMI_ID} diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index 09e7bc84..4ca8adec 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -1,18 +1,5 @@ #!/bin/bash -x - -CF_OVP_TARGET=${CF_OVP_TARGET:-nomarket} - -if [ ${CF_OVP_TARGET} == "market" ]; then - export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} - export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} - export AWS_DEFAULT_REGION=us-east-1 -else - export AWS_DEFAULT_REGION=eu-west-1 -fi - -if [ "${OPENVIDU_PRO_IS_SNAPSHOT}" == "true" ]; then - OPENVIDU_PRO_VERSION=${OPENVIDU_PRO_VERSION}-SNAPSHOT -fi +export AWS_DEFAULT_REGION=eu-west-1 DATESTAMP=$(date +%s) TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json) @@ -61,13 +48,8 @@ sed -i "s/AMIUSEAST1/${AMIUSEAST1}/g" cfn-mkt-kms-ami.yaml ## KMS AMI # Copy template to S3 -if [ ${CF_OVP_TARGET} == "market" ]; then - aws s3 cp cfn-mkt-kms-ami.yaml s3://naeva-openvidu-pro - TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/naeva-openvidu-pro/cfn-mkt-kms-ami.yaml -else - aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io - TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml -fi +aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io +TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml aws cloudformation create-stack \ --stack-name kms-${DATESTAMP} \ @@ -94,13 +76,8 @@ aws cloudformation delete-stack --stack-name kms-${DATESTAMP} ## OpenVidu AMI # Copy template to S3 -if [ ${CF_OVP_TARGET} == "market" ]; then - aws s3 cp cfn-mkt-ov-ami.yaml s3://naeva-openvidu-pro - TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/naeva-openvidu-pro/cfn-mkt-ov-ami.yaml -else aws s3 cp cfn-mkt-ov-ami.yaml s3://aws.openvidu.io TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-ov-ami.yaml -fi aws cloudformation create-stack \ --stack-name openvidu-${DATESTAMP} \ @@ -128,13 +105,8 @@ aws cloudformation delete-stack --stack-name openvidu-${DATESTAMP} aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} # Updating the template -if [ ${CF_OVP_TARGET} == "market" ]; then - sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-mkt-openvidu-server-pro.yaml.template > cfn-mkt-openvidu-server-pro-${OPENVIDU_PRO_VERSION}.yaml - sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-mkt-openvidu-server-pro-${OPENVIDU_PRO_VERSION}.yaml -else - sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-openvidu-server-pro-no-market.yaml.template > cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml - sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml -fi +sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-openvidu-server-pro-no-market.yaml.template > cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml +sed -i "s/KMS_AMI_ID/${KMS_RAW_AMI_ID}/g" cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml rm $TEMPJSON rm cfn-mkt-kms-ami.yaml diff --git a/openvidu-server/deployments/pro/aws/replicate_amis.sh b/openvidu-server/deployments/pro/aws/replicate_amis.sh index 1838573f..78772710 100755 --- a/openvidu-server/deployments/pro/aws/replicate_amis.sh +++ b/openvidu-server/deployments/pro/aws/replicate_amis.sh @@ -12,10 +12,9 @@ set -eu -o pipefail # OV_AMI_ID OpenVidu AMI ID export AWS_DEFAULT_REGION=eu-west-1 -if [ ${CF_OVP_TARGET} == "market" ]; then - export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} - export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} -fi +export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} +export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} + echo "Making original AMIs public" From e4ccb6f3bb41c4b17fbb9c36000deaa86a05426b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 16 Sep 2020 13:50:22 +0200 Subject: [PATCH 021/435] openvidu-server: OPENVIDU_RECORDING_COMPOSED_BASICAUTH --- .../java/io/openvidu/server/config/OpenviduConfig.java | 7 +++++++ .../recording/service/ComposedRecordingService.java | 8 +++++--- .../additional-spring-configuration-metadata.json | 6 ++++++ openvidu-server/src/main/resources/application.properties | 1 + 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index 1beb6a41..13173325 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -130,6 +130,8 @@ public class OpenviduConfig { private String openviduRecordingCustomLayout; + private boolean openviduRecordingComposedBasicauth; + private String openviduRecordingVersion; private Integer openviduStreamsVideoMaxRecvBandwidth; @@ -246,6 +248,10 @@ public class OpenviduConfig { return this.openviduRecordingCustomLayout; } + public boolean isOpenviduRecordingComposedBasicauth() { + return this.openviduRecordingComposedBasicauth; + } + public String getOpenViduRecordingVersion() { return this.openviduRecordingVersion; } @@ -488,6 +494,7 @@ public class OpenviduConfig { openviduRecordingPublicAccess = asBoolean("OPENVIDU_RECORDING_PUBLIC_ACCESS"); openviduRecordingAutostopTimeout = asNonNegativeInteger("OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT"); openviduRecordingCustomLayout = asFileSystemPath("OPENVIDU_RECORDING_CUSTOM_LAYOUT"); + openviduRecordingComposedBasicauth = asBoolean("OPENVIDU_RECORDING_COMPOSED_BASICAUTH"); openviduRecordingVersion = asNonEmptyString("OPENVIDU_RECORDING_VERSION"); openviduRecordingComposedUrl = asOptionalURL("OPENVIDU_RECORDING_COMPOSED_URL"); checkOpenviduRecordingNotification(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java index 8ecc5c1d..449c2a63 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java @@ -516,6 +516,8 @@ public class ComposedRecordingService extends RecordingService { } String layout, finalUrl; + final String basicauth = openviduConfig.isOpenviduRecordingComposedBasicauth() ? ("OPENVIDUAPP:" + secret + "@") + : ""; if (RecordingLayout.CUSTOM.equals(recording.getRecordingLayout())) { layout = recording.getCustomLayout(); if (!layout.isEmpty()) { @@ -523,8 +525,8 @@ public class ComposedRecordingService extends RecordingService { layout = layout.endsWith("/") ? layout.substring(0, layout.length() - 1) : layout; } layout += "/index.html"; - finalUrl = (startsWithHttp ? "http" : "https") + "://OPENVIDUAPP:" + secret + "@" + recordingUrl - + "/layouts/custom" + layout + "?sessionId=" + recording.getSessionId() + "&secret=" + secret; + finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl + "/layouts/custom" + + layout + "?sessionId=" + recording.getSessionId() + "&secret=" + secret; } else { layout = recording.getRecordingLayout().name().toLowerCase().replaceAll("_", "-"); int port = startsWithHttp ? 80 : 443; @@ -535,7 +537,7 @@ public class ComposedRecordingService extends RecordingService { } String defaultPathForDefaultLayout = recordingComposedUrlDefined ? "" : ("/" + openviduConfig.getOpenViduFrontendDefaultPath()); - finalUrl = (startsWithHttp ? "http" : "https") + "://OPENVIDUAPP:" + secret + "@" + recordingUrl + finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl + defaultPathForDefaultLayout + "/#/layout-" + layout + "/" + recording.getSessionId() + "/" + secret + "/" + port + "/" + !recording.hasAudio(); } diff --git a/openvidu-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/openvidu-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 9448757d..6be8652a 100644 --- a/openvidu-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/openvidu-server/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -93,6 +93,12 @@ "description": "URL the composed-video recording dockerized Chrome will use to connect to the recording layouts inside OpenVidu Server host. This will affect all video recording layouts (default one BEST_FIT, all CUSTOM layouts). This allows changing the default URL, which is the public URL 'https://DOMAIN_OR_PUBLIC_IP:HTTPS_PORT/', for those cases where OpenVidu Server host does not allow back and forth connections using the public url from inside the host", "defaultValue": "" }, + { + "name": "OPENVIDU_RECORDING_COMPOSED_BASICAUTH", + "type": "java.lang.Boolean", + "description": "'true' to automatically add Basic Auth credentials to the URL passed to the recording container, false otherwise", + "defaultValue": true + }, { "name": "OPENVIDU_WEBHOOK", "type": "java.lang.Boolean", diff --git a/openvidu-server/src/main/resources/application.properties b/openvidu-server/src/main/resources/application.properties index 48b9859a..5fdf2cc9 100644 --- a/openvidu-server/src/main/resources/application.properties +++ b/openvidu-server/src/main/resources/application.properties @@ -33,6 +33,7 @@ OPENVIDU_RECORDING_NOTIFICATION=publisher_moderator OPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/custom-layout OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT=120 OPENVIDU_RECORDING_COMPOSED_URL= +OPENVIDU_RECORDING_COMPOSED_BASICAUTH=true OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH=1000 OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH=300 From 834da536b621566ef7280edf42000ce9a48e623f Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 16 Sep 2020 23:05:25 +0200 Subject: [PATCH 022/435] Load dinamically env variables from .env file --- .../pro/docker-compose/media-node/docker-compose.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index fe9ab5b4..2f0a872d 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -21,6 +21,8 @@ services: ulimits: core: -1 entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh'] + env_file: + - .env environment: - KMS_IMAGE=${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} - KMS_DEBUG_LEVEL=${KMS_DEBUG_LEVEL:-} From 693e2e65836c1fda9a26d0891c0db1f5f074e87f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 17 Sep 2020 16:50:41 +0200 Subject: [PATCH 023/435] openvidu-browser: clean "closeSession" configuration from jsonrpcclient.js --- openvidu-browser/src/OpenVidu/OpenVidu.ts | 1 - .../kurento-jsonrpc/clients/jsonrpcclient.js | 15 +-------------- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 312bd7f7..6a7bb76b 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -759,7 +759,6 @@ export class OpenVidu { startWs(onConnectSucces: (error: Error) => void): void { const config = { heartbeat: 5000, - sendCloseMessage: false, ws: { uri: this.wsUri, onconnected: onConnectSucces, diff --git a/openvidu-browser/src/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js b/openvidu-browser/src/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js index c4a5b7a8..bf7257c2 100644 --- a/openvidu-browser/src/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js +++ b/openvidu-browser/src/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js @@ -33,7 +33,6 @@ var Logger = console; /** * * heartbeat: interval in ms for each heartbeat message, - * sendCloseMessage : true / false, before closing the connection, it sends a closeSession message *
  * ws : {
  * 	uri : URI to conntect to,
@@ -250,25 +249,13 @@ function JsonRpcClient(configuration) {
 
     this.close = function (code, reason) {
         Logger.debug("Closing  with code: " + code + " because: " + reason);
-
         if (pingInterval != undefined) {
             Logger.debug("Clearing ping interval");
             clearInterval(pingInterval);
         }
         pingPongStarted = false;
         enabledPings = false;
-
-        if (configuration.sendCloseMessage) {
-            Logger.debug("Sending close message")
-            this.send('closeSession', null, function (error, result) {
-                if (error) {
-                    Logger.error("Error sending close message: " + JSON.stringify(error));
-                }
-                ws.close(code, reason);
-            });
-        } else {
-            ws.close(code, reason);
-        }
+        ws.close(code, reason);
     }
 
     // This method is only for testing

From 01894918b7d1460b032dc12438b2b9189d3ec599 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 17 Sep 2020 17:47:26 +0200
Subject: [PATCH 024/435] openvidu-server: recording upload refactoring

---
 .../io/openvidu/server/OpenViduServer.java    |  18 +
 .../recording/DummyRecordingUploader.java     |  20 +
 .../server/recording/RecordingUploader.java   |  11 +
 .../ComposedQuickStartRecordingService.java   | 346 +++++++++---------
 .../service/ComposedRecordingService.java     |  26 +-
 .../recording/service/RecordingManager.java   | 189 +++++-----
 .../service/RecordingManagerUtils.java        |  61 +++
 .../RecordingManagerUtilsLocalStorage.java    |  62 ++++
 .../recording/service/RecordingService.java   |  37 +-
 .../service/SingleStreamRecordingService.java |  13 +-
 .../io/openvidu/server/utils/JsonUtils.java   |  15 +-
 11 files changed, 511 insertions(+), 287 deletions(-)
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingUploader.java
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/recording/RecordingUploader.java
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtils.java
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java

diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
index ee2d8cbe..f1acf638 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
@@ -61,8 +61,12 @@ import io.openvidu.server.kurento.kms.FixedOneKmsManager;
 import io.openvidu.server.kurento.kms.KmsManager;
 import io.openvidu.server.kurento.kms.LoadManager;
 import io.openvidu.server.recording.DummyRecordingDownloader;
+import io.openvidu.server.recording.DummyRecordingUploader;
 import io.openvidu.server.recording.RecordingDownloader;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.recording.service.RecordingManager;
+import io.openvidu.server.recording.service.RecordingManagerUtils;
+import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage;
 import io.openvidu.server.rpc.RpcHandler;
 import io.openvidu.server.rpc.RpcNotificationService;
 import io.openvidu.server.utils.CommandExecutor;
@@ -184,6 +188,20 @@ public class OpenViduServer implements JsonRpcConfigurer {
 		return new KurentoParticipantEndpointConfig();
 	}
 
+	@Bean
+	@ConditionalOnMissingBean
+	@DependsOn({ "openviduConfig", "recordingManager" })
+	public RecordingManagerUtils recordingManagerUtils(OpenviduConfig openviduConfig,
+			RecordingManager recordingManager) {
+		return new RecordingManagerUtilsLocalStorage(openviduConfig, recordingManager);
+	}
+
+	@Bean
+	@ConditionalOnMissingBean
+	public RecordingUploader recordingUpload() {
+		return new DummyRecordingUploader();
+	}
+
 	@Bean
 	@ConditionalOnMissingBean
 	public RecordingDownloader recordingDownload() {
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingUploader.java b/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingUploader.java
new file mode 100644
index 00000000..828e10c1
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingUploader.java
@@ -0,0 +1,20 @@
+package io.openvidu.server.recording;
+
+public class DummyRecordingUploader implements RecordingUploader {
+
+	@Override
+	public void uploadRecording(Recording recording, Runnable successCallback, Runnable errorCallback) {
+		// Just immediately run success callback function
+		successCallback.run();
+	}
+
+	@Override
+	public void storeAsUploadingRecording(String recording) {
+	}
+
+	@Override
+	public boolean isBeingUploaded(String recordingId) {
+		return false;
+	}
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingUploader.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingUploader.java
new file mode 100644
index 00000000..e88b8719
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingUploader.java
@@ -0,0 +1,11 @@
+package io.openvidu.server.recording;
+
+public interface RecordingUploader {
+
+	void uploadRecording(Recording recording, Runnable successCallback, Runnable errorCallback);
+
+	void storeAsUploadingRecording(String recording);
+
+	boolean isBeingUploaded(String recordingId);
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
index c5325740..c0b8d86c 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
@@ -1,7 +1,14 @@
 package io.openvidu.server.recording.service;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.github.dockerjava.api.model.Bind;
 import com.github.dockerjava.api.model.Volume;
+
 import io.openvidu.client.OpenViduException;
 import io.openvidu.java.client.RecordingProperties;
 import io.openvidu.server.cdr.CallDetailRecord;
@@ -10,204 +17,213 @@ import io.openvidu.server.core.EndReason;
 import io.openvidu.server.core.Session;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.RecordingDownloader;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.utils.QuarantineKiller;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
 
 public class ComposedQuickStartRecordingService extends ComposedRecordingService {
 
-    private static final Logger log = LoggerFactory.getLogger(ComposedRecordingService.class);
+	private static final Logger log = LoggerFactory.getLogger(ComposedRecordingService.class);
 
-    public ComposedQuickStartRecordingService(RecordingManager recordingManager, RecordingDownloader recordingDownloader, OpenviduConfig openviduConfig, CallDetailRecord cdr, QuarantineKiller quarantineKiller) {
-        super(recordingManager, recordingDownloader, openviduConfig, cdr, quarantineKiller);
-    }
+	public ComposedQuickStartRecordingService(RecordingManager recordingManager,
+			RecordingDownloader recordingDownloader, RecordingUploader recordingUploader, OpenviduConfig openviduConfig,
+			CallDetailRecord cdr, QuarantineKiller quarantineKiller) {
+		super(recordingManager, recordingDownloader, recordingUploader, openviduConfig, cdr, quarantineKiller);
+	}
 
-    public void stopRecordingContainer(Session session, EndReason reason) {
-        log.info("Stopping COMPOSED_QUICK_START of session {}. Reason: {}",
-                session.getSessionId(), RecordingManager.finalReason(reason));
+	public void stopRecordingContainer(Session session, EndReason reason) {
+		log.info("Stopping COMPOSED_QUICK_START of session {}. Reason: {}", session.getSessionId(),
+				RecordingManager.finalReason(reason));
 
-        String containerId = this.sessionsContainers.get(session.getSessionId());
+		String containerId = this.sessionsContainers.get(session.getSessionId());
 
-        if (containerId != null) {
-            try {
-                dockerManager.removeDockerContainer(containerId, true);
-            } catch (Exception e) {
-                log.error("Can't remove COMPOSED_QUICK_START recording container from session {}", session.getSessionId());
-            }
+		if (containerId != null) {
+			try {
+				dockerManager.removeDockerContainer(containerId, true);
+			} catch (Exception e) {
+				log.error("Can't remove COMPOSED_QUICK_START recording container from session {}",
+						session.getSessionId());
+			}
 
-            containers.remove(containerId);
-            sessionsContainers.remove(session.getSessionId());
-        }
+			containers.remove(containerId);
+			sessionsContainers.remove(session.getSessionId());
+		}
 
-    }
+	}
 
-    @Override
-    protected Recording startRecordingWithVideo(Session session, Recording recording, RecordingProperties properties)
-            throws OpenViduException {
+	@Override
+	protected Recording startRecordingWithVideo(Session session, Recording recording, RecordingProperties properties)
+			throws OpenViduException {
 
-        log.info("Starting COMPOSED_QUICK_START ({}) recording {} of session {}",
-                properties.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId());
+		log.info("Starting COMPOSED_QUICK_START ({}) recording {} of session {}",
+				properties.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId());
 
-        List envs = new ArrayList<>();
+		List envs = new ArrayList<>();
 
-        envs.add("DEBUG_MODE=" + openviduConfig.isOpenViduRecordingDebug());
-        envs.add("RESOLUTION=" + properties.resolution());
-        envs.add("ONLY_VIDEO=" + !properties.hasAudio());
-        envs.add("FRAMERATE=30");
-        envs.add("VIDEO_ID=" + recording.getId());
-        envs.add("VIDEO_NAME=" + properties.name());
-        envs.add("VIDEO_FORMAT=mp4");
-        envs.add("RECORDING_JSON='" + recording.toJson().toString() + "'");
+		envs.add("DEBUG_MODE=" + openviduConfig.isOpenViduRecordingDebug());
+		envs.add("RESOLUTION=" + properties.resolution());
+		envs.add("ONLY_VIDEO=" + !properties.hasAudio());
+		envs.add("FRAMERATE=30");
+		envs.add("VIDEO_ID=" + recording.getId());
+		envs.add("VIDEO_NAME=" + properties.name());
+		envs.add("VIDEO_FORMAT=mp4");
+		envs.add("RECORDING_JSON='" + recording.toJson().toString() + "'");
 
-        String containerId = this.sessionsContainers.get(session.getSessionId());
-        try {
-            String recordExecCommand = "";
-            for(int i = 0; i < envs.size(); i++) {
-                if (i > 0) {
-                    recordExecCommand += "&& ";
-                }
-                recordExecCommand += "export " + envs.get(i) + " ";
-            }
-            recordExecCommand += "&& ./composed_quick_start.sh --start-recording > /var/log/ffmpeg.log 2>&1 &";
-            dockerManager.runCommandInContainer(containerId, recordExecCommand, 0);
-        } catch (Exception e) {
-            this.cleanRecordingMaps(recording);
-            throw this.failStartRecording(session, recording,
-                    "Couldn't initialize recording container. Error: " + e.getMessage());
-        }
+		String containerId = this.sessionsContainers.get(session.getSessionId());
+		try {
+			String recordExecCommand = "";
+			for (int i = 0; i < envs.size(); i++) {
+				if (i > 0) {
+					recordExecCommand += "&& ";
+				}
+				recordExecCommand += "export " + envs.get(i) + " ";
+			}
+			recordExecCommand += "&& ./composed_quick_start.sh --start-recording > /var/log/ffmpeg.log 2>&1 &";
+			dockerManager.runCommandInContainer(containerId, recordExecCommand, 0);
+		} catch (Exception e) {
+			this.cleanRecordingMaps(recording);
+			throw this.failStartRecording(session, recording,
+					"Couldn't initialize recording container. Error: " + e.getMessage());
+		}
 
-        this.sessionsContainers.put(session.getSessionId(), containerId);
+		this.sessionsContainers.put(session.getSessionId(), containerId);
 
-        try {
-            this.waitForVideoFileNotEmpty(recording);
-        } catch (OpenViduException e) {
-            this.cleanRecordingMaps(recording);
-            throw this.failStartRecording(session, recording,
-                    "Couldn't initialize recording container. Error: " + e.getMessage());
-        }
+		try {
+			this.waitForVideoFileNotEmpty(recording);
+		} catch (OpenViduException e) {
+			this.cleanRecordingMaps(recording);
+			throw this.failStartRecording(session, recording,
+					"Couldn't initialize recording container. Error: " + e.getMessage());
+		}
 
-        return recording;
-    }
+		return recording;
+	}
 
-    @Override
-    protected Recording stopRecordingWithVideo(Session session, Recording recording, EndReason reason) {
-        log.info("Stopping COMPOSED_QUICK_START ({}) recording {} of session {}. Reason: {}",
-                recording.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId(),
-                RecordingManager.finalReason(reason));
-        log.info("Container for session {} still being ready for new recordings", recording.getSessionId());
+	@Override
+	protected Recording stopRecordingWithVideo(Session session, Recording recording, EndReason reason) {
+		log.info("Stopping COMPOSED_QUICK_START ({}) recording {} of session {}. Reason: {}",
+				recording.hasAudio() ? "video + audio" : "audio-only", recording.getId(), recording.getSessionId(),
+				RecordingManager.finalReason(reason));
+		log.info("Container for session {} still being ready for new recordings", recording.getSessionId());
 
-        String containerId = this.sessionsContainers.get(recording.getSessionId());
+		String containerId = this.sessionsContainers.get(recording.getSessionId());
 
-        if (session == null) {
-            log.warn(
-                    "Existing recording {} does not have an active session associated. This usually means a custom recording"
-                            + " layout did not join a recorded participant or the recording has been automatically"
-                            + " stopped after last user left and timeout passed",
-                    recording.getId());
-        }
+		if (session == null) {
+			log.warn(
+					"Existing recording {} does not have an active session associated. This usually means a custom recording"
+							+ " layout did not join a recorded participant or the recording has been automatically"
+							+ " stopped after last user left and timeout passed",
+					recording.getId());
+		}
 
-        try {
-            dockerManager.runCommandInContainer(containerId, "./composed_quick_start.sh --stop-recording", 10);
-        } catch (InterruptedException e1) {
-            cleanRecordingMaps(recording);
-            log.error("Error stopping recording for session id: {}", session.getSessionId());
-            e1.printStackTrace();
-        }
+		try {
+			dockerManager.runCommandInContainer(containerId, "./composed_quick_start.sh --stop-recording", 10);
+		} catch (InterruptedException e1) {
+			cleanRecordingMaps(recording);
+			log.error("Error stopping recording for session id: {}", session.getSessionId());
+			e1.printStackTrace();
+		}
 
-        recording = updateRecordingAttributes(recording);
+		recording = updateRecordingAttributes(recording);
 
-        this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(), getMetadataFilePath(recording));
-        cleanRecordingMaps(recording);
+		this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(),
+				getMetadataFilePath(recording));
+		cleanRecordingMaps(recording);
 
-        final long timestamp = System.currentTimeMillis();
-        this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, recording.getStatus());
+		if (session != null && reason != null) {
+			this.recordingManager.sessionHandler.sendRecordingStoppedNotification(session, recording, reason);
+		}
 
-        if (session != null && reason != null) {
-            this.recordingManager.sessionHandler.sendRecordingStoppedNotification(session, recording, reason);
-        }
+		final Recording[] finalRecordingArray = new Recording[1];
+		finalRecordingArray[0] = recording;
+		this.uploadRecording(finalRecordingArray[0], reason);
 
-        // Decrement active recordings
-        // ((KurentoSession) session).getKms().getActiveRecordings().decrementAndGet();
+		// Decrement active recordings
+		// ((KurentoSession) session).getKms().getActiveRecordings().decrementAndGet();
 
-        return recording;
-    }
+		return recording;
+	}
 
-    public void runComposedQuickStartContainer(Session session) {
-        // Start recording container if output mode=COMPOSED_QUICK_START
-        Session recorderSession = session;
-        io.openvidu.java.client.Recording.OutputMode defaultOutputMode = recorderSession.getSessionProperties().defaultOutputMode();
-        if (io.openvidu.java.client.Recording.OutputMode.COMPOSED_QUICK_START.equals(defaultOutputMode)
-                && sessionsContainers.get(recorderSession.getSessionId()) == null) {
-            // Retry to run if container is launched for the same session quickly after close it
-            int secondsToRetry = 10;
-            int secondsBetweenRetries = 1;
-            int seconds = 0;
-            boolean launched = false;
-            while (!launched && seconds < secondsToRetry) {
-                try {
-                    log.info("Launching COMPOSED_QUICK_START recording container for session: {}", recorderSession.getSessionId());
-                    runContainer(recorderSession, new RecordingProperties.Builder().name("")
-                            .outputMode(recorderSession.getSessionProperties().defaultOutputMode())
-                            .recordingLayout(recorderSession.getSessionProperties().defaultRecordingLayout())
-                            .customLayout(recorderSession.getSessionProperties().defaultCustomLayout()).build());
-                    log.info("COMPOSED_QUICK_START recording container launched for session: {}", recorderSession.getSessionId());
-                    launched = true;
-                } catch (Exception e) {
-                    log.warn("Failed to launch COMPOSED_QUICK_START recording container for session {}. Trying again in {} seconds", recorderSession.getSessionId(), secondsBetweenRetries);
-                    try {
-                        Thread.sleep(secondsBetweenRetries * 1000);
-                    } catch (InterruptedException e2) {}
-                    seconds++;
-                } finally {
-                    if (seconds == secondsToRetry && !launched) {
-                        log.error("Error launchaing COMPOSED_QUICK_ªSTART recording container for session {}", recorderSession.getSessionId());
-                    }
-                }
-            }
-        }
-    }
+	public void runComposedQuickStartContainer(Session session) {
+		// Start recording container if output mode=COMPOSED_QUICK_START
+		Session recorderSession = session;
+		io.openvidu.java.client.Recording.OutputMode defaultOutputMode = recorderSession.getSessionProperties()
+				.defaultOutputMode();
+		if (io.openvidu.java.client.Recording.OutputMode.COMPOSED_QUICK_START.equals(defaultOutputMode)
+				&& sessionsContainers.get(recorderSession.getSessionId()) == null) {
+			// Retry to run if container is launched for the same session quickly after
+			// close it
+			int secondsToRetry = 10;
+			int secondsBetweenRetries = 1;
+			int seconds = 0;
+			boolean launched = false;
+			while (!launched && seconds < secondsToRetry) {
+				try {
+					log.info("Launching COMPOSED_QUICK_START recording container for session: {}",
+							recorderSession.getSessionId());
+					runContainer(recorderSession, new RecordingProperties.Builder().name("")
+							.outputMode(recorderSession.getSessionProperties().defaultOutputMode())
+							.recordingLayout(recorderSession.getSessionProperties().defaultRecordingLayout())
+							.customLayout(recorderSession.getSessionProperties().defaultCustomLayout()).build());
+					log.info("COMPOSED_QUICK_START recording container launched for session: {}",
+							recorderSession.getSessionId());
+					launched = true;
+				} catch (Exception e) {
+					log.warn(
+							"Failed to launch COMPOSED_QUICK_START recording container for session {}. Trying again in {} seconds",
+							recorderSession.getSessionId(), secondsBetweenRetries);
+					try {
+						Thread.sleep(secondsBetweenRetries * 1000);
+					} catch (InterruptedException e2) {
+					}
+					seconds++;
+				} finally {
+					if (seconds == secondsToRetry && !launched) {
+						log.error("Error launchaing COMPOSED_QUICK_ªSTART recording container for session {}",
+								recorderSession.getSessionId());
+					}
+				}
+			}
+		}
+	}
 
-    private String runContainer(Session session, RecordingProperties properties) throws Exception {
-        log.info("Starting COMPOSED_QUICK_START container for session id: {}", session.getSessionId());
+	private String runContainer(Session session, RecordingProperties properties) throws Exception {
+		log.info("Starting COMPOSED_QUICK_START container for session id: {}", session.getSessionId());
 
-        Recording recording = new Recording(session.getSessionId(), null, properties);
-        String layoutUrl = this.getLayoutUrl(recording);
+		Recording recording = new Recording(session.getSessionId(), null, properties);
+		String layoutUrl = this.getLayoutUrl(recording);
 
-        List envs = new ArrayList<>();
-        envs.add("DEBUG_MODE=" + openviduConfig.isOpenViduRecordingDebug());
-        envs.add("RECORDING_TYPE=COMPOSED_QUICK_START");
-        envs.add("RESOLUTION=" + properties.resolution());
-        envs.add("URL=" + layoutUrl);
+		List envs = new ArrayList<>();
+		envs.add("DEBUG_MODE=" + openviduConfig.isOpenViduRecordingDebug());
+		envs.add("RECORDING_TYPE=COMPOSED_QUICK_START");
+		envs.add("RESOLUTION=" + properties.resolution());
+		envs.add("URL=" + layoutUrl);
 
-        log.info("Recorder connecting to url {}", layoutUrl);
+		log.info("Recorder connecting to url {}", layoutUrl);
 
-        String containerId = null;
-        try {
-            final String container = RecordingManager.IMAGE_NAME + ":" + RecordingManager.IMAGE_TAG;
-            final String containerName = "recording_" + session.getSessionId();
-            Volume volume1 = new Volume("/recordings");
-            List volumes = new ArrayList<>();
-            volumes.add(volume1);
-            Bind bind1 = new Bind(openviduConfig.getOpenViduRecordingPath(), volume1);
-            List binds = new ArrayList<>();
-            binds.add(bind1);
-            containerId = dockerManager.runContainer(container, containerName, null, volumes, binds, "host", envs, null,
-                    properties.shmSize(), false, null);
-            containers.put(containerId, containerName);
-            this.sessionsContainers.put(session.getSessionId(), containerId);
-        } catch (Exception e) {
-            if (containerId != null) {
-                dockerManager.removeDockerContainer(containerId, true);
-                containers.remove(containerId);
-                sessionsContainers.remove(session.getSessionId());
-            }
-            log.error("Error while launchig container for COMPOSED_QUICK_START: ({})", e.getMessage());
-            throw e;
-        }
-        return containerId;
-    }
+		String containerId = null;
+		try {
+			final String container = RecordingManager.IMAGE_NAME + ":" + RecordingManager.IMAGE_TAG;
+			final String containerName = "recording_" + session.getSessionId();
+			Volume volume1 = new Volume("/recordings");
+			List volumes = new ArrayList<>();
+			volumes.add(volume1);
+			Bind bind1 = new Bind(openviduConfig.getOpenViduRecordingPath(), volume1);
+			List binds = new ArrayList<>();
+			binds.add(bind1);
+			containerId = dockerManager.runContainer(container, containerName, null, volumes, binds, "host", envs, null,
+					properties.shmSize(), false, null);
+			containers.put(containerId, containerName);
+			this.sessionsContainers.put(session.getSessionId(), containerId);
+		} catch (Exception e) {
+			if (containerId != null) {
+				dockerManager.removeDockerContainer(containerId, true);
+				containers.remove(containerId);
+				sessionsContainers.remove(session.getSessionId());
+			}
+			log.error("Error while launchig container for COMPOSED_QUICK_START: ({})", e.getMessage());
+			throw e;
+		}
+		return containerId;
+	}
 
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index 449c2a63..0ddf3581 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -56,6 +56,7 @@ import io.openvidu.server.recording.CompositeWrapper;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.RecordingDownloader;
 import io.openvidu.server.recording.RecordingInfoUtils;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.utils.DockerManager;
 import io.openvidu.server.utils.QuarantineKiller;
 
@@ -70,8 +71,9 @@ public class ComposedRecordingService extends RecordingService {
 	protected DockerManager dockerManager;
 
 	public ComposedRecordingService(RecordingManager recordingManager, RecordingDownloader recordingDownloader,
-			OpenviduConfig openviduConfig, CallDetailRecord cdr, QuarantineKiller quarantineKiller) {
-		super(recordingManager, recordingDownloader, openviduConfig, cdr, quarantineKiller);
+			RecordingUploader recordingUploader, OpenviduConfig openviduConfig, CallDetailRecord cdr,
+			QuarantineKiller quarantineKiller) {
+		super(recordingManager, recordingDownloader, recordingUploader, openviduConfig, cdr, quarantineKiller);
 		this.dockerManager = new DockerManager();
 	}
 
@@ -278,7 +280,9 @@ public class ComposedRecordingService extends RecordingService {
 							log.warn("Deleting unusable files for recording {}", recordingId);
 							if (HttpStatus.NO_CONTENT
 									.equals(this.recordingManager.deleteRecordingFromHost(recordingId, true))) {
-								log.warn("Files properly deleted");
+								log.warn("Files properly deleted for recording {}", recordingId);
+							} else {
+								log.warn("No files found for recording {}", recordingId);
 							}
 						}
 					}
@@ -300,13 +304,15 @@ public class ComposedRecordingService extends RecordingService {
 					getMetadataFilePath(recording));
 			cleanRecordingMaps(recording);
 
-			final long timestamp = System.currentTimeMillis();
-			this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, recording.getStatus());
-
 			if (session != null && reason != null) {
 				this.recordingManager.sessionHandler.sendRecordingStoppedNotification(session, recording, reason);
 			}
 
+			// Upload if necessary
+			final Recording[] finalRecordingArray = new Recording[1];
+			finalRecordingArray[0] = recording;
+			this.uploadRecording(finalRecordingArray[0], reason);
+
 			// Decrement active recordings
 			// ((KurentoSession) session).getKms().getActiveRecordings().decrementAndGet();
 		}
@@ -354,6 +360,7 @@ public class ComposedRecordingService extends RecordingService {
 		finalRecordingArray[0] = recording;
 		try {
 			this.recordingDownloader.downloadRecording(finalRecordingArray[0], null, () -> {
+
 				String filesPath = this.openviduConfig.getOpenViduRecordingPath() + finalRecordingArray[0].getId()
 						+ "/";
 				File videoFile = new File(filesPath + finalRecordingArray[0].getName() + ".webm");
@@ -364,16 +371,15 @@ public class ComposedRecordingService extends RecordingService {
 						finalDuration,
 						filesPath + RecordingManager.RECORDING_ENTITY_FILE + finalRecordingArray[0].getId());
 
-				final long timestamp = System.currentTimeMillis();
-				cdr.recordRecordingStatusChanged(finalRecordingArray[0], reason, timestamp,
-						finalRecordingArray[0].getStatus());
-
 				// Decrement active recordings once it is downloaded
 				((KurentoSession) session).getKms().getActiveRecordings().decrementAndGet();
 
 				// Now we can drop Media Node if waiting-idle-to-terminate
 				this.quarantineKiller.dropMediaNode(session.getMediaNodeId());
 
+				// Upload if necessary
+				this.uploadRecording(finalRecordingArray[0], reason);
+
 			});
 		} catch (IOException e) {
 			log.error("Error while downloading recording {}: {}", finalRecordingArray[0].getName(), e.getMessage());
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 57d41d1b..9d4dc50b 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
@@ -72,6 +72,7 @@ import io.openvidu.server.kurento.kms.Kms;
 import io.openvidu.server.kurento.kms.KmsManager;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.RecordingDownloader;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.utils.CustomFileManager;
 import io.openvidu.server.utils.DockerManager;
 import io.openvidu.server.utils.JsonUtils;
@@ -93,9 +94,15 @@ public class RecordingManager {
 	@Autowired
 	private SessionManager sessionManager;
 
+	@Autowired
+	protected RecordingManagerUtils recordingManagerUtils;
+
 	@Autowired
 	private RecordingDownloader recordingDownloader;
 
+	@Autowired
+	private RecordingUploader recordingUploader;
+
 	@Autowired
 	protected OpenviduConfig openviduConfig;
 
@@ -119,7 +126,7 @@ public class RecordingManager {
 	private ScheduledThreadPoolExecutor automaticRecordingStopExecutor = new ScheduledThreadPoolExecutor(
 			Runtime.getRuntime().availableProcessors());
 
-	static final String RECORDING_ENTITY_FILE = ".recording.";
+	public static final String RECORDING_ENTITY_FILE = ".recording.";
 	public static final String IMAGE_NAME = "openvidu/openvidu-recording";
 	static String IMAGE_TAG;
 
@@ -159,12 +166,12 @@ public class RecordingManager {
 		RecordingManager.IMAGE_TAG = openviduConfig.getOpenViduRecordingVersion();
 
 		this.dockerManager = new DockerManager();
-		this.composedRecordingService = new ComposedRecordingService(this, recordingDownloader, openviduConfig, cdr,
-				quarantineKiller);
-		this.composedQuickStartRecordingService = new ComposedQuickStartRecordingService(this, recordingDownloader,
+		this.composedRecordingService = new ComposedRecordingService(this, recordingDownloader, recordingUploader,
 				openviduConfig, cdr, quarantineKiller);
-		this.singleStreamRecordingService = new SingleStreamRecordingService(this, recordingDownloader, openviduConfig,
-				cdr, quarantineKiller);
+		this.composedQuickStartRecordingService = new ComposedQuickStartRecordingService(this, recordingDownloader,
+				recordingUploader, openviduConfig, cdr, quarantineKiller);
+		this.singleStreamRecordingService = new SingleStreamRecordingService(this, recordingDownloader,
+				recordingUploader, openviduConfig, cdr, quarantineKiller);
 
 		log.info("Recording module required: Downloading openvidu/openvidu-recording:"
 				+ openviduConfig.getOpenViduRecordingVersion() + " Docker image (350MB aprox)");
@@ -432,64 +439,105 @@ public class RecordingManager {
 	}
 
 	public Collection getFinishedRecordings() {
-		return this.getAllRecordingsFromHost().stream().filter(recording -> recording.getStatus().equals(Status.ready))
-				.collect(Collectors.toSet());
+		return recordingManagerUtils.getAllRecordingsFromStorage().stream()
+				.filter(recording -> recording.getStatus().equals(Status.ready)).collect(Collectors.toSet());
 	}
 
 	public Recording getRecording(String recordingId) {
-		return this.getRecordingFromHost(recordingId);
+		return recordingManagerUtils.getRecordingFromStorage(recordingId);
 	}
 
 	public Collection getAllRecordings() {
-		return this.getAllRecordingsFromHost();
+		return recordingManagerUtils.getAllRecordingsFromStorage();
 	}
 
 	public String getFreeRecordingId(String sessionId) {
-		Set recordingIds = this.getRecordingIdsFromHost();
-		String recordingId = sessionId;
-		boolean isPresent = recordingIds.contains(recordingId);
-		int i = 1;
-		while (isPresent) {
-			recordingId = sessionId + "-" + i;
-			i++;
-			isPresent = recordingIds.contains(recordingId);
-		}
-		return recordingId;
+		return recordingManagerUtils.getFreeRecordingId(sessionId);
 	}
 
 	public HttpStatus deleteRecordingFromHost(String recordingId, boolean force) {
 
-		if (!force && (this.startedRecordings.containsKey(recordingId)
-				|| this.startingRecordings.containsKey(recordingId))) {
-			// Cannot delete an active recording
-			return HttpStatus.CONFLICT;
+		if (this.startedRecordings.containsKey(recordingId) || this.startingRecordings.containsKey(recordingId)) {
+			if (!force) {
+				// Cannot delete an active recording
+				return HttpStatus.CONFLICT;
+			}
 		}
 
-		Recording recording = getRecordingFromHost(recordingId);
+		Recording recording = recordingManagerUtils.getRecordingFromStorage(recordingId);
 		if (recording == null) {
 			return HttpStatus.NOT_FOUND;
 		}
 		if (Status.stopped.equals(recording.getStatus())) {
-			// Recording is being downloaded from remote host
-			log.warn("Cancelling ongoing download process of recording {}", recording.getId());
+			// Recording is being downloaded from remote host or being uploaded
+			log.warn("Recording {} status is \"stopped\". Cancelling possible ongoing download process", recording.getId());
 			this.recordingDownloader.cancelDownload(recording.getId());
 		}
 
-		File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
+		return recordingManagerUtils.deleteRecordingFromStorage(recordingId);
+	}
+
+	public Set getAllRecordingIdsFromLocalStorage() {
+		File folder = new File(openviduConfig.getOpenViduRecordingPath());
+		File[] files = folder.listFiles();
+
+		Set fileNamesNoExtension = new HashSet<>();
+		for (int i = 0; i < files.length; i++) {
+			if (files[i].isDirectory()) {
+				File[] innerFiles = files[i].listFiles();
+				for (int j = 0; j < innerFiles.length; j++) {
+					if (innerFiles[j].isFile()
+							&& innerFiles[j].getName().startsWith(RecordingManager.RECORDING_ENTITY_FILE)) {
+						fileNamesNoExtension
+								.add(innerFiles[j].getName().replaceFirst(RecordingManager.RECORDING_ENTITY_FILE, ""));
+						break;
+					}
+				}
+			}
+		}
+		return fileNamesNoExtension;
+	}
+
+	public HttpStatus deleteRecordingFromLocalStorage(String recordingId) {
+		File folder = new File(openviduConfig.getOpenViduRecordingPath());
 		File[] files = folder.listFiles();
 		for (int i = 0; i < files.length; i++) {
 			if (files[i].isDirectory() && files[i].getName().equals(recordingId)) {
 				// Correct folder. Delete it
 				try {
 					FileUtils.deleteDirectory(files[i]);
+					return HttpStatus.NO_CONTENT;
 				} catch (IOException e) {
 					log.error("Couldn't delete folder {}", files[i].getAbsolutePath());
+					return HttpStatus.INTERNAL_SERVER_ERROR;
 				}
-				break;
 			}
 		}
+		return HttpStatus.NOT_FOUND;
+	}
 
-		return HttpStatus.NO_CONTENT;
+	public File getRecordingEntityFileFromLocalStorage(String recordingId) {
+		String metadataFilePath = openviduConfig.getOpenViduRecordingPath() + recordingId + "/"
+				+ RecordingManager.RECORDING_ENTITY_FILE + recordingId;
+		return new File(metadataFilePath);
+	}
+
+	public Set getAllRecordingsFromLocalStorage() {
+		File folder = new File(openviduConfig.getOpenViduRecordingPath());
+		File[] files = folder.listFiles();
+		Set recordingEntities = new HashSet<>();
+		for (int i = 0; i < files.length; i++) {
+			if (files[i].isDirectory()) {
+				File[] innerFiles = files[i].listFiles();
+				for (int j = 0; j < innerFiles.length; j++) {
+					Recording recording = getRecordingFromEntityFile(innerFiles[j]);
+					if (recording != null) {
+						recordingEntities.add(recording);
+					}
+				}
+			}
+		}
+		return recordingEntities;
 	}
 
 	public Recording getRecordingFromEntityFile(File file) {
@@ -501,28 +549,27 @@ public class RecordingManager {
 				log.error("Error reading recording entity file {}: {}", file.getAbsolutePath(), (e.getMessage()));
 				return null;
 			}
-			Recording recording = new Recording(json);
-			if (Status.ready.equals(recording.getStatus()) || Status.failed.equals(recording.getStatus())) {
-				recording.setUrl(getRecordingUrl(recording));
-			}
-			return recording;
+			return getRecordingFromJson(json);
 		}
 		return null;
 	}
 
-	public String getRecordingUrl(Recording recording) {
-		return openviduConfig.getFinalUrl() + "recordings/" + recording.getId() + "/" + recording.getName() + "."
-				+ this.getExtensionFromRecording(recording);
+	public Recording getRecordingFromJson(JsonObject json) {
+		Recording recording = new Recording(json);
+		if (Status.ready.equals(recording.getStatus())
+				&& composedQuickStartRecordingService.isBeingUploaded(recording)) {
+			// Recording has finished but is being uploaded
+			recording.setStatus(Status.stopped);
+			recording.setUrl(null);
+		} else if (Status.ready.equals(recording.getStatus()) || Status.failed.equals(recording.getStatus())) {
+			// Recording has been completely processed and must include URL
+			recording.setUrl(recordingManagerUtils.getRecordingUrl(recording));
+		}
+		return recording;
 	}
 
-	private String getExtensionFromRecording(Recording recording) {
-		if (OutputMode.INDIVIDUAL.equals(recording.getOutputMode())) {
-			return "zip";
-		} else if (recording.hasVideo()) {
-			return "mp4";
-		} else {
-			return "webm";
-		}
+	public String getRecordingUrl(Recording recording) {
+		return recordingManagerUtils.getRecordingUrl(recording);
 	}
 
 	public void initAutomaticRecordingStopThread(final Session session) {
@@ -623,56 +670,6 @@ public class RecordingManager {
 		}
 	}
 
-	private Recording getRecordingFromHost(String recordingId) {
-		log.info(this.openviduConfig.getOpenViduRecordingPath() + recordingId + "/"
-				+ RecordingManager.RECORDING_ENTITY_FILE + recordingId);
-		File file = new File(this.openviduConfig.getOpenViduRecordingPath() + recordingId + "/"
-				+ RecordingManager.RECORDING_ENTITY_FILE + recordingId);
-		log.info("File exists: " + file.exists());
-		Recording recording = this.getRecordingFromEntityFile(file);
-		return recording;
-	}
-
-	private Set getAllRecordingsFromHost() {
-		File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
-		File[] files = folder.listFiles();
-
-		Set recordingEntities = new HashSet<>();
-		for (int i = 0; i < files.length; i++) {
-			if (files[i].isDirectory()) {
-				File[] innerFiles = files[i].listFiles();
-				for (int j = 0; j < innerFiles.length; j++) {
-					Recording recording = this.getRecordingFromEntityFile(innerFiles[j]);
-					if (recording != null) {
-						recordingEntities.add(recording);
-					}
-				}
-			}
-		}
-		return recordingEntities;
-	}
-
-	private Set getRecordingIdsFromHost() {
-		File folder = new File(this.openviduConfig.getOpenViduRecordingPath());
-		File[] files = folder.listFiles();
-
-		Set fileNamesNoExtension = new HashSet<>();
-		for (int i = 0; i < files.length; i++) {
-			if (files[i].isDirectory()) {
-				File[] innerFiles = files[i].listFiles();
-				for (int j = 0; j < innerFiles.length; j++) {
-					if (innerFiles[j].isFile()
-							&& innerFiles[j].getName().startsWith(RecordingManager.RECORDING_ENTITY_FILE)) {
-						fileNamesNoExtension
-								.add(innerFiles[j].getName().replaceFirst(RecordingManager.RECORDING_ENTITY_FILE, ""));
-						break;
-					}
-				}
-			}
-		}
-		return fileNamesNoExtension;
-	}
-
 	private void checkRecordingPaths(String openviduRecordingPath, String openviduRecordingCustomLayout)
 			throws OpenViduException {
 		log.info("Initializing recording paths");
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtils.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtils.java
new file mode 100644
index 00000000..b2eaa7cb
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtils.java
@@ -0,0 +1,61 @@
+package io.openvidu.server.recording.service;
+
+import java.util.Set;
+
+import org.springframework.http.HttpStatus;
+
+import io.openvidu.java.client.Recording.OutputMode;
+import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.recording.Recording;
+import io.openvidu.server.utils.JsonUtils;
+
+public abstract class RecordingManagerUtils {
+
+	protected OpenviduConfig openviduConfig;
+	protected RecordingManager recordingManager;
+
+	protected JsonUtils jsonUtils = new JsonUtils();
+
+	public RecordingManagerUtils(OpenviduConfig openviduConfig, RecordingManager recordingManager) {
+		this.openviduConfig = openviduConfig;
+		this.recordingManager = recordingManager;
+	}
+
+	public abstract Recording getRecordingFromStorage(String recordingId);
+
+	public abstract Set getAllRecordingsFromStorage();
+
+	public abstract HttpStatus deleteRecordingFromStorage(String recordingId);
+
+	protected abstract String getRecordingUrl(Recording recording);
+
+	protected abstract Set getAllRecordingIdsFromStorage();
+
+	protected String getExtensionFromRecording(Recording recording) {
+		if (OutputMode.INDIVIDUAL.equals(recording.getOutputMode())) {
+			return "zip";
+		} else if (recording.hasVideo()) {
+			return "mp4";
+		} else {
+			return "webm";
+		}
+	}
+
+	public String getFreeRecordingId(String sessionId) {
+		Set recordingIds = getAllRecordingIdsFromStorage();
+		return getNextAvailableRecordingId(sessionId, recordingIds);
+	}
+
+	private String getNextAvailableRecordingId(String baseRecordingId, Set existingRecordingIds) {
+		String recordingId = baseRecordingId;
+		boolean isPresent = existingRecordingIds.contains(recordingId);
+		int i = 1;
+		while (isPresent) {
+			recordingId = baseRecordingId + "-" + i;
+			i++;
+			isPresent = existingRecordingIds.contains(recordingId);
+		}
+		return recordingId;
+	}
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java
new file mode 100644
index 00000000..e69f10e2
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java
@@ -0,0 +1,62 @@
+package io.openvidu.server.recording.service;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.http.HttpStatus;
+
+import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.recording.Recording;
+
+public class RecordingManagerUtilsLocalStorage extends RecordingManagerUtils {
+
+	public RecordingManagerUtilsLocalStorage(OpenviduConfig openviduConfig, RecordingManager recordingManager) {
+		super(openviduConfig, recordingManager);
+	}
+
+	@Override
+	public Recording getRecordingFromStorage(String recordingId) {
+		File file = recordingManager.getRecordingEntityFileFromLocalStorage(recordingId);
+		return recordingManager.getRecordingFromEntityFile(file);
+	}
+
+	@Override
+	public Set getAllRecordingsFromStorage() {
+		return recordingManager.getAllRecordingsFromLocalStorage();
+	}
+
+	@Override
+	public HttpStatus deleteRecordingFromStorage(String recordingId) {
+		return recordingManager.deleteRecordingFromLocalStorage(recordingId);
+	}
+
+	@Override
+	public String getRecordingUrl(Recording recording) {
+		return openviduConfig.getFinalUrl() + "recordings/" + recording.getId() + "/" + recording.getName() + "."
+				+ this.getExtensionFromRecording(recording);
+	}
+
+	@Override
+	protected Set getAllRecordingIdsFromStorage() {
+		File folder = new File(openviduConfig.getOpenViduRecordingPath());
+		File[] files = folder.listFiles();
+
+		Set fileNamesNoExtension = new HashSet<>();
+		for (int i = 0; i < files.length; i++) {
+			if (files[i].isDirectory()) {
+				File[] innerFiles = files[i].listFiles();
+				for (int j = 0; j < innerFiles.length; j++) {
+					if (innerFiles[j].isFile()
+							&& innerFiles[j].getName().startsWith(RecordingManager.RECORDING_ENTITY_FILE)) {
+						fileNamesNoExtension
+								.add(innerFiles[j].getName().replaceFirst(RecordingManager.RECORDING_ENTITY_FILE, ""));
+						break;
+					}
+				}
+			}
+		}
+		return fileNamesNoExtension;
+	}
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java
index 385899e3..f47aba83 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingService.java
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
 
 import io.openvidu.client.OpenViduException;
 import io.openvidu.client.OpenViduException.Code;
+import io.openvidu.java.client.Recording.Status;
 import io.openvidu.java.client.RecordingLayout;
 import io.openvidu.java.client.RecordingProperties;
 import io.openvidu.server.cdr.CallDetailRecord;
@@ -32,6 +33,7 @@ import io.openvidu.server.core.EndReason;
 import io.openvidu.server.core.Session;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.RecordingDownloader;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.utils.CommandExecutor;
 import io.openvidu.server.utils.CustomFileManager;
 import io.openvidu.server.utils.QuarantineKiller;
@@ -44,14 +46,17 @@ public abstract class RecordingService {
 	protected OpenviduConfig openviduConfig;
 	protected RecordingManager recordingManager;
 	protected RecordingDownloader recordingDownloader;
+	protected RecordingUploader recordingUploader;
 	protected CallDetailRecord cdr;
 	protected QuarantineKiller quarantineKiller;
 	protected CustomFileManager fileWriter = new CustomFileManager();
 
 	RecordingService(RecordingManager recordingManager, RecordingDownloader recordingDownloader,
-			OpenviduConfig openviduConfig, CallDetailRecord cdr, QuarantineKiller quarantineKiller) {
+			RecordingUploader recordingUploader, OpenviduConfig openviduConfig, CallDetailRecord cdr,
+			QuarantineKiller quarantineKiller) {
 		this.recordingManager = recordingManager;
 		this.recordingDownloader = recordingDownloader;
+		this.recordingUploader = recordingUploader;
 		this.openviduConfig = openviduConfig;
 		this.cdr = cdr;
 		this.quarantineKiller = quarantineKiller;
@@ -105,9 +110,14 @@ public abstract class RecordingService {
 	 */
 	protected Recording sealRecordingMetadataFileAsReady(Recording recording, long size, double duration,
 			String metadataFilePath) {
-		io.openvidu.java.client.Recording.Status status = io.openvidu.java.client.Recording.Status.failed
-				.equals(recording.getStatus()) ? io.openvidu.java.client.Recording.Status.failed
-						: io.openvidu.java.client.Recording.Status.ready;
+		Status status = Status.failed.equals(recording.getStatus()) ? Status.failed : Status.ready;
+
+		if (Status.ready.equals(status)) {
+			// Prevent uploading recordings from being retrieved from REST API with "ready"
+			// status. This will force their status back to "stopped" on GET until upload
+			// process has finished
+			storeAsUploadingRecording(recording);
+		}
 
 		// Status is now failed or ready. Url property must be defined
 		recording.setUrl(recordingManager.getRecordingUrl(recording));
@@ -195,6 +205,25 @@ public abstract class RecordingService {
 		return folderPath + RecordingManager.RECORDING_ENTITY_FILE + recording.getId();
 	}
 
+	protected void uploadRecording(final Recording recording, EndReason reason) {
+		recordingUploader.uploadRecording(recording, () -> {
+			final long timestamp = System.currentTimeMillis();
+			cdr.recordRecordingStatusChanged(recording, reason, timestamp, recording.getStatus());
+		}, () -> {
+			final long timestamp = System.currentTimeMillis();
+			cdr.recordRecordingStatusChanged(recording, reason, timestamp,
+					io.openvidu.java.client.Recording.Status.failed);
+		});
+	}
+
+	protected void storeAsUploadingRecording(Recording recording) {
+		recordingUploader.storeAsUploadingRecording(recording.getId());
+	}
+
+	protected boolean isBeingUploaded(Recording recording) {
+		return recordingUploader.isBeingUploaded(recording.getId());
+	}
+
 	/**
 	 * Simple wrapper for returning update RecordingProperties and a free
 	 * recordingId when starting a new recording
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
index 404ca521..27c7e61f 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
@@ -64,6 +64,7 @@ import io.openvidu.server.kurento.endpoint.PublisherEndpoint;
 import io.openvidu.server.recording.RecorderEndpointWrapper;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.RecordingDownloader;
+import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.utils.QuarantineKiller;
 
 public class SingleStreamRecordingService extends RecordingService {
@@ -76,8 +77,9 @@ public class SingleStreamRecordingService extends RecordingService {
 	private final String INDIVIDUAL_STREAM_METADATA_FILE = ".stream.";
 
 	public SingleStreamRecordingService(RecordingManager recordingManager, RecordingDownloader recordingDownloader,
-			OpenviduConfig openviduConfig, CallDetailRecord cdr, QuarantineKiller quarantineKiller) {
-		super(recordingManager, recordingDownloader, openviduConfig, cdr, quarantineKiller);
+			RecordingUploader recordingUploader, OpenviduConfig openviduConfig, CallDetailRecord cdr,
+			QuarantineKiller quarantineKiller) {
+		super(recordingManager, recordingDownloader, recordingUploader, openviduConfig, cdr, quarantineKiller);
 	}
 
 	@Override
@@ -179,10 +181,6 @@ public class SingleStreamRecordingService extends RecordingService {
 				}
 				finalRecordingArray[0] = this.sealMetadataFiles(finalRecordingArray[0]);
 
-				final long timestamp = System.currentTimeMillis();
-				cdr.recordRecordingStatusChanged(finalRecordingArray[0], reason, timestamp,
-						finalRecordingArray[0].getStatus());
-
 				cleanRecordingWrappers(finalRecordingArray[0].getSessionId());
 
 				// Decrement active recordings once it is downloaded
@@ -191,6 +189,9 @@ public class SingleStreamRecordingService extends RecordingService {
 				// Now we can drop Media Node if waiting-idle-to-terminate
 				this.quarantineKiller.dropMediaNode(session.getMediaNodeId());
 
+				// Upload if necessary
+				this.uploadRecording(finalRecordingArray[0], reason);
+
 			});
 		} catch (IOException e) {
 			log.error("Error while downloading recording {}", finalRecordingArray[0].getName());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/JsonUtils.java b/openvidu-server/src/main/java/io/openvidu/server/utils/JsonUtils.java
index 7e0468a3..24242d3b 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/utils/JsonUtils.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/utils/JsonUtils.java
@@ -20,6 +20,7 @@ package io.openvidu.server.utils;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.Reader;
 import java.util.Map.Entry;
 
 import org.kurento.jsonrpc.Props;
@@ -56,13 +57,15 @@ public class JsonUtils {
 
 	public JsonElement fromFileToJsonElement(String filePath)
 			throws IOException, FileNotFoundException, JsonParseException, IllegalStateException {
+		return fromReaderToJsonElement(new FileReader(filePath));
+	}
+
+	public JsonObject fromReaderToJsonObject(Reader reader) throws IOException {
+		return this.fromReaderToJsonElement(reader).getAsJsonObject();
+	}
+
+	public JsonElement fromReaderToJsonElement(Reader reader) throws IOException {
 		JsonElement json = null;
-		FileReader reader = null;
-		try {
-			reader = new FileReader(filePath);
-		} catch (FileNotFoundException e) {
-			throw e;
-		}
 		try {
 			json = JsonParser.parseReader(reader);
 		} catch (JsonParseException | IllegalStateException exception) {

From 207acdd2b6ca74b071ac525487097b8cdfa6ee0d Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 18 Sep 2020 12:37:13 +0200
Subject: [PATCH 025/435] openvidu-server: use recordingId instead of sessionId
 for managing single stream recorders (NullPointer fix)

---
 .../recording/service/RecordingManager.java   |  2 +-
 .../service/SingleStreamRecordingService.java | 48 +++++++++----------
 2 files changed, 25 insertions(+), 25 deletions(-)

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 9d4dc50b..4f9ca237 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
@@ -407,7 +407,7 @@ public class RecordingManager {
 			log.info("Stopping RecorderEndpoint in session {} for stream of participant {}", session.getSessionId(),
 					streamId);
 			final CountDownLatch stoppedCountDown = new CountDownLatch(1);
-			this.singleStreamRecordingService.stopRecorderEndpointOfPublisherEndpoint(session.getSessionId(), streamId,
+			this.singleStreamRecordingService.stopRecorderEndpointOfPublisherEndpoint(recording.getId(), streamId,
 					stoppedCountDown, kmsDisconnectionTime);
 			try {
 				if (!stoppedCountDown.await(5, TimeUnit.SECONDS)) {
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
index 27c7e61f..170ef9a7 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
@@ -97,8 +97,8 @@ public class SingleStreamRecordingService extends RecordingService {
 		Recording recording = new Recording(session.getSessionId(), recordingId, properties);
 		this.recordingManager.recordingToStarting(recording);
 
-		activeRecorders.put(session.getSessionId(), new ConcurrentHashMap());
-		storedRecorders.put(session.getSessionId(), new ConcurrentHashMap());
+		activeRecorders.put(recording.getId(), new ConcurrentHashMap());
+		storedRecorders.put(recording.getId(), new ConcurrentHashMap());
 
 		final int activePublishers = session.getActivePublishers();
 		final CountDownLatch recordingStartedCountdown = new CountDownLatch(activePublishers);
@@ -149,13 +149,12 @@ public class SingleStreamRecordingService extends RecordingService {
 				recording.hasVideo() ? (recording.hasAudio() ? "video+audio" : "video-only") : "audioOnly",
 				recording.getId(), recording.getSessionId(), reason);
 
-		final HashMap wrappers = new HashMap<>(
-				storedRecorders.get(recording.getSessionId()));
+		final HashMap wrappers = new HashMap<>(storedRecorders.get(recording.getId()));
 		final CountDownLatch stoppedCountDown = new CountDownLatch(wrappers.size());
 
 		for (RecorderEndpointWrapper wrapper : wrappers.values()) {
-			this.stopRecorderEndpointOfPublisherEndpoint(recording.getSessionId(), wrapper.getStreamId(),
-					stoppedCountDown, kmsDisconnectionTime);
+			this.stopRecorderEndpointOfPublisherEndpoint(recording.getId(), wrapper.getStreamId(), stoppedCountDown,
+					kmsDisconnectionTime);
 		}
 		try {
 			if (!stoppedCountDown.await(5, TimeUnit.SECONDS)) {
@@ -181,7 +180,7 @@ public class SingleStreamRecordingService extends RecordingService {
 				}
 				finalRecordingArray[0] = this.sealMetadataFiles(finalRecordingArray[0]);
 
-				cleanRecordingWrappers(finalRecordingArray[0].getSessionId());
+				cleanRecordingWrappers(finalRecordingArray[0]);
 
 				// Decrement active recordings once it is downloaded
 				((KurentoSession) session).getKms().getActiveRecordings().decrementAndGet();
@@ -195,7 +194,7 @@ public class SingleStreamRecordingService extends RecordingService {
 			});
 		} catch (IOException e) {
 			log.error("Error while downloading recording {}", finalRecordingArray[0].getName());
-			cleanRecordingWrappers(finalRecordingArray[0].getSessionId());
+			cleanRecordingWrappers(finalRecordingArray[0]);
 		}
 
 		if (reason != null && session != null) {
@@ -215,8 +214,7 @@ public class SingleStreamRecordingService extends RecordingService {
 		try {
 			if (participant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) {
 				try {
-					if (this.activeRecorders.get(session.getSessionId())
-							.containsKey(participant.getPublisherStreamId())) {
+					if (this.activeRecorders.get(recordingId).containsKey(participant.getPublisherStreamId())) {
 						log.warn("Concurrent initialization of RecorderEndpoint for stream {} of session {}. Returning",
 								participant.getPublisherStreamId(), session.getSessionId());
 						return;
@@ -254,10 +252,12 @@ public class SingleStreamRecordingService extends RecordingService {
 							"file://" + openviduConfig.getOpenViduRemoteRecordingPath() + recordingId + "/"
 									+ participant.getPublisherStreamId() + ".webm").withMediaProfile(profile).build();
 
+					final String finalRecordingId = recordingId;
+
 					recorder.addRecordingListener(new EventListener() {
 						@Override
 						public void onEvent(RecordingEvent event) {
-							activeRecorders.get(session.getSessionId()).get(participant.getPublisherStreamId())
+							activeRecorders.get(finalRecordingId).get(participant.getPublisherStreamId())
 									.setStartTime(Long.parseLong(event.getTimestampMillis()));
 							log.info("Recording started event for stream {}", participant.getPublisherStreamId());
 							globalStartLatch.countDown();
@@ -278,8 +278,8 @@ public class SingleStreamRecordingService extends RecordingService {
 							kurentoParticipant.getPublisher().getMediaOptions().hasVideo(),
 							kurentoParticipant.getPublisher().getMediaOptions().getTypeOfVideo());
 
-					activeRecorders.get(session.getSessionId()).put(participant.getPublisherStreamId(), wrapper);
-					storedRecorders.get(session.getSessionId()).put(participant.getPublisherStreamId(), wrapper);
+					activeRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper);
+					storedRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper);
 
 					connectAccordingToProfile(kurentoParticipant.getPublisher(), recorder, profile);
 					wrapper.getRecorder().record();
@@ -299,10 +299,10 @@ public class SingleStreamRecordingService extends RecordingService {
 		}
 	}
 
-	public void stopRecorderEndpointOfPublisherEndpoint(String sessionId, String streamId,
+	public void stopRecorderEndpointOfPublisherEndpoint(String recordingId, String streamId,
 			CountDownLatch globalStopLatch, Long kmsDisconnectionTime) {
-		log.info("Stopping single stream recorder for stream {} in session {}", streamId, sessionId);
-		final RecorderEndpointWrapper finalWrapper = activeRecorders.get(sessionId).remove(streamId);
+		log.info("Stopping single stream recorder for stream {} in recording {}", streamId, recordingId);
+		final RecorderEndpointWrapper finalWrapper = activeRecorders.get(recordingId).remove(streamId);
 		if (finalWrapper != null && kmsDisconnectionTime == 0) {
 			finalWrapper.getRecorder().addStoppedListener(new EventListener() {
 				@Override
@@ -320,13 +320,13 @@ public class SingleStreamRecordingService extends RecordingService {
 				// Stopping recorder endpoint because of a KMS disconnection
 				finalWrapper.setEndTime(kmsDisconnectionTime);
 				generateIndividualMetadataFile(finalWrapper);
-				log.warn("Forcing individual recording stop after KMS restart for stream {} in session {}", streamId,
-						sessionId);
+				log.warn("Forcing individual recording stop after KMS restart for stream {} in recording {}", streamId,
+						recordingId);
 			} else {
-				if (storedRecorders.get(sessionId).containsKey(streamId)) {
-					log.info("Stream {} recording of session {} was already stopped", streamId, sessionId);
+				if (storedRecorders.get(recordingId).containsKey(streamId)) {
+					log.info("Stream {} recording of recording {} was already stopped", streamId, recordingId);
 				} else {
-					log.error("Stream {} wasn't being recorded in session {}", streamId, sessionId);
+					log.error("Stream {} wasn't being recorded in recording {}", streamId, recordingId);
 				}
 			}
 			globalStopLatch.countDown();
@@ -539,9 +539,9 @@ public class SingleStreamRecordingService extends RecordingService {
 		}
 	}
 
-	private void cleanRecordingWrappers(String sessionId) {
-		this.storedRecorders.remove(sessionId);
-		this.activeRecorders.remove(sessionId);
+	private void cleanRecordingWrappers(Recording recording) {
+		this.storedRecorders.remove(recording.getId());
+		this.activeRecorders.remove(recording.getId());
 	}
 
 }

From 23e965f9f461264bd7a54ad29d30cfbf2988d93b Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 18 Sep 2020 15:00:59 +0200
Subject: [PATCH 026/435] openvidu-server: networkCache minor refactoring

---
 .../io/openvidu/server/rest/SessionRestController.java     | 7 +------
 .../java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java  | 6 +++---
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index f825b384..7ef11811 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -763,7 +763,6 @@ public class SessionRestController {
 		String rtspUri;
 		Boolean adaptativeBitrate;
 		Boolean onlyPlayWithSubscribers;
-		String networkCacheStr;
 		Integer networkCache;
 		String data;
 		try {
@@ -771,11 +770,7 @@ public class SessionRestController {
 			rtspUri = (String) params.get("rtspUri");
 			adaptativeBitrate = (Boolean) params.get("adaptativeBitrate");
 			onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers");
-			networkCacheStr = (String) params.get("networkCache");
-			if (networkCacheStr != null) 
-				networkCache = Integer.parseInt(networkCacheStr);
-			else
-				networkCache = null;
+			networkCache = (Integer) params.get("networkCache");
 			data = (String) params.get("data");
 		} catch (ClassCastException e) {
 			return this.generateErrorResponse("Type error in some parameter",
diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index d114b130..5f9986c1 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -3088,7 +3088,7 @@ public class OpenViduTestAppE2eTest {
 					HttpStatus.SC_BAD_REQUEST);
 
 			// Publish IP camera. Dummy URL because no user will subscribe to it [200]
-			String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'data':'MY_IP_CAMERA'}";
+			String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}";
 			JsonObject response = restClient.rest(HttpMethod.POST, "/api/sessions/IP_CAM_SESSION/connection", ipCamBody,
 					HttpStatus.SC_OK, true,
 					"{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}");
@@ -3108,7 +3108,7 @@ public class OpenViduTestAppE2eTest {
 			Assert.assertEquals("Wrong rtspUri property", "rtsp://dummyurl.com",
 					ipCamPublisher.get("rtspUri").getAsString());
 			JsonObject mediaOptions = ipCamPublisher.get("mediaOptions").getAsJsonObject();
-			Assert.assertEquals("Wrong number of properties in MediaOptions", 10, mediaOptions.size());
+			Assert.assertEquals("Wrong number of properties in MediaOptions", 11, mediaOptions.size());
 			Assert.assertTrue("Wrong adaptativeBitrate property", mediaOptions.get("adaptativeBitrate").getAsBoolean());
 			Assert.assertTrue("Wrong onlyPlayWithSubscribers property",
 					mediaOptions.get("onlyPlayWithSubscribers").getAsBoolean());
@@ -3185,7 +3185,7 @@ public class OpenViduTestAppE2eTest {
 			recPath = recPath.endsWith("/") ? recPath : (recPath + "/");
 			String fullRecordingPath = "file://" + recPath + "TestSession/audioVideo.mp4";
 			ipCamBody = "{'type':'IPCAM','rtspUri':'" + fullRecordingPath
-					+ "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'data':'MY_IP_CAMERA'}";
+					+ "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}";
 
 			restClient.rest(HttpMethod.POST, "/api/sessions/TestSession/connection", ipCamBody, HttpStatus.SC_OK, true,
 					"{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}");

From 70831114fed8bae90b941de38e969cc525fd3ce4 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 18 Sep 2020 15:04:15 +0200
Subject: [PATCH 027/435] openvidu-server: refactor single stream recorder

---
 .../kurento/core/KurentoParticipant.java      |  2 +-
 .../recording/service/RecordingManager.java   | 21 ++++++++---
 .../service/SingleStreamRecordingService.java | 35 +++----------------
 3 files changed, 21 insertions(+), 37 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java
index 05c795b3..0e24020b 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java
@@ -183,7 +183,7 @@ public class KurentoParticipant extends Participant {
 
 		if (this.openviduConfig.isRecordingModuleEnabled()
 				&& this.recordingManager.sessionIsBeingRecorded(session.getSessionId())) {
-			this.recordingManager.startOneIndividualStreamRecording(session, null, null, this);
+			this.recordingManager.startOneIndividualStreamRecording(session, this);
 		}
 
 		if (!silent) {
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 4f9ca237..d1548af7 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
@@ -370,8 +370,7 @@ public class RecordingManager {
 		return recording;
 	}
 
-	public void startOneIndividualStreamRecording(Session session, String recordingId, MediaProfileSpecType profile,
-			Participant participant) {
+	public void startOneIndividualStreamRecording(Session session, Participant participant) {
 		Recording recording = this.sessionsRecordings.get(session.getSessionId());
 		if (recording == null) {
 			recording = this.sessionsRecordingsStarting.get(session.getSessionId());
@@ -386,13 +385,24 @@ public class RecordingManager {
 			log.info("Starting new RecorderEndpoint in session {} for new stream of participant {}",
 					session.getSessionId(), participant.getParticipantPublicId());
 			final CountDownLatch startedCountDown = new CountDownLatch(1);
-			this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(session, recordingId, profile,
+
+			MediaProfileSpecType profile = null;
+			try {
+				profile = this.singleStreamRecordingService.generateMediaProfile(recording.getRecordingProperties(),
+						participant);
+			} catch (OpenViduException e) {
+				log.error("Cannot start single stream recorder for stream {} in session {}: {}",
+						participant.getPublisherStreamId(), session.getSessionId(), e.getMessage());
+				return;
+			}
+
+			this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(session, recording.getId(), profile,
 					participant, startedCountDown);
 		} else if (RecordingUtils.IS_COMPOSED(recording.getOutputMode()) && !recording.hasVideo()) {
 			// Connect this stream to existing Composite recorder
 			log.info("Joining PublisherEndpoint to existing Composite in session {} for new stream of participant {}",
 					session.getSessionId(), participant.getParticipantPublicId());
-			this.composedRecordingService.joinPublisherEndpointToComposite(session, recordingId, participant);
+			this.composedRecordingService.joinPublisherEndpointToComposite(session, recording.getId(), participant);
 		}
 	}
 
@@ -470,7 +480,8 @@ public class RecordingManager {
 		}
 		if (Status.stopped.equals(recording.getStatus())) {
 			// Recording is being downloaded from remote host or being uploaded
-			log.warn("Recording {} status is \"stopped\". Cancelling possible ongoing download process", recording.getId());
+			log.warn("Recording {} status is \"stopped\". Cancelling possible ongoing download process",
+					recording.getId());
 			this.recordingDownloader.cancelDownload(recording.getId());
 		}
 
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
index 170ef9a7..4cb7e1ab 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java
@@ -116,7 +116,7 @@ public class SingleStreamRecordingService extends RecordingService {
 					recordingStartedCountdown.countDown();
 					continue;
 				}
-				this.startRecorderEndpointForPublisherEndpoint(session, recordingId, profile, p,
+				this.startRecorderEndpointForPublisherEndpoint(session, recording.getId(), profile, p,
 						recordingStartedCountdown);
 			}
 		}
@@ -205,7 +205,7 @@ public class SingleStreamRecordingService extends RecordingService {
 		return finalRecordingArray[0];
 	}
 
-	public void startRecorderEndpointForPublisherEndpoint(final Session session, String recordingId,
+	public void startRecorderEndpointForPublisherEndpoint(final Session session, final String recordingId,
 			MediaProfileSpecType profile, final Participant participant, CountDownLatch globalStartLatch) {
 
 		log.info("Starting single stream recorder for stream {} in session {}", participant.getPublisherStreamId(),
@@ -220,31 +220,6 @@ public class SingleStreamRecordingService extends RecordingService {
 						return;
 					}
 
-					if (recordingId == null) {
-						// Stream is being recorded because is a new publisher in an ongoing recorded
-						// session. If recordingId is defined is because Stream is being recorded from
-						// "startRecording" method
-						Recording recording = this.recordingManager.sessionsRecordings.get(session.getSessionId());
-						if (recording == null) {
-							recording = this.recordingManager.sessionsRecordingsStarting.get(session.getSessionId());
-							if (recording == null) {
-								log.error(
-										"Cannot start single stream recorder for stream {} in session {}. The recording {} cannot be found",
-										participant.getPublisherStreamId(), session.getSessionId(), recordingId);
-								return;
-							}
-						}
-						recordingId = recording.getId();
-
-						try {
-							profile = generateMediaProfile(recording.getRecordingProperties(), participant);
-						} catch (OpenViduException e) {
-							log.error("Cannot start single stream recorder for stream {} in session {}: {}",
-									participant.getPublisherStreamId(), session.getSessionId(), e.getMessage());
-							return;
-						}
-					}
-
 					KurentoParticipant kurentoParticipant = (KurentoParticipant) participant;
 					MediaPipeline pipeline = kurentoParticipant.getPublisher().getPipeline();
 
@@ -252,12 +227,10 @@ public class SingleStreamRecordingService extends RecordingService {
 							"file://" + openviduConfig.getOpenViduRemoteRecordingPath() + recordingId + "/"
 									+ participant.getPublisherStreamId() + ".webm").withMediaProfile(profile).build();
 
-					final String finalRecordingId = recordingId;
-
 					recorder.addRecordingListener(new EventListener() {
 						@Override
 						public void onEvent(RecordingEvent event) {
-							activeRecorders.get(finalRecordingId).get(participant.getPublisherStreamId())
+							activeRecorders.get(recordingId).get(participant.getPublisherStreamId())
 									.setStartTime(Long.parseLong(event.getTimestampMillis()));
 							log.info("Recording started event for stream {}", participant.getPublisherStreamId());
 							globalStartLatch.countDown();
@@ -333,7 +306,7 @@ public class SingleStreamRecordingService extends RecordingService {
 		}
 	}
 
-	private MediaProfileSpecType generateMediaProfile(RecordingProperties properties, Participant participant)
+	MediaProfileSpecType generateMediaProfile(RecordingProperties properties, Participant participant)
 			throws OpenViduException {
 
 		KurentoParticipant kParticipant = (KurentoParticipant) participant;

From 80a052fcea24f9c4a6646a8d92273884e969410a Mon Sep 17 00:00:00 2001
From: csantosm <4a.santos@gmail.com>
Date: Fri, 18 Sep 2020 15:13:52 +0200
Subject: [PATCH 028/435] openvidu-server: Network quality

- Added method to send notification with network quality
- Added double parser method
---
 .../io/openvidu/server/config/OpenviduConfig.java  | 14 ++++++++++++++
 .../openvidu/server/core/SessionEventsHandler.java |  4 ++++
 2 files changed, 18 insertions(+)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
index 13173325..fd609f87 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
@@ -772,6 +772,20 @@ public class OpenviduConfig {
 		}
 	}
 
+	protected Double asNonNegativeDouble(String property) {
+		try {
+			Double doubleValue = Double.parseDouble(getValue(property));
+
+			if (doubleValue < 0) {
+				addError(property, "Is not a non negative double");
+			}
+			return doubleValue;
+		} catch (NumberFormatException e) {
+			addError(property, "Is not a non negative doubleValue");
+			return 0.0;
+		}
+	}
+
 	/*
 	 * This method checks all types of Internet addresses (IPv4, IPv6 and Domains)
 	 */
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
index e217cff4..982d96f5 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
@@ -311,6 +311,10 @@ public class SessionEventsHandler {
 		rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
 	}
 
+	public void onNetworkQualityChanged(Participant participant, JsonObject params ) {
+		rpcNotificationService.sendNotification(participant.getParticipantPrivateId(), ProtocolElements.NETWORKQUALITYCHANGED_METHOD, params);
+	}
+
 	public void onSendMessage(Participant participant, JsonObject message, Set participants,
 			Integer transactionId, OpenViduException error) {
 

From 1bfde64752e1f7584296122efc59024ffca2cf46 Mon Sep 17 00:00:00 2001
From: csantosm <4a.santos@gmail.com>
Date: Fri, 18 Sep 2020 15:14:33 +0200
Subject: [PATCH 029/435] openvidu-client: Network quality

- Added network fields to ProtocolElements
---
 .../java/io/openvidu/client/internal/ProtocolElements.java  | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
index 8f033494..c664e8ac 100644
--- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
+++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
@@ -93,6 +93,12 @@ public class ProtocolElements {
 	public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue";
 	public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason";
 
+	public static final String NETWORKQUALITYCHANGED_METHOD = "networkQualityChanged";
+	public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId";
+	public static final String NETWORKQUALITYCHANGED_NEWVALUE_PARAM = "newValue";
+	public static final String NETWORKQUALITYCHANGED_OLDVALUE_PARAM = "oldValue";
+	public static final String NETWORKQUALITYCHANGED_REASON_PARAM = "reason";
+
 	public static final String FORCEDISCONNECT_METHOD = "forceDisconnect";
 	public static final String FORCEDISCONNECT_CONNECTIONID_PARAM = "connectionId";
 

From c39e16852f6bf64a5f26d9a5829225f4e6457630 Mon Sep 17 00:00:00 2001
From: csantosm <4a.santos@gmail.com>
Date: Fri, 18 Sep 2020 15:15:55 +0200
Subject: [PATCH 030/435] openvidu-browser: Network quality

- Added networkQualityChanged event
---
 openvidu-browser/src/OpenVidu/OpenVidu.ts     |  1 +
 openvidu-browser/src/OpenVidu/Session.ts      | 18 +++++-
 .../Events/NetworkQualityChangedEvent.ts      | 63 +++++++++++++++++++
 3 files changed, 79 insertions(+), 3 deletions(-)
 create mode 100644 openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts

diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts
index 6a7bb76b..8820a72c 100644
--- a/openvidu-browser/src/OpenVidu/OpenVidu.ts
+++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts
@@ -777,6 +777,7 @@ export class OpenVidu {
         recordingStopped: this.session.onRecordingStopped.bind(this.session),
         sendMessage: this.session.onNewMessage.bind(this.session),
         streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session),
+        networkQualityChanged: this.session.onNetworkQualityChangedChanged.bind(this.session),
         filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session),
         iceCandidate: this.session.recvIceCandidate.bind(this.session),
         mediaError: this.session.onMediaError.bind(this.session)
diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts
index 61f50bc9..f6650a68 100644
--- a/openvidu-browser/src/OpenVidu/Session.ts
+++ b/openvidu-browser/src/OpenVidu/Session.ts
@@ -37,6 +37,7 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc
 import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent';
 import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent';
 import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
+import { NetworkQualityChangedEvent, NetworkQualityChangedReason } from '../OpenViduInternal/Events/NetworkQualityChangedEvent';
 import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError';
 import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode';
 
@@ -591,7 +592,7 @@ export class Session extends EventDispatcher {
     /**
      * See [[EventDispatcher.on]]
      */
-    on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): EventDispatcher {
+    on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): EventDispatcher {
 
         super.onAux(type, "Event '" + type + "' triggered by 'Session'", handler);
 
@@ -623,7 +624,7 @@ export class Session extends EventDispatcher {
     /**
      * See [[EventDispatcher.once]]
      */
-    once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): Session {
+    once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): Session {
 
         super.onceAux(type, "Event '" + type + "' triggered once by 'Session'", handler);
 
@@ -655,7 +656,7 @@ export class Session extends EventDispatcher {
     /**
      * See [[EventDispatcher.off]]
      */
-    off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent) => void): Session {
+    off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): Session {
 
         super.off(type, handler);
 
@@ -920,6 +921,17 @@ export class Session extends EventDispatcher {
         }
     }
 
+
+    /**
+     * @hidden
+     */
+    onNetworkQualityChangedChanged(msg): void {
+
+        if (msg.connectionId === this.connection.connectionId) {
+            this.ee.emitEvent('networkQualityChanged', [new NetworkQualityChangedEvent(this, msg.newValue, msg.oldValue, msg.reason)]);
+        }
+    }
+
     /**
      * @hidden
      */
diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts
new file mode 100644
index 00000000..710950e0
--- /dev/null
+++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts
@@ -0,0 +1,63 @@
+/*
+ * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Event } from './Event';
+import { Session } from '../../OpenVidu/Session';
+
+/**
+ * Defines event `networkQualityChangedEvent` dispatched by [[Session]].
+ * This event is fired when the network quality of the local connection changes
+ */
+export class NetworkQualityChangedEvent extends Event {
+
+    /**
+     * Cause of the change on the neteotk quality event
+     */
+    reason: NetworkQualityChangedReason;
+
+    /**
+     * New value of the property (after change, current value)
+     */
+    newValue: Object;
+
+    /**
+     * Previous value of the property (before change)
+     */
+    oldValue: Object;
+
+    /**
+     * @hidden
+     */
+    constructor(target: Session, newValue: Object, oldValue: Object, reason: NetworkQualityChangedReason) {
+        super(false, target, 'networkQualityChanged');
+        this.newValue = newValue;
+        this.oldValue = oldValue;
+        this.reason = reason;
+    }
+
+    /**
+     * @hidden
+     */
+    // tslint:disable-next-line:no-empty
+    callDefaultBehavior() { }
+
+}
+
+export enum NetworkQualityChangedReason {
+	ABOVE_MAX = "above_max",
+	BELOW_MIN = "below_min"
+}

From a32351c029013bd2f3c6043b33f02f977c04c5c2 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 18 Sep 2020 15:23:22 +0200
Subject: [PATCH 031/435] openvidu-server: default value for networkCache

---
 .../main/java/io/openvidu/server/rest/SessionRestController.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index 7ef11811..a5bbcd39 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -784,6 +784,7 @@ public class SessionRestController {
 		type = "IPCAM"; // Other possible values in the future
 		adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true;
 		onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true;
+		networkCache = networkCache != null ? networkCache : 2000;
 		data = data != null ? data : "";
 
 		boolean hasAudio = true;

From 5f258daf8074d6fa0db95904237f2ec8caaa5497 Mon Sep 17 00:00:00 2001
From: csantosm <4a.santos@gmail.com>
Date: Fri, 18 Sep 2020 16:19:57 +0200
Subject: [PATCH 032/435] openvidu-browser: Exported network quality types

Exported NetworkQualityChangedEvent and NetworkQualityChangedReason
---
 openvidu-browser/src/index.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/openvidu-browser/src/index.ts b/openvidu-browser/src/index.ts
index 828697bf..d9c509ae 100644
--- a/openvidu-browser/src/index.ts
+++ b/openvidu-browser/src/index.ts
@@ -23,6 +23,8 @@ export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent
 export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent';
 export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent';
 export { FilterEvent } from './OpenViduInternal/Events/FilterEvent';
+export { NetworkQualityChangedEvent } from './OpenViduInternal/Events/NetworkQualityChangedEvent';
+export { NetworkQualityChangedReason } from './OpenViduInternal/Events/NetworkQualityChangedEvent';
 
 export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities';
 export { Device } from './OpenViduInternal/Interfaces/Public/Device';

From 71c5409b0523bf5cf31fcc98d78e248a4dd9f086 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Tue, 22 Sep 2020 10:34:51 +0200
Subject: [PATCH 033/435] openvidu-server: return 501 for any recording REST
 method if recording disabled

---
 .../server/rest/SessionRestController.java    | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index a5bbcd39..a8f8adf7 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -598,6 +598,11 @@ public class SessionRestController {
 
 		log.info("REST API: POST /api/recordings/stop/{}", recordingId);
 
+		if (!this.openviduConfig.isRecordingModuleEnabled()) {
+			// OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false
+			return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+		}
+
 		Recording recording = recordingManager.getStartedRecording(recordingId);
 
 		if (recording == null) {
@@ -634,6 +639,11 @@ public class SessionRestController {
 
 		log.info("REST API: GET /api/recordings/{}", recordingId);
 
+		if (!this.openviduConfig.isRecordingModuleEnabled()) {
+			// OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false
+			return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+		}
+
 		try {
 			Recording recording = this.recordingManager.getRecording(recordingId);
 			if (io.openvidu.java.client.Recording.Status.started.equals(recording.getStatus())
@@ -651,6 +661,11 @@ public class SessionRestController {
 
 		log.info("REST API: GET /api/recordings");
 
+		if (!this.openviduConfig.isRecordingModuleEnabled()) {
+			// OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false
+			return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+		}
+
 		Collection recordings = this.recordingManager.getAllRecordings();
 		JsonObject json = new JsonObject();
 		JsonArray jsonArray = new JsonArray();
@@ -671,6 +686,11 @@ public class SessionRestController {
 
 		log.info("REST API: DELETE /api/recordings/{}", recordingId);
 
+		if (!this.openviduConfig.isRecordingModuleEnabled()) {
+			// OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false
+			return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+		}
+
 		return new ResponseEntity<>(this.recordingManager.deleteRecordingFromHost(recordingId, false));
 	}
 

From 0f565f5b45e6457653ca5aff5d1988578f76be60 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Tue, 22 Sep 2020 17:15:12 +0200
Subject: [PATCH 034/435] Typedoc config updated to avoid protected classes

---
 openvidu-browser/config/typedoc.js     | 1 +
 openvidu-node-client/config/typedoc.js | 1 +
 2 files changed, 2 insertions(+)

diff --git a/openvidu-browser/config/typedoc.js b/openvidu-browser/config/typedoc.js
index 5516ee51..12b52250 100644
--- a/openvidu-browser/config/typedoc.js
+++ b/openvidu-browser/config/typedoc.js
@@ -19,6 +19,7 @@ module.exports = {
     ],
     excludeExternals: true,
     excludePrivate: true,
+    excludeProtected: true,
     excludeNotExported: true,
     theme: "default",
     readme: "none",
diff --git a/openvidu-node-client/config/typedoc.js b/openvidu-node-client/config/typedoc.js
index 62bd81de..987eccd7 100644
--- a/openvidu-node-client/config/typedoc.js
+++ b/openvidu-node-client/config/typedoc.js
@@ -12,6 +12,7 @@ module.exports = {
     externalPattern: "node_modules",
     excludeExternals: true,
     excludePrivate: true,
+    excludeProtected: true,
     excludeNotExported: true,
     theme: "default",
     readme: "none",

From df92cca9de403b0dea2cc481d49a1c018fa14fd7 Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Tue, 22 Sep 2020 18:19:51 +0200
Subject: [PATCH 035/435] Deployment: External and secure Kibana and
 Elasticsearch in can be configured in OpenVidu Pro Node

---
 ...penvidu-server-pro-no-market.yaml.template | 35 +++++++++----------
 .../docker-compose/openvidu-server-pro/.env   |  7 ++--
 .../openvidu-server-pro/beats/filebeat.yml    |  4 ++-
 .../openvidu-server-pro/docker-compose.yml    | 19 +++++++---
 .../install_openvidu_pro.sh                   |  2 +-
 .../openvidu-server-pro/openvidu              |  2 +-
 .../pro/default-app-without-demos.conf        |  2 --
 .../default_nginx_conf/pro/default.conf       |  2 --
 .../docker/openvidu-server-pro/entrypoint.sh  | 13 ++-----
 9 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
index 6d60034f..be09fbd3 100644
--- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
+++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
@@ -63,21 +63,20 @@ Parameters:
     Type: Number
     Default: 1
 
-  # Kibana configuration
-
-  KibanaUser:
-    Description: "Username for Kibana Dashboard"
+  # Elasticsearch configuration
+  ElasticsearchUser:
+    Description: "Username for Elasticsearch and Kibana"
     Type: String
     AllowedPattern: ^((?!")(?! ).)+$
-    ConstraintDescription: Kibana user is mandatory (no whitespaces or quotations allowed)
-    Default: kibanaadmin
+    ConstraintDescription: Elasticsearch user is mandatory (no whitespaces or quotations allowed)
+    Default: elasticadmin
 
-  KibanaPassword:
-    Description: "Password for Kibana Dashboard"
+  ElasticsearchPassword:
+    Description: "Password for Elasticsearch and Kibana"
     Type: String
     AllowedPattern: ^((?!")(?! ).)+$
     NoEcho: true
-    ConstraintDescription: Kibana password is mandatory (no whitespaces or quotations allowed)
+    ConstraintDescription: Elasticsearch password is mandatory (no whitespaces or quotations allowed)
 
   # EC2 Instance configuration
 
@@ -216,8 +215,8 @@ Metadata:
       - Label:
           default: Kibana configuration
         Parameters:
-          - KibanaUser
-          - KibanaPassword
+          - ElasticsearchUser
+          - ElasticsearchPassword
       - Label:
             default: EC2 Instance configuration
         Parameters:
@@ -256,10 +255,10 @@ Metadata:
       OpenViduSecret:
         default: "Openvidu Secret"
       # Kibana configuration
-      KibanaUser:
-        default: "Kibana username"
-      KibanaPassword:
-        default: "Kibana password"
+      ElasticsearchUser:
+        default: "Elasticsearch and Kibana username"
+      ElasticsearchPassword:
+        default: "Elasticsearch and Kibana password"
       # EC2 instance configuration
       AwsInstanceTypeOV:
         default: "Instance type for Openvidu Server Pro Node"
@@ -383,9 +382,9 @@ Resources:
                 sed -i "s/CERTIFICATE_TYPE=selfsigned/CERTIFICATE_TYPE=${WhichCert}/" $WORKINGDIR/.env
                 sed -i "s/LETSENCRYPT_EMAIL=user@example.com/LETSENCRYPT_EMAIL=${LetsEncryptEmail}/" $WORKINGDIR/.env
 
-                # Replace Kibana Conf
-                sed -i "s/KIBANA_USER=kibanaadmin/KIBANA_USER=${KibanaUser}/" $WORKINGDIR/.env
-                sed -i "s/KIBANA_PASSWORD=/KIBANA_PASSWORD=${KibanaPassword}/" $WORKINGDIR/.env
+                # Replace Elastic Search Conf
+                sed -i "s/ELASTICSEARCH_USERNAME=elasticadmin/ELASTICSEARCH_USERNAME=${ElasticsearchUser}/" $WORKINGDIR/.env
+                sed -i "s/ELASTICSEARCH_PASSWORD=/ELASTICSEARCH_PASSWORD=${ElasticsearchPassword}/" $WORKINGDIR/.env
 
                 # Replace vars AWS
                 sed -i "s/#AWS_DEFAULT_REGION=/AWS_DEFAULT_REGION=${AWS::Region}/" $WORKINGDIR/.env
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
index 056cf286..567116e1 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
@@ -228,9 +228,10 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
 
 # Kibana And ElasticSearch Configuration
 # --------------------------
-# Kibana dashboard configuration (Credentials)
-KIBANA_USER=kibanaadmin
-KIBANA_PASSWORD=
+# Kibana And ElasticSeach Basic Auth configuration (Credentials)
+# This credentials will aso be valid for Kibana dashboard
+ELASTICSEARCH_USERNAME=elasticadmin
+ELASTICSEARCH_PASSWORD=
 
 # Cloudformation configuration
 # --------------------------
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
index c84977e8..3581884d 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
@@ -16,7 +16,9 @@ processors:
 
 output:
   elasticsearch:
-    hosts: ["elasticsearch:9200"]
+    hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
+    username: ${ELASTICSEARCH_USERNAME}
+    password: ${ELASTICSEARCH_PASSWORD}
     indices:
       - index: "filebeat-redis-%{+yyyy.MM.dd}"
         when.or:
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
index 5cd67732..8a1ed5af 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
@@ -42,9 +42,9 @@ services:
             - COTURN_REDIS_IP=127.0.0.1
             - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET}
             - OPENVIDU_PRO_CLUSTER=true
-            - OPENVIDU_PRO_KIBANA_HOST=http://127.0.0.1/kibana
-            - OPENVIDU_PRO_ELASTICSEARCH_HOST=http://127.0.0.1:9200
-            - WAIT_KIBANA_URL=http://127.0.0.1:5601/api/status
+            - OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
+            - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
+            - WAIT_KIBANA_URL=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana}
             - DOTENV_PATH=${PWD}
 
     redis:
@@ -70,7 +70,6 @@ services:
         image: openvidu/openvidu-proxy:3.0.0
         restart: on-failure
         network_mode: host
-        entrypoint: ['/bin/sh', '-c', 'htpasswd -bc /etc/nginx/kibana.htpasswd "${KIBANA_USER}" "${KIBANA_PASSWORD}" && /usr/local/bin/entrypoint.sh']
         volumes:
             - ./certificates:/etc/letsencrypt
             - ./owncert:/owncert
@@ -89,8 +88,13 @@ services:
     elasticsearch:
         image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
         restart: always
+        command: 
+            - '/bin/bash'
+            - '-c'
+            - '/usr/share/elasticsearch/bin/elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} -p ${ELASTICSEARCH_PASSWORD} -r superuser && /tini -- /usr/local/bin/docker-entrypoint.sh'
         environment:
             - discovery.type=single-node
+            - xpack.security.enabled=true
         ports:
             - 9200:9200
         volumes:
@@ -101,13 +105,20 @@ services:
         restart: always
         environment:
             - SERVER_BASEPATH="/kibana"
+            - ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
+            - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
         ports:
             - 5601:5601
 
     filebeat:
         image: docker.elastic.co/beats/filebeat:7.8.0
+        network_mode: host
         restart: always
         user: root
+        environment:
+            - ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
+            - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
+            - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
         volumes:
             - ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
             - /var/lib/docker:/var/lib/docker:ro
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh
index 5dd1ca1f..0a4f48d9 100755
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh
@@ -105,7 +105,7 @@ new_ov_installation() {
      printf '\n     1. Go to openvidu folder:'
      printf '\n     $ cd openvidu'
      printf '\n'
-     printf '\n     2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, OPENVIDU_SECRET, and KIBANA_PASSWORD in .env file:'
+     printf '\n     2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, OPENVIDU_SECRET, and ELASTICSEARCH_PASSWORD in .env file:'
      printf '\n     $ nano .env'
      printf '\n'
      printf '\n     3. Start OpenVidu'
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/openvidu b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/openvidu
index 9f948e61..c1991b79 100755
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/openvidu
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/openvidu
@@ -120,7 +120,7 @@ generate_report() {
     printf '\n'
     printf '\n'
 
-    cat < "${OV_FOLDER}/.env" | sed -r -e "s/OPENVIDU_SECRET=.+/OPENVIDU_SECRET=****/" -e "s/OPENVIDU_PRO_LICENSE=.+/OPENVIDU_PRO_LICENSE=****/" -e "s/KIBANA_PASSWORD=.+/KIBANA_PASSWORD=****/"
+    cat < "${OV_FOLDER}/.env" | sed -r -e "s/OPENVIDU_SECRET=.+/OPENVIDU_SECRET=****/" -e "s/OPENVIDU_PRO_LICENSE=.+/OPENVIDU_PRO_LICENSE=****/" -e "s/ELASTICSEARCH_PASSWORD=.+/ELASTICSEARCH_PASSWORD=****/"
 
     printf '\n'
     printf '\n  ========= docker-compose.yml =========='
diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf
index 1473ac20..9e5b254a 100644
--- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf
+++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf
@@ -89,8 +89,6 @@ server {
     location /kibana {
         {rules_access_dashboard}
         deny all;
-        auth_basic "Openvidu Monitoring";
-        auth_basic_user_file /etc/nginx/kibana.htpasswd;
 
         rewrite ^/kibana/(.*)$ /$1 break;
         proxy_pass http://kibana/;
diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf
index d5ada4eb..b1ffd189 100644
--- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf
+++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf
@@ -99,8 +99,6 @@ server {
     location /kibana {
         {rules_access_dashboard}
         deny all;
-        auth_basic "Openvidu Monitoring";
-        auth_basic_user_file /etc/nginx/kibana.htpasswd;
 
         rewrite ^/kibana/(.*)$ /$1 break;
         proxy_pass http://kibana/;
diff --git a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh
index b7b8ed9e..468e4812 100755
--- a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh
+++ b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh
@@ -8,19 +8,12 @@ if [ ! -z "${WAIT_KIBANA_URL}" ]; then
   printf "\n  ======================================="
   printf "\n"
 
-  while true
-  do
-    HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "${WAIT_KIBANA_URL}")
-
+  until $(curl --insecure --output /dev/null --silent --head --fail ${WAIT_KIBANA_URL})
+  do 
     printf "\n  Waiting for kibana in '%s' URL..." "${WAIT_KIBANA_URL}"
-
-    if [ "$HTTP_STATUS" == "200" ]; then
-      printf "\n  ==== Kibana is Ready ===="
-      break
-    fi
-
     sleep 1
   done
+  printf "\n  ==== Kibana is Ready ===="
 fi
 
 # Launch Openvidu Pro

From 353989e26b997cef1b3d6837f06fa521c24dd015 Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Tue, 22 Sep 2020 19:04:50 +0200
Subject: [PATCH 036/435] Deployment: Fix typos Elasticsearch OpenVidu Pro

---
 .../deployments/pro/docker-compose/openvidu-server-pro/.env     | 2 +-
 .../pro/docker-compose/openvidu-server-pro/docker-compose.yml   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
index 567116e1..7e59b016 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env
@@ -228,7 +228,7 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
 
 # Kibana And ElasticSearch Configuration
 # --------------------------
-# Kibana And ElasticSeach Basic Auth configuration (Credentials)
+# Kibana And ElasticSearch Basic Auth configuration (Credentials)
 # This credentials will aso be valid for Kibana dashboard
 ELASTICSEARCH_USERNAME=elasticadmin
 ELASTICSEARCH_PASSWORD=
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
index 8a1ed5af..62abfeb5 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
@@ -91,7 +91,7 @@ services:
         command: 
             - '/bin/bash'
             - '-c'
-            - '/usr/share/elasticsearch/bin/elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} -p ${ELASTICSEARCH_PASSWORD} -r superuser && /tini -- /usr/local/bin/docker-entrypoint.sh'
+            - '/usr/share/elasticsearch/bin/elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} -p ${ELASTICSEARCH_PASSWORD} -r superuser; /tini -- /usr/local/bin/docker-entrypoint.sh'
         environment:
             - discovery.type=single-node
             - xpack.security.enabled=true

From bea77f5360a020f23bff8838a20d9743cde65d0b Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Wed, 23 Sep 2020 21:40:48 +0200
Subject: [PATCH 037/435] Deployment: Update to dev version docker-compose

---
 .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
index 62abfeb5..0eeafe55 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
@@ -22,7 +22,7 @@ version: '3.1'
 services:
 
     openvidu-server:
-        image: openvidu/openvidu-server-pro:2.15.1
+        image: openvidu/openvidu-server-pro:2.16.0-dev2
         restart: on-failure
         network_mode: host
         entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh']
@@ -67,7 +67,7 @@ services:
             - MAX_PORT=65535
 
     nginx:
-        image: openvidu/openvidu-proxy:3.0.0
+        image: openvidu/openvidu-proxy:4.0.0-dev1
         restart: on-failure
         network_mode: host
         volumes:

From 407f72f0d1ed8abc0bc03a9d91444b3efb49f4b0 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 24 Sep 2020 12:28:51 +0200
Subject: [PATCH 038/435] openvidu-server: do not set recording URL to null
 while uploading

---
 .../openvidu/server/recording/service/RecordingManager.java  | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

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 d1548af7..f4666ddf 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
@@ -396,8 +396,8 @@ public class RecordingManager {
 				return;
 			}
 
-			this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(session, recording.getId(), profile,
-					participant, startedCountDown);
+			this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(session, recording.getId(),
+					profile, participant, startedCountDown);
 		} else if (RecordingUtils.IS_COMPOSED(recording.getOutputMode()) && !recording.hasVideo()) {
 			// Connect this stream to existing Composite recorder
 			log.info("Joining PublisherEndpoint to existing Composite in session {} for new stream of participant {}",
@@ -571,7 +571,6 @@ public class RecordingManager {
 				&& composedQuickStartRecordingService.isBeingUploaded(recording)) {
 			// Recording has finished but is being uploaded
 			recording.setStatus(Status.stopped);
-			recording.setUrl(null);
 		} else if (Status.ready.equals(recording.getStatus()) || Status.failed.equals(recording.getStatus())) {
 			// Recording has been completely processed and must include URL
 			recording.setUrl(recordingManagerUtils.getRecordingUrl(recording));

From 593b2fa80d89d74aae05ee5e7007274310411c09 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 24 Sep 2020 12:37:20 +0200
Subject: [PATCH 039/435] openvidu-server: updateRecordingAttributes to not
 return object

---
 .../service/ComposedQuickStartRecordingService.java          | 2 +-
 .../server/recording/service/ComposedRecordingService.java   | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
index c0b8d86c..f1262adb 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
@@ -123,7 +123,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
 			e1.printStackTrace();
 		}
 
-		recording = updateRecordingAttributes(recording);
+		updateRecordingAttributes(recording);
 
 		this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(),
 				getMetadataFilePath(recording));
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index 0ddf3581..19020abe 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -298,7 +298,7 @@ public class ComposedRecordingService extends RecordingService {
 		} else {
 
 			stopAndRemoveRecordingContainer(recording, containerId, 30);
-			recording = updateRecordingAttributes(recording);
+			updateRecordingAttributes(recording);
 
 			this.sealRecordingMetadataFileAsReady(recording, recording.getSize(), recording.getDuration(),
 					getMetadataFilePath(recording));
@@ -415,7 +415,7 @@ public class ComposedRecordingService extends RecordingService {
 		containers.remove(containerId);
 	}
 
-	protected Recording updateRecordingAttributes(Recording recording) {
+	protected void updateRecordingAttributes(Recording recording) {
 		try {
 			RecordingInfoUtils infoUtils = new RecordingInfoUtils(this.openviduConfig.getOpenViduRecordingPath()
 					+ recording.getId() + "/" + recording.getId() + ".info");
@@ -432,7 +432,6 @@ public class ComposedRecordingService extends RecordingService {
 				recording.setHasVideo(infoUtils.hasVideo());
 			}
 			infoUtils.deleteFilePath();
-			return recording;
 		} catch (IOException e) {
 			recording.setStatus(io.openvidu.java.client.Recording.Status.failed);
 			throw new OpenViduException(Code.RECORDING_REPORT_ERROR_CODE,

From b9d28d11cdf8f8474dc4b482754cb45f4eeb2aa9 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 25 Sep 2020 16:45:03 +0200
Subject: [PATCH 040/435] openvidu-server: composed quickstart recording stop
 bug fix

---
 .../ComposedQuickStartRecordingService.java   |  4 +-
 .../service/ComposedRecordingService.java     |  2 +-
 .../openvidu/server/utils/DockerManager.java  | 46 ++++++++++++-------
 3 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
index f1262adb..5ab5588e 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java
@@ -78,7 +78,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
 				recordExecCommand += "export " + envs.get(i) + " ";
 			}
 			recordExecCommand += "&& ./composed_quick_start.sh --start-recording > /var/log/ffmpeg.log 2>&1 &";
-			dockerManager.runCommandInContainer(containerId, recordExecCommand, 0);
+			dockerManager.runCommandInContainer(containerId, recordExecCommand);
 		} catch (Exception e) {
 			this.cleanRecordingMaps(recording);
 			throw this.failStartRecording(session, recording,
@@ -116,7 +116,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService
 		}
 
 		try {
-			dockerManager.runCommandInContainer(containerId, "./composed_quick_start.sh --stop-recording", 10);
+			dockerManager.runCommandInContainerSync(containerId, "./composed_quick_start.sh --stop-recording", 10);
 		} catch (InterruptedException e1) {
 			cleanRecordingMaps(recording);
 			log.error("Error stopping recording for session id: {}", session.getSessionId());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index 19020abe..e91ef8b9 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -396,7 +396,7 @@ public class ComposedRecordingService extends RecordingService {
 	protected void stopAndRemoveRecordingContainer(Recording recording, String containerId, int secondsOfWait) {
 		// Gracefully stop ffmpeg process
 		try {
-			dockerManager.runCommandInContainer(containerId, "echo 'q' > stop", 0);
+			dockerManager.runCommandInContainer(containerId, "echo 'q' > stop");
 		} catch (InterruptedException e1) {
 			e1.printStackTrace();
 		}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java b/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
index bb4a87d0..c616729b 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
@@ -26,23 +26,29 @@ import java.util.concurrent.TimeUnit;
 
 import javax.ws.rs.ProcessingException;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import com.github.dockerjava.api.DockerClient;
-import com.github.dockerjava.api.async.ResultCallback;
-import com.github.dockerjava.api.command.*;
+import com.github.dockerjava.api.command.CreateContainerCmd;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.ExecCreateCmdResponse;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.command.InspectImageResponse;
 import com.github.dockerjava.api.exception.ConflictException;
 import com.github.dockerjava.api.exception.DockerClientException;
 import com.github.dockerjava.api.exception.InternalServerErrorException;
 import com.github.dockerjava.api.exception.NotFoundException;
-import com.github.dockerjava.api.model.*;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.Container;
+import com.github.dockerjava.api.model.HostConfig;
+import com.github.dockerjava.api.model.Volume;
 import com.github.dockerjava.core.DefaultDockerClientConfig;
 import com.github.dockerjava.core.DockerClientBuilder;
 import com.github.dockerjava.core.DockerClientConfig;
 import com.github.dockerjava.core.command.ExecStartResultCallback;
 import com.github.dockerjava.core.command.PullImageResultCallback;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import io.openvidu.client.OpenViduException;
 import io.openvidu.client.OpenViduException.Code;
 import io.openvidu.server.recording.service.WaitForContainerStoppedCallback;
@@ -63,7 +69,7 @@ public class DockerManager {
 			// Pull image
 			this.dockerClient.pullImageCmd(image).exec(new PullImageResultCallback()).awaitCompletion(secondsOfWait,
 					TimeUnit.SECONDS);
-			
+
 		} catch (NotFoundException | InternalServerErrorException e) {
 			if (dockerImageExistsLocally(image)) {
 				log.info("Docker image '{}' exists locally", image);
@@ -102,9 +108,8 @@ public class DockerManager {
 	}
 
 	public String runContainer(String container, String containerName, String user, List volumes,
-			List binds, String networkMode, List envs, List command, Long shmSize, boolean privileged,
-		    Map labels)
-			throws Exception {
+			List binds, String networkMode, List envs, List command, Long shmSize,
+			boolean privileged, Map labels) throws Exception {
 
 		CreateContainerCmd cmd = dockerClient.createContainerCmd(container).withEnv(envs);
 		if (containerName != null) {
@@ -167,21 +172,30 @@ public class DockerManager {
 		}
 	}
 
-	public String runCommandInContainer(String containerId, String command, int secondsOfWait)
+	public void runCommandInContainer(String containerId, String command) throws InterruptedException {
+		ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId).withAttachStdout(true)
+				.withAttachStderr(true).withCmd("bash", "-c", command).exec();
+		dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(new ExecStartResultCallback() {
+		});
+	}
+
+	public void runCommandInContainerSync(String containerId, String command, int secondsOfWait)
 			throws InterruptedException {
 		ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId).withAttachStdout(true)
 				.withAttachStderr(true).withCmd("bash", "-c", command).exec();
 		CountDownLatch latch = new CountDownLatch(1);
-		final String[] stringResponse = new String[1];
 		dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(new ExecStartResultCallback() {
 			@Override
-			public void onNext(Frame item) {
-				stringResponse[0] = new String(item.getPayload());
+			public void onComplete() {
 				latch.countDown();
 			}
 		});
-		latch.await(secondsOfWait, TimeUnit.SECONDS);
-		return stringResponse[0];
+		try {
+			latch.await(secondsOfWait, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			throw new InterruptedException("Container " + containerId + " did not return from executing command \""
+					+ command + "\" in " + secondsOfWait + " seconds");
+		}
 	}
 
 	public void waitForContainerStopped(String containerId, int secondsOfWait) throws Exception {

From eb7fb81995f42192bf6f221fa96c4fa51d747197 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 25 Sep 2020 17:34:46 +0200
Subject: [PATCH 041/435] openvidu-test-e2e: improved quick start record test

---
 .../test/e2e/OpenViduTestAppE2eTest.java      | 189 ++++++++++--------
 1 file changed, 102 insertions(+), 87 deletions(-)

diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index 5f9986c1..6fa0317d 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -1245,96 +1245,111 @@ public class OpenViduTestAppE2eTest {
 		setupBrowser("chrome");
 
 		log.info("Remote composed quick start record");
+		
+		CountDownLatch initLatch = new CountDownLatch(1);
+		io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
 
-		final String sessionName = "COMPOSED_QUICK_START_RECORDED_SESSION";
+		try {
 
-		// 1. MANUAL mode and recording explicitly stopped
+			if (!initLatch.await(30, TimeUnit.SECONDS)) {
+				Assert.fail("Timeout waiting for webhook springboot app to start");
+				CustomWebhook.shutDown();
+				return;
+			}
 
-		user.getDriver().findElement(By.id("add-user-btn")).click();
-		user.getDriver().findElement(By.id("session-name-input-0")).clear();
-		user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
-
-		user.getDriver().findElement(By.id("session-settings-btn-0")).click();
-		Thread.sleep(1000);
-		user.getDriver().findElement(By.id("output-mode-select")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("option-COMPOSED_QUICK_START")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("save-btn")).click();
-		Thread.sleep(1000);
-
-		// Join the subscriber user to the session
-		user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .publish-checkbox")).click();
-		user.getDriver().findElement(By.className("join-btn")).click();
-		user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
-
-		// Check the recording container is up and running but no ongoing recordings
-		checkDockerContainerRunning(RECORDING_IMAGE, 1);
-		Assert.assertEquals("Wrong number of recordings found", 0, OV.listRecordings().size());
-
-		// Join the publisher user to the session
-		user.getDriver().findElement(By.id("add-user-btn")).click();
-		user.getDriver().findElement(By.id("session-name-input-1")).clear();
-		user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(sessionName);
-		user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
-
-		user.getEventManager().waitUntilEventReaches("connectionCreated", 4);
-		user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
-		user.getEventManager().waitUntilEventReaches("streamCreated", 2);
-		user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
-
-		// Start recording
-		OV.fetch();
-		String recId = OV.startRecording(sessionName).getId();
-		user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
-		checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-
-		Thread.sleep(1000);
-
-		Assert.assertEquals("Wrong number of recordings found", 1, OV.listRecordings().size());
-		OV.stopRecording(recId);
-		user.getEventManager().waitUntilEventReaches("recordingStopped", 2);
-		checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-
-		Assert.assertEquals("Wrong number of sessions", 1, OV.getActiveSessions().size());
-		Session session = OV.getActiveSessions().get(0);
-		session.close();
-
-		checkDockerContainerRunning("openvidu/openvidu-recording", 0);
-
-		// 2. ALWAYS mode and recording stopped by session close up
-		user.getDriver().findElement(By.id("remove-all-users-btn")).click();
-		user.getDriver().findElement(By.id("add-user-btn")).click();
-		user.getDriver().findElement(By.id("session-name-input-0")).clear();
-		user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
-
-		user.getDriver().findElement(By.id("session-settings-btn-0")).click();
-		Thread.sleep(1000);
-		user.getDriver().findElement(By.id("recording-mode-select")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("option-ALWAYS")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("output-mode-select")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("option-COMPOSED_QUICK_START")).click();
-		Thread.sleep(500);
-		user.getDriver().findElement(By.id("save-btn")).click();
-		Thread.sleep(1000);
-
-		user.getDriver().findElement(By.className("join-btn")).click();
-		user.getEventManager().waitUntilEventReaches("connectionCreated", 5);
-		user.getEventManager().waitUntilEventReaches("accessAllowed", 2);
-		user.getEventManager().waitUntilEventReaches("streamCreated", 3);
-		user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
-		user.getEventManager().waitUntilEventReaches("recordingStarted", 3);
-
-		checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-
-		OV.fetch();
-		session = OV.getActiveSessions().get(0);
-		session.close();
-
-		checkDockerContainerRunning("openvidu/openvidu-recording", 0);
+			final String sessionName = "COMPOSED_QUICK_START_RECORDED_SESSION";
+	
+			// 1. MANUAL mode and recording explicitly stopped
+	
+			user.getDriver().findElement(By.id("add-user-btn")).click();
+			user.getDriver().findElement(By.id("session-name-input-0")).clear();
+			user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
+	
+			user.getDriver().findElement(By.id("session-settings-btn-0")).click();
+			Thread.sleep(1000);
+			user.getDriver().findElement(By.id("output-mode-select")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("option-COMPOSED_QUICK_START")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("save-btn")).click();
+			Thread.sleep(1000);
+	
+			// Join the subscriber user to the session
+			user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .publish-checkbox")).click();
+			user.getDriver().findElement(By.className("join-btn")).click();
+			user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
+	
+			// Check the recording container is up and running but no ongoing recordings
+			checkDockerContainerRunning(RECORDING_IMAGE, 1);
+			Assert.assertEquals("Wrong number of recordings found", 0, OV.listRecordings().size());
+	
+			// Join the publisher user to the session
+			user.getDriver().findElement(By.id("add-user-btn")).click();
+			user.getDriver().findElement(By.id("session-name-input-1")).clear();
+			user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(sessionName);
+			user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
+	
+			user.getEventManager().waitUntilEventReaches("connectionCreated", 4);
+			user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
+			user.getEventManager().waitUntilEventReaches("streamCreated", 2);
+			user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
+	
+			// Start recording
+			OV.fetch();
+			String recId = OV.startRecording(sessionName).getId();
+			user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
+			CustomWebhook.waitForEvent("recordingStatusChanged", 1);
+			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
+	
+			Thread.sleep(2000);
+	
+			Assert.assertEquals("Wrong number of recordings found", 1, OV.listRecordings().size());
+			OV.stopRecording(recId);
+			user.getEventManager().waitUntilEventReaches("recordingStopped", 2);
+			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
+	
+			Assert.assertEquals("Wrong number of sessions", 1, OV.getActiveSessions().size());
+			Session session = OV.getActiveSessions().get(0);
+			session.close();
+	
+			checkDockerContainerRunning("openvidu/openvidu-recording", 0);
+	
+			// 2. ALWAYS mode and recording stopped by session close up
+			user.getDriver().findElement(By.id("remove-all-users-btn")).click();
+			user.getDriver().findElement(By.id("add-user-btn")).click();
+			user.getDriver().findElement(By.id("session-name-input-0")).clear();
+			user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
+	
+			user.getDriver().findElement(By.id("session-settings-btn-0")).click();
+			Thread.sleep(1000);
+			user.getDriver().findElement(By.id("recording-mode-select")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("option-ALWAYS")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("output-mode-select")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("option-COMPOSED_QUICK_START")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("save-btn")).click();
+			Thread.sleep(1000);
+	
+			user.getDriver().findElement(By.className("join-btn")).click();
+			user.getEventManager().waitUntilEventReaches("connectionCreated", 5);
+			user.getEventManager().waitUntilEventReaches("accessAllowed", 2);
+			user.getEventManager().waitUntilEventReaches("streamCreated", 3);
+			user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
+			user.getEventManager().waitUntilEventReaches("recordingStarted", 3);
+			CustomWebhook.waitForEvent("recordingStatusChanged", 1);
+			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
+	
+			OV.fetch();
+			session = OV.getActiveSessions().get(0);
+			session.close();
+	
+			checkDockerContainerRunning("openvidu/openvidu-recording", 0);
+		} finally {
+			CustomWebhook.shutDown();
+		}
 	}
 
 	@Test

From e294ac606b48722431d15718e6037e34ba7f7caf Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 25 Sep 2020 17:36:49 +0200
Subject: [PATCH 042/435] openvidu-server: typo fixed

---
 .../java/io/openvidu/server/recording/RecordingInfoUtils.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java
index f4e2cddd..ac303add 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java
@@ -50,7 +50,7 @@ public class RecordingInfoUtils {
 			throw new OpenViduException(Code.RECORDING_FILE_EMPTY_ERROR, "The recording file is corrupted");
 		}
 		if (this.json.size() == 0) {
-			// Recording metadata from ffprobe is an emtpy JSON
+			// Recording metadata from ffprobe is an empty JSON
 			throw new OpenViduException(Code.RECORDING_FILE_EMPTY_ERROR, "The recording file is empty");
 		}
 

From 03503e586c4980c13432a717393f3a6d92b51eda Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Fri, 25 Sep 2020 23:53:21 +0200
Subject: [PATCH 043/435] openvidu-server: fixed wait for video file not empty
 in COMPOSED video recording

---
 .../service/ComposedRecordingService.java     | 34 ++++++++++++-------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index e91ef8b9..01a64264 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -393,7 +393,7 @@ public class ComposedRecordingService extends RecordingService {
 		return finalRecordingArray[0];
 	}
 
-	protected void stopAndRemoveRecordingContainer(Recording recording, String containerId, int secondsOfWait) {
+	private void stopAndRemoveRecordingContainer(Recording recording, String containerId, int secondsOfWait) {
 		// Gracefully stop ffmpeg process
 		try {
 			dockerManager.runCommandInContainer(containerId, "echo 'q' > stop");
@@ -440,21 +440,26 @@ public class ComposedRecordingService extends RecordingService {
 	}
 
 	protected void waitForVideoFileNotEmpty(Recording recording) throws OpenViduException {
-		boolean isPresent = false;
-		int i = 1;
-		int timeout = 150; // Wait for 150*150 = 22500 = 22.5 seconds
-		while (!isPresent && timeout <= 150) {
+
+		final String VIDEO_FILE = this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"
+				+ recording.getName() + ".mp4";
+
+		int SECONDS_MAX_WAIT = 15;
+		int MILLISECONDS_INTERVAL_WAIT = 100;
+		int LIMIT = SECONDS_MAX_WAIT * 1000 / MILLISECONDS_INTERVAL_WAIT;
+
+		int i = 0;
+		boolean arePresent = fileExistsAndHasBytes(VIDEO_FILE);
+		while (!arePresent && i < LIMIT) {
 			try {
-				Thread.sleep(150);
-				timeout++;
-				File f = new File(this.openviduConfig.getOpenViduRecordingPath() + recording.getId() + "/"
-						+ recording.getName() + ".mp4");
-				isPresent = ((f.isFile()) && (f.length() > 0));
+				Thread.sleep(MILLISECONDS_INTERVAL_WAIT);
+				arePresent = fileExistsAndHasBytes(VIDEO_FILE);
+				i++;
 			} catch (InterruptedException e) {
 				e.printStackTrace();
 			}
 		}
-		if (i == timeout) {
+		if (!arePresent) {
 			log.error("Recorder container failed generating video file (is empty) for session {}",
 					recording.getSessionId());
 			throw new OpenViduException(Code.RECORDING_START_ERROR_CODE,
@@ -462,7 +467,12 @@ public class ComposedRecordingService extends RecordingService {
 		}
 	}
 
-	protected void failRecordingCompletion(Recording recording, String containerId, OpenViduException e)
+	private boolean fileExistsAndHasBytes(String fileName) {
+		File f = new File(fileName);
+		return (f.exists() && f.isFile() && f.length() > 0);
+	}
+
+	private void failRecordingCompletion(Recording recording, String containerId, OpenViduException e)
 			throws OpenViduException {
 		recording.setStatus(io.openvidu.java.client.Recording.Status.failed);
 		dockerManager.removeDockerContainer(containerId, true);

From 3a61ce0f8636e8a36083e9bb263064f114db15b0 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Sat, 26 Sep 2020 01:12:25 +0200
Subject: [PATCH 044/435] openvidu-server: fix recording started client event

---
 .../server/core/SessionEventsHandler.java     | 30 +++++++------------
 .../recording/service/RecordingManager.java   | 10 +++++--
 2 files changed, 18 insertions(+), 22 deletions(-)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
index 982d96f5..bee845f2 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
@@ -22,7 +22,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
 import org.kurento.client.GenericMediaEvent;
@@ -62,9 +61,7 @@ public class SessionEventsHandler {
 	@Autowired
 	protected OpenviduConfig openviduConfig;
 
-	Map recordingsStarted = new ConcurrentHashMap<>();
-
-	ReentrantLock lock = new ReentrantLock();
+	private Map recordingsToSendClientEvents = new ConcurrentHashMap<>();
 
 	public void onSessionCreated(Session session) {
 		CDR.recordSessionCreated(session);
@@ -290,16 +287,10 @@ public class SessionEventsHandler {
 		rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result);
 
 		if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) {
-			lock.lock();
-			try {
-				Recording recording = this.recordingsStarted.remove(session.getSessionId());
-				if (recording != null) {
-					// RECORDER participant is now receiving video from the first publisher
-					this.sendRecordingStartedNotification(session, recording);
-				}
-			} finally {
-				lock.unlock();
-			}
+			recordingsToSendClientEvents.computeIfPresent(session.getSessionId(), (key, value) -> {
+				sendRecordingStartedNotification(session, value);
+				return null;
+			});
 		}
 	}
 
@@ -311,8 +302,9 @@ public class SessionEventsHandler {
 		rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject());
 	}
 
-	public void onNetworkQualityChanged(Participant participant, JsonObject params ) {
-		rpcNotificationService.sendNotification(participant.getParticipantPrivateId(), ProtocolElements.NETWORKQUALITYCHANGED_METHOD, params);
+	public void onNetworkQualityChanged(Participant participant, JsonObject params) {
+		rpcNotificationService.sendNotification(participant.getParticipantPrivateId(),
+				ProtocolElements.NETWORKQUALITYCHANGED_METHOD, params);
 	}
 
 	public void onSendMessage(Participant participant, JsonObject message, Set participants,
@@ -460,7 +452,7 @@ public class SessionEventsHandler {
 	public void sendRecordingStoppedNotification(Session session, Recording recording, EndReason reason) {
 
 		// Be sure to clean this map (this should return null)
-		this.recordingsStarted.remove(session.getSessionId());
+		recordingsToSendClientEvents.remove(session.getSessionId());
 
 		// Filter participants by roles according to "OPENVIDU_RECORDING_NOTIFICATION"
 		Set existingParticipants;
@@ -570,8 +562,8 @@ public class SessionEventsHandler {
 		this.rpcNotificationService.closeRpcSession(participantPrivateId);
 	}
 
-	public void setRecordingStarted(String sessionId, Recording recording) {
-		this.recordingsStarted.put(sessionId, recording);
+	public void storeRecordingToSendClientEvent(Recording recording) {
+		recordingsToSendClientEvents.put(recording.getSessionId(), recording);
 	}
 
 	private Set filterParticipantsByRole(OpenViduRole[] roles, Set participants) {
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 f4666ddf..2a281104 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
@@ -280,9 +280,12 @@ public class RecordingManager {
 						this.cdr.recordRecordingStatusChanged(recording, null, recording.getCreatedAt(),
 								Status.started);
 
-						if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) {
+						if (!((properties.outputMode().equals(OutputMode.COMPOSED)
+								|| properties.outputMode().equals(OutputMode.COMPOSED_QUICK_START))
+								&& properties.hasVideo())) {
 							// Directly send recording started notification for all cases except for
-							// COMPOSED recordings with video (will be sent on first RECORDER subscriber)
+							// COMPOSED/COMPOSED_QUICK_START recordings with video (will be sent on first
+							// RECORDER subscriber)
 							this.sessionHandler.sendRecordingStartedNotification(session, recording);
 						}
 						if (session.getActivePublishers() == 0) {
@@ -835,6 +838,8 @@ public class RecordingManager {
 				|| (sessionsRecordingsStarting.putIfAbsent(recording.getSessionId(), recording) != null)) {
 			log.error("Concurrent session recording initialization. Aborting this thread");
 			throw new RuntimeException("Concurrent initialization of recording " + recording.getId());
+		} else {
+			this.sessionHandler.storeRecordingToSendClientEvent(recording);
 		}
 	}
 
@@ -843,7 +848,6 @@ public class RecordingManager {
 	 * collection
 	 */
 	private void recordingFromStartingToStarted(Recording recording) {
-		this.sessionHandler.setRecordingStarted(recording.getSessionId(), recording);
 		this.sessionsRecordings.put(recording.getSessionId(), recording);
 		this.startingRecordings.remove(recording.getId());
 		this.sessionsRecordingsStarting.remove(recording.getSessionId());

From 0d00ad8fee1822affad597730bf8ef0b922e3c9b Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Sat, 26 Sep 2020 17:13:37 +0200
Subject: [PATCH 045/435] openvidu-server: fix close session with recording in
 starting status

---
 .../recording/service/RecordingManager.java   | 33 ++++++++++++++-----
 1 file changed, 25 insertions(+), 8 deletions(-)

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 2a281104..a63533c4 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
@@ -280,12 +280,10 @@ public class RecordingManager {
 						this.cdr.recordRecordingStatusChanged(recording, null, recording.getCreatedAt(),
 								Status.started);
 
-						if (!((properties.outputMode().equals(OutputMode.COMPOSED)
-								|| properties.outputMode().equals(OutputMode.COMPOSED_QUICK_START))
-								&& properties.hasVideo())) {
+						if (!(OutputMode.COMPOSED.equals(properties.outputMode()) && properties.hasVideo())) {
 							// Directly send recording started notification for all cases except for
-							// COMPOSED/COMPOSED_QUICK_START recordings with video (will be sent on first
-							// RECORDER subscriber)
+							// COMPOSED recordings with video (will be sent on first RECORDER subscriber)
+							// Both INDIVIDUAL and COMPOSED_QUICK_START should notify immediately
 							this.sessionHandler.sendRecordingStartedNotification(session, recording);
 						}
 						if (session.getActivePublishers() == 0) {
@@ -320,7 +318,19 @@ public class RecordingManager {
 			recording = this.sessionsRecordings.get(session.getSessionId());
 		}
 
-		recording = ((RecordingService) singleStreamRecordingService).sealRecordingMetadataFileAsStopped(recording);
+		if (recording == null) {
+			recording = this.sessionsRecordingsStarting.get(session.getSessionId());
+			if (recording == null) {
+				log.error("Cannot stop recording. Session {} is not being recorded", recordingId,
+						session.getSessionId());
+				return null;
+			} else {
+				// Recording is still starting
+				log.warn("Recording {} is still in \"starting\" status", recording.getId());
+			}
+		}
+
+		((RecordingService) singleStreamRecordingService).sealRecordingMetadataFileAsStopped(recording);
 
 		final long timestamp = System.currentTimeMillis();
 		this.cdr.recordRecordingStatusChanged(recording, reason, timestamp, Status.stopped);
@@ -412,8 +422,15 @@ public class RecordingManager {
 	public void stopOneIndividualStreamRecording(KurentoSession session, String streamId, long kmsDisconnectionTime) {
 		Recording recording = this.sessionsRecordings.get(session.getSessionId());
 		if (recording == null) {
-			log.error("Cannot stop recording of existing stream {}. Session {} is not being recorded", streamId,
-					session.getSessionId());
+			recording = this.sessionsRecordingsStarting.get(session.getSessionId());
+			if (recording == null) {
+				log.error("Cannot stop recording of existing stream {}. Session {} is not being recorded", streamId,
+						session.getSessionId());
+				return;
+			} else {
+				// Recording is still starting
+				log.warn("Recording {} is still in \"starting\" status", recording.getId());
+			}
 		}
 		if (OutputMode.INDIVIDUAL.equals(recording.getOutputMode())) {
 			// Stop specific RecorderEndpoint for this stream

From b5f83ea7cc9a6429c025d8e68216b431b059b64f Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Sat, 26 Sep 2020 17:14:15 +0200
Subject: [PATCH 046/435] openvidu-test-e2e: fixed composed recording tests

---
 .../test/browsers/utils/CustomWebhook.java    |   4 +
 .../test/e2e/OpenViduTestAppE2eTest.java      | 101 ++++++++++++++----
 2 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java
index 2737785f..0ecf7aca 100644
--- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java
+++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java
@@ -59,6 +59,10 @@ public class CustomWebhook {
 		CustomWebhook.context.close();
 	}
 
+	public static void clean() {
+		CustomWebhook.events.clear();
+	}
+
 	public synchronized static JsonObject waitForEvent(String eventName, int maxSecondsWait) throws Exception {
 		if (events.get(eventName) == null) {
 			events.put(eventName, new LinkedBlockingDeque<>());
diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index 6fa0317d..b787e0ce 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -1245,7 +1245,7 @@ public class OpenViduTestAppE2eTest {
 		setupBrowser("chrome");
 
 		log.info("Remote composed quick start record");
-		
+
 		CountDownLatch initLatch = new CountDownLatch(1);
 		io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
 
@@ -1258,13 +1258,14 @@ public class OpenViduTestAppE2eTest {
 			}
 
 			final String sessionName = "COMPOSED_QUICK_START_RECORDED_SESSION";
-	
+			JsonObject event;
+
 			// 1. MANUAL mode and recording explicitly stopped
-	
+
 			user.getDriver().findElement(By.id("add-user-btn")).click();
 			user.getDriver().findElement(By.id("session-name-input-0")).clear();
 			user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
-	
+
 			user.getDriver().findElement(By.id("session-settings-btn-0")).click();
 			Thread.sleep(1000);
 			user.getDriver().findElement(By.id("output-mode-select")).click();
@@ -1273,53 +1274,57 @@ public class OpenViduTestAppE2eTest {
 			Thread.sleep(500);
 			user.getDriver().findElement(By.id("save-btn")).click();
 			Thread.sleep(1000);
-	
+
 			// Join the subscriber user to the session
 			user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .publish-checkbox")).click();
 			user.getDriver().findElement(By.className("join-btn")).click();
 			user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
-	
+
 			// Check the recording container is up and running but no ongoing recordings
 			checkDockerContainerRunning(RECORDING_IMAGE, 1);
 			Assert.assertEquals("Wrong number of recordings found", 0, OV.listRecordings().size());
-	
+
 			// Join the publisher user to the session
 			user.getDriver().findElement(By.id("add-user-btn")).click();
 			user.getDriver().findElement(By.id("session-name-input-1")).clear();
 			user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(sessionName);
 			user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click();
-	
+
 			user.getEventManager().waitUntilEventReaches("connectionCreated", 4);
 			user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
 			user.getEventManager().waitUntilEventReaches("streamCreated", 2);
 			user.getEventManager().waitUntilEventReaches("streamPlaying", 2);
-	
+
 			// Start recording
 			OV.fetch();
 			String recId = OV.startRecording(sessionName).getId();
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
 			CustomWebhook.waitForEvent("recordingStatusChanged", 1);
 			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-	
+
 			Thread.sleep(2000);
-	
+
 			Assert.assertEquals("Wrong number of recordings found", 1, OV.listRecordings().size());
 			OV.stopRecording(recId);
 			user.getEventManager().waitUntilEventReaches("recordingStopped", 2);
 			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-	
+
 			Assert.assertEquals("Wrong number of sessions", 1, OV.getActiveSessions().size());
 			Session session = OV.getActiveSessions().get(0);
 			session.close();
-	
+
 			checkDockerContainerRunning("openvidu/openvidu-recording", 0);
-	
+
+			Assert.assertEquals("Wrong recording status", Recording.Status.ready,
+					OV.getRecording(sessionName).getStatus());
+
 			// 2. ALWAYS mode and recording stopped by session close up
+			CustomWebhook.clean();
 			user.getDriver().findElement(By.id("remove-all-users-btn")).click();
 			user.getDriver().findElement(By.id("add-user-btn")).click();
 			user.getDriver().findElement(By.id("session-name-input-0")).clear();
 			user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
-	
+
 			user.getDriver().findElement(By.id("session-settings-btn-0")).click();
 			Thread.sleep(1000);
 			user.getDriver().findElement(By.id("recording-mode-select")).click();
@@ -1332,21 +1337,76 @@ public class OpenViduTestAppE2eTest {
 			Thread.sleep(500);
 			user.getDriver().findElement(By.id("save-btn")).click();
 			Thread.sleep(1000);
-	
+
 			user.getDriver().findElement(By.className("join-btn")).click();
 			user.getEventManager().waitUntilEventReaches("connectionCreated", 5);
 			user.getEventManager().waitUntilEventReaches("accessAllowed", 2);
 			user.getEventManager().waitUntilEventReaches("streamCreated", 3);
 			user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 3);
-			CustomWebhook.waitForEvent("recordingStatusChanged", 1);
+
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // started
+			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
+					event.get("status").getAsString());
+
 			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
-	
+
 			OV.fetch();
 			session = OV.getActiveSessions().get(0);
 			session.close();
-	
+
 			checkDockerContainerRunning("openvidu/openvidu-recording", 0);
+
+			Assert.assertEquals("Wrong recording status", Recording.Status.ready,
+					OV.getRecording(sessionName + "-1").getStatus());
+
+			// 3. Session closed before recording started should trigger
+			CustomWebhook.clean();
+			user.getDriver().findElement(By.id("remove-all-users-btn")).click();
+			user.getDriver().findElement(By.id("add-user-btn")).click();
+			user.getDriver().findElement(By.id("session-name-input-0")).clear();
+			user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(sessionName);
+
+			user.getDriver().findElement(By.id("session-settings-btn-0")).click();
+			Thread.sleep(1000);
+			user.getDriver().findElement(By.id("recording-mode-select")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("option-ALWAYS")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("output-mode-select")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("option-COMPOSED_QUICK_START")).click();
+			Thread.sleep(500);
+			user.getDriver().findElement(By.id("save-btn")).click();
+			Thread.sleep(1000);
+
+			user.getDriver().findElement(By.className("join-btn")).click();
+			user.getEventManager().waitUntilEventReaches("connectionCreated", 6);
+			user.getEventManager().waitUntilEventReaches("accessAllowed", 3);
+			user.getEventManager().waitUntilEventReaches("streamCreated", 4);
+			user.getEventManager().waitUntilEventReaches("streamPlaying", 4);
+			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
+
+			OV.fetch();
+			session = OV.getActiveSessions().get(0);
+			session.close();
+
+			// Recording hasn't had time to start. Should trigger stopped, started, failed
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // stopped
+			Assert.assertEquals("Wrong status in recordingStatusChanged event", "stopped",
+					event.get("status").getAsString());
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // started
+			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
+					event.get("status").getAsString());
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // failed
+			Assert.assertEquals("Wrong status in recordingStatusChanged event", "failed",
+					event.get("status").getAsString());
+
+			checkDockerContainerRunning("openvidu/openvidu-recording", 0);
+
+			Assert.assertEquals("Wrong recording status", Recording.Status.failed,
+					OV.getRecording(sessionName + "-2").getStatus());
+
 		} finally {
 			CustomWebhook.shutDown();
 		}
@@ -2381,9 +2441,10 @@ public class OpenViduTestAppE2eTest {
 				.recordingLayout(RecordingLayout.BEST_FIT).resolution("1280x720").hasVideo(true).hasAudio(false)
 				.name(customRecordingName).build();
 
+		// Start recording method should block until video exists and size > 0
 		Recording recording2 = OV.startRecording(session.getSessionId(), recordingProperties);
 		recording2 = OV.stopRecording(recording2.getId());
-		Assert.assertEquals("Wrong recording status", Recording.Status.failed, recording2.getStatus());
+		Assert.assertEquals("Wrong recording status", Recording.Status.ready, recording2.getStatus());
 		OV.deleteRecording(recording2.getId());
 
 		recording2 = OV.startRecording(session.getSessionId(), recordingProperties);

From 90299411bb4f638d24df51d1ccb209b5b5e757d0 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Sat, 26 Sep 2020 18:43:49 +0200
Subject: [PATCH 047/435] openvidu-test-e2e: remoteComposedQuickStartRecordTest
 fix

---
 .../java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java   | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index b787e0ce..64d54b6e 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -1299,7 +1299,7 @@ public class OpenViduTestAppE2eTest {
 			OV.fetch();
 			String recId = OV.startRecording(sessionName).getId();
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
-			CustomWebhook.waitForEvent("recordingStatusChanged", 1);
+			CustomWebhook.waitForEvent("recordingStatusChanged", 3);
 			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
 
 			Thread.sleep(2000);
@@ -1345,7 +1345,7 @@ public class OpenViduTestAppE2eTest {
 			user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 3);
 
-			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // started
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 3); // started
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
 					event.get("status").getAsString());
 
@@ -1395,7 +1395,7 @@ public class OpenViduTestAppE2eTest {
 			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // stopped
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "stopped",
 					event.get("status").getAsString());
-			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // started
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 3); // started
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
 					event.get("status").getAsString());
 			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // failed

From ed7aaec1d5fc735ecbf36e1ffdd84dfbcb7df620 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Sat, 26 Sep 2020 18:50:00 +0200
Subject: [PATCH 048/435] openvidu-test-e2e: longer recording started event
 timeouts

---
 .../java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java   | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index 64d54b6e..f8de5a25 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -1299,7 +1299,7 @@ public class OpenViduTestAppE2eTest {
 			OV.fetch();
 			String recId = OV.startRecording(sessionName).getId();
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 2);
-			CustomWebhook.waitForEvent("recordingStatusChanged", 3);
+			CustomWebhook.waitForEvent("recordingStatusChanged", 5);
 			checkDockerContainerRunning("openvidu/openvidu-recording", 1);
 
 			Thread.sleep(2000);
@@ -1345,7 +1345,7 @@ public class OpenViduTestAppE2eTest {
 			user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
 			user.getEventManager().waitUntilEventReaches("recordingStarted", 3);
 
-			event = CustomWebhook.waitForEvent("recordingStatusChanged", 3); // started
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 5); // started
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
 					event.get("status").getAsString());
 
@@ -1395,7 +1395,7 @@ public class OpenViduTestAppE2eTest {
 			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // stopped
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "stopped",
 					event.get("status").getAsString());
-			event = CustomWebhook.waitForEvent("recordingStatusChanged", 3); // started
+			event = CustomWebhook.waitForEvent("recordingStatusChanged", 5); // started
 			Assert.assertEquals("Wrong status in recordingStatusChanged event", "started",
 					event.get("status").getAsString());
 			event = CustomWebhook.waitForEvent("recordingStatusChanged", 1); // failed

From 92956887b5ed66b051e7efdd3d755a84a8b28938 Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Mon, 28 Sep 2020 10:06:16 +0200
Subject: [PATCH 049/435] Deployment: ELK Updates - Filebeat can be used
 externally with and without de security - Minor fix in Label ELK label
 description in CF template

---
 ...fn-openvidu-server-pro-no-market.yaml.template |  2 +-
 .../openvidu-server-pro/beats/filebeat.yml        |  2 --
 .../openvidu-server-pro/docker-compose.yml        | 15 ++++++++-------
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
index be09fbd3..25489e9d 100644
--- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
+++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template
@@ -213,7 +213,7 @@ Metadata:
           - OpenViduSecret
           - MediaNodesStartNumber
       - Label:
-          default: Kibana configuration
+          default: Elasticsearch and Kibana configuration
         Parameters:
           - ElasticsearchUser
           - ElasticsearchPassword
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
index 3581884d..1cbe8027 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
@@ -17,8 +17,6 @@ processors:
 output:
   elasticsearch:
     hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"]
-    username: ${ELASTICSEARCH_USERNAME}
-    password: ${ELASTICSEARCH_PASSWORD}
     indices:
       - index: "filebeat-redis-%{+yyyy.MM.dd}"
         when.or:
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
index 0eeafe55..12b28d04 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
@@ -88,10 +88,6 @@ services:
     elasticsearch:
         image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0
         restart: always
-        command: 
-            - '/bin/bash'
-            - '-c'
-            - '/usr/share/elasticsearch/bin/elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} -p ${ELASTICSEARCH_PASSWORD} -r superuser; /tini -- /usr/local/bin/docker-entrypoint.sh'
         environment:
             - discovery.type=single-node
             - xpack.security.enabled=true
@@ -99,6 +95,10 @@ services:
             - 9200:9200
         volumes:
             - ./elasticsearch:/usr/share/elasticsearch/data
+        command: > 
+            /bin/bash -c "elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} 
+            -p ${ELASTICSEARCH_PASSWORD} -r superuser;
+            docker-entrypoint.sh"
 
     kibana:
         image: docker.elastic.co/kibana/kibana:7.8.0
@@ -116,11 +116,12 @@ services:
         restart: always
         user: root
         environment:
-            - ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME}
-            - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD}
             - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200}
         volumes:
             - ./beats/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
             - /var/lib/docker:/var/lib/docker:ro
             - /var/run/docker.sock:/var/run/docker.sock
-        command: filebeat -e -strict.perms=false
+        command: >
+            /bin/bash -c "filebeat -e -strict.perms=false
+            `if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi`
+            `if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`"

From d039f71fdb2a601d36aa9d864e1bbbafded0e79f Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Mon, 28 Sep 2020 11:03:24 +0200
Subject: [PATCH 050/435] New composed_quick_start.sh logic to wait for the
 ffmpeg process to end

---
 .../scripts/composed_quick_start.sh                  | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh b/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh
index 9ded1ae6..cfbb96c4 100644
--- a/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh
+++ b/openvidu-server/docker/openvidu-recording/scripts/composed_quick_start.sh
@@ -96,6 +96,9 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--start-recording" ]]; then
             <./stop ffmpeg -y -f alsa -i pulse -f x11grab -draw_mouse 0 -framerate $FRAMERATE -video_size $RESOLUTION -i :$DISPLAY_NUM -c:a aac -c:v libx264 -preset ultrafast -crf 28 -refs 4 -qmin 4 -pix_fmt yuv420p -filter:v fps=$FRAMERATE "/recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT"
         fi
 
+        # Warn the stop thread about ffmpeg process being completed
+        echo "ffmpeg-completed" > /tmp/$VIDEO_ID-completed.txt
+
     } 2>&1 | tee -a /tmp/container-start-recording.log
 
 elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--stop-recording" ]]; then
@@ -109,10 +112,17 @@ elif [[ "${COMPOSED_QUICK_START_ACTION}" == "--stop-recording" ]]; then
             exit 0
         fi
 
-        # Stop and wait ffmpeg process to be stopped
+        # Stop ffmpeg process
         FFMPEG_PID=$(pgrep ffmpeg)
         echo 'q' > stop && tail --pid=$FFMPEG_PID -f /dev/null
 
+        ## Wait for the ffmpeg process to be finished
+        until [ -f /tmp/$VIDEO_ID-completed.txt ]
+        do
+            # Check 20 times per second
+            sleep 0.05
+        done
+        rm -f /tmp/$VIDEO_ID-completed.txt
 
         ### Generate video report file ###
         ffprobe -v quiet -print_format json -show_format -show_streams /recordings/$VIDEO_ID/$VIDEO_NAME.$VIDEO_FORMAT > /recordings/$VIDEO_ID/$VIDEO_ID.info

From 521909c931d044e2f67390e82b8d9c5040c924db Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Mon, 28 Sep 2020 18:26:37 +0200
Subject: [PATCH 051/435] openvidu-server: DockerManager.close

---
 .../server/recording/service/RecordingManager.java     |  7 ++++---
 .../java/io/openvidu/server/utils/DockerManager.java   | 10 +++++++++-
 2 files changed, 13 insertions(+), 4 deletions(-)

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 a63533c4..21cfc13e 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
@@ -216,10 +216,9 @@ public class RecordingManager {
 
 	public void checkRecordingRequirements(String openviduRecordingPath, String openviduRecordingCustomLayout)
 			throws OpenViduException {
-		if (dockerManager == null) {
-			this.dockerManager = new DockerManager();
-		}
+		DockerManager dockerManager = null;
 		try {
+			dockerManager = new DockerManager();
 			dockerManager.checkDockerEnabled();
 		} catch (OpenViduException e) {
 			String message = e.getMessage();
@@ -238,6 +237,8 @@ public class RecordingManager {
 			}
 			log.error(message);
 			throw e;
+		} finally {
+			dockerManager.close();
 		}
 		this.checkRecordingPaths(openviduRecordingPath, openviduRecordingCustomLayout);
 	}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java b/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
index c616729b..f3ad46c4 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/utils/DockerManager.java
@@ -57,7 +57,7 @@ public class DockerManager {
 
 	private static final Logger log = LoggerFactory.getLogger(DockerManager.class);
 
-	DockerClient dockerClient;
+	private DockerClient dockerClient;
 
 	public DockerManager() {
 		DockerClientConfig config = DefaultDockerClientConfig.createDefaultConfigBuilder().build();
@@ -246,6 +246,14 @@ public class DockerManager {
 		return containerInfo.getConfig().getLabels();
 	}
 
+	public void close() {
+		try {
+			this.dockerClient.close();
+		} catch (IOException e) {
+			log.error("Error closing DockerClient: {}", e.getMessage());
+		}
+	}
+
 	static public String getDockerGatewayIp() {
 		try {
 			return CommandExecutor.execCommand(5000, "/bin/sh", "-c",

From 709d7d2a5c369d26b380bd6338362b6c337d330c Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Mon, 28 Sep 2020 20:02:21 +0200
Subject: [PATCH 052/435] deployment-openvidu-pro: Updated to work with
 external ELK services

---
 .../pro/docker-compose/media-node/beats/filebeat.yml         | 5 +----
 .../media-node/beats/metricbeat-elasticsearch.yml            | 3 ---
 .../docker-compose/media-node/beats/metricbeat-openvidu.yml  | 3 ++-
 .../docker-compose/openvidu-server-pro/beats/filebeat.yml    | 3 ++-
 .../docker-compose/openvidu-server-pro/docker-compose.yml    | 2 +-
 5 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml
index a6e22122..c09e980b 100644
--- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml
+++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml
@@ -20,10 +20,8 @@ processors:
       fields:
         ip: ${MEDIA_NODE_IP}
 
-
 output:
   elasticsearch:
-    hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
     indices:
       - index: "filebeat-kurento-%{+yyyy.MM.dd}"
         when.or:
@@ -37,5 +35,4 @@ output:
 
 logging.json: true
 logging.metrics.enabled: false
-setup.ilm.enabled: true
-setup.ilm.policy_name: "openvidu_cleanup_policy"
\ No newline at end of file
+setup.ilm.enabled: false
\ No newline at end of file
diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml
index 0ddb27e9..d30028c1 100644
--- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml
+++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml
@@ -1,6 +1,3 @@
-output:
-  elasticsearch:
-    hosts: ["${OPENVIDU_SERVER_PRO_IP}:9200"]
 metricbeat.modules:
   - module: system
     metricsets: [cpu]
diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml
index bbd5f726..7f01c1dc 100644
--- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml
+++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-openvidu.yml
@@ -9,4 +9,5 @@ metricbeat.modules:
     cpu.metrics: [normalized_percentages]
 fields: {ip: "${MEDIA_NODE_IP}"}
 pipeline:
-  queue.mem.events: 0
\ No newline at end of file
+  queue.mem.events: 0
+setup.ilm.enabled: false
\ No newline at end of file
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
index 1cbe8027..42fc9710 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml
@@ -29,4 +29,5 @@ output:
 
 
 logging.json: true
-logging.metrics.enabled: false
\ No newline at end of file
+logging.metrics.enabled: false
+setup.ilm.enabled: false
\ No newline at end of file
diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
index 12b28d04..33b369cf 100644
--- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml
@@ -111,7 +111,7 @@ services:
             - 5601:5601
 
     filebeat:
-        image: docker.elastic.co/beats/filebeat:7.8.0
+        image: docker.elastic.co/beats/filebeat-oss:7.8.0
         network_mode: host
         restart: always
         user: root

From a852a826faa17d43abebafa013d49db73a9593a6 Mon Sep 17 00:00:00 2001
From: cruizba 
Date: Mon, 28 Sep 2020 20:06:56 +0200
Subject: [PATCH 053/435] deployment-openvidu-pro: Use oss beats services

---
 .../deployments/pro/docker-compose/media-node/.env            | 4 ++--
 .../pro/docker-compose/media-node/docker-compose.yml          | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/.env b/openvidu-server/deployments/pro/docker-compose/media-node/.env
index 704c9211..fd244380 100644
--- a/openvidu-server/deployments/pro/docker-compose/media-node/.env
+++ b/openvidu-server/deployments/pro/docker-compose/media-node/.env
@@ -21,10 +21,10 @@
 # -------------------------------
 # Docker hub kurento media server: https://www.docker.elastic.co/
 # Uncomment the next line and define this variable with METRICBEAT_IMAGE image that you want use
-# METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat:7.8.0
+# METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0
 
 # FileBeat ElasticSearch Image
 # -------------------------------
 # Docker hub kurento media server: https://www.docker.elastic.co/
 # Uncomment the next line and define this variable with FILEBEAT_IMAGE image that you want use
-# FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat:7.8.0
\ No newline at end of file
+# FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0
\ No newline at end of file
diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml
index 2f0a872d..5e568d0b 100644
--- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml
+++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml
@@ -26,8 +26,8 @@ services:
         environment:
             - KMS_IMAGE=${KMS_IMAGE:-kurento/kurento-media-server:6.14.0}
             - KMS_DEBUG_LEVEL=${KMS_DEBUG_LEVEL:-}
-            - METRICBEAT_IMAGE=${METRICBEAT_IMAGE:-docker.elastic.co/beats/metricbeat:7.8.0}
-            - FILEBEAT_IMAGE=${FILEBEAT_IMAGE:-docker.elastic.co/beats/filebeat:7.8.0}
+            - METRICBEAT_IMAGE=${METRICBEAT_IMAGE:-docker.elastic.co/beats/metricbeat-oss:7.8.0}
+            - FILEBEAT_IMAGE=${FILEBEAT_IMAGE:-docker.elastic.co/beats/filebeat-oss:7.8.0}
         ports:
             - 3000:3000
         volumes:

From 12f215ddd9571c5ae9394386f4ed9032526ebcf5 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Tue, 29 Sep 2020 11:59:30 +0200
Subject: [PATCH 054/435] openvidu-browser: fix unexpected undefined exception
 on reconnected callback

---
 openvidu-browser/src/OpenVidu/OpenVidu.ts | 40 +++++++++++++----------
 openvidu-browser/src/OpenVidu/Session.ts  |  2 +-
 2 files changed, 23 insertions(+), 19 deletions(-)

diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts
index 8820a72c..bfb971e6 100644
--- a/openvidu-browser/src/OpenVidu/OpenVidu.ts
+++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts
@@ -337,10 +337,10 @@ export class OpenVidu {
     const family = platform.os!!.family;
     const userAgent = !!platform.ua ? platform.ua : navigator.userAgent;
 
-    if(this.isIPhoneOrIPad(userAgent)) {
-        if(this.isIOSWithSafari(userAgent) || platform['isIonicIos']){
-          return 1;
-        }
+    if (this.isIPhoneOrIPad(userAgent)) {
+      if (this.isIOSWithSafari(userAgent) || platform['isIonicIos']) {
+        return 1;
+      }
       return 0;
     }
 
@@ -377,7 +377,7 @@ export class OpenVidu {
     }
 
     if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Electron') &&
-       (browser === 'Safari' && version < 13)) {
+      (browser === 'Safari' && version < 13)) {
       return 0;
     } else {
       return 1;
@@ -1025,17 +1025,21 @@ export class OpenVidu {
   private reconnectedCallback(): void {
     logger.warn('Websocket reconnected');
     if (this.isRoomAvailable()) {
-      this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
-        if (!!error) {
-          logger.error(error);
-          logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
-          this.session.onLostConnection("networkDisconnect");
-          this.jsonRpcClient.close(4101, "Reconnection fault");
-        } else {
-          this.jsonRpcClient.resetPing();
-          this.session.onRecoveredConnection();
-        }
-      });
+      if (!!this.session.connection) {
+        this.sendRequest('connect', { sessionId: this.session.connection.rpcSessionId }, (error, response) => {
+          if (!!error) {
+            logger.error(error);
+            logger.warn('Websocket was able to reconnect to OpenVidu Server, but your Connection was already destroyed due to timeout. You are no longer a participant of the Session and your media streams have been destroyed');
+            this.session.onLostConnection("networkDisconnect");
+            this.jsonRpcClient.close(4101, "Reconnection fault");
+          } else {
+            this.jsonRpcClient.resetPing();
+            this.session.onRecoveredConnection();
+          }
+        });
+      } else {
+        logger.warn('There was no previous connection when running reconnection callback');
+      }
     } else {
       alert('Connection error. Please reload page.');
     }
@@ -1064,9 +1068,9 @@ export class OpenVidu {
     return isIPad || isIPhone;
   }
 
-  private isIOSWithSafari(userAgent): boolean{
+  private isIOSWithSafari(userAgent): boolean {
     return /\b(\w*Apple\w*)\b/.test(navigator.vendor) && /\b(\w*Safari\w*)\b/.test(userAgent)
-          && !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent);
+      && !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent);
   }
 
 
diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts
index f6650a68..09f5a38a 100644
--- a/openvidu-browser/src/OpenVidu/Session.ts
+++ b/openvidu-browser/src/OpenVidu/Session.ts
@@ -987,7 +987,7 @@ export class Session extends EventDispatcher {
      */
     onLostConnection(reason: string): void {
         logger.warn('Lost connection in Session ' + this.sessionId);
-        if (!!this.sessionId && !this.connection.disposed) {
+        if (!!this.sessionId && !!this.connection && !this.connection.disposed) {
             this.leave(true, reason);
         }
     }

From 6a8e85c763d5c96291c5bdf73fc6ec555cb34fe3 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Tue, 29 Sep 2020 14:20:45 +0200
Subject: [PATCH 055/435] openvidu-server:
 KmsManager#atLeastOneConnectedAndRunningKms

---
 .../java/io/openvidu/server/kurento/kms/KmsManager.java   | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java
index f93112c3..a77c718f 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -121,6 +122,13 @@ public abstract class KmsManager {
 		}
 	}
 
+	public synchronized boolean atLeastOneConnectedAndRunningKms() {
+		Optional optional = this.kmss.values().stream()
+				.filter(kms -> kms.isKurentoClientConnected() && mediaNodeStatusManager.isRunning(kms.getId()))
+				.findFirst();
+		return optional.isPresent();
+	}
+
 	public synchronized List getKmssSortedByLoad() {
 		List kmsLoads = getKmsLoads();
 		Collections.sort(kmsLoads);

From 0254f0f0785079035f78cc92eb369aa42eef266a Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Tue, 29 Sep 2020 15:02:56 +0200
Subject: [PATCH 056/435] openvidu-server: TokenGenerator refactoring

---
 .../io/openvidu/server/OpenViduServer.java    |  3 +-
 .../openvidu/server/core/TokenGenerator.java  | 39 +++++++++++-
 .../server/core/TokenGeneratorDefault.java    | 62 -------------------
 3 files changed, 37 insertions(+), 67 deletions(-)
 delete mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java

diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
index f1acf638..b1fe5e82 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
@@ -50,7 +50,6 @@ import io.openvidu.server.config.OpenviduConfig.Error;
 import io.openvidu.server.core.SessionEventsHandler;
 import io.openvidu.server.core.SessionManager;
 import io.openvidu.server.core.TokenGenerator;
-import io.openvidu.server.core.TokenGeneratorDefault;
 import io.openvidu.server.coturn.CoturnCredentialsService;
 import io.openvidu.server.coturn.CoturnCredentialsServiceFactory;
 import io.openvidu.server.kurento.core.KurentoParticipantEndpointConfig;
@@ -160,7 +159,7 @@ public class OpenViduServer implements JsonRpcConfigurer {
 	@ConditionalOnMissingBean
 	@DependsOn("openviduConfig")
 	public TokenGenerator tokenGenerator() {
-		return new TokenGeneratorDefault();
+		return new TokenGenerator();
 	}
 
 	@Bean
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java
index 472f4ee8..6320f7bf 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java
@@ -17,12 +17,45 @@
 
 package io.openvidu.server.core;
 
+import org.apache.commons.lang3.RandomStringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import io.openvidu.java.client.OpenViduRole;
+import io.openvidu.server.OpenViduServer;
+import io.openvidu.server.config.OpenviduBuildInfo;
+import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.coturn.CoturnCredentialsService;
+import io.openvidu.server.coturn.TurnCredentials;
 import io.openvidu.server.kurento.core.KurentoTokenOptions;
 
-public interface TokenGenerator {
+public class TokenGenerator {
+
+	@Autowired
+	private CoturnCredentialsService coturnCredentialsService;
+
+	@Autowired
+	protected OpenviduConfig openviduConfig;
+
+	@Autowired
+	protected OpenviduBuildInfo openviduBuildConfig;
 
 	public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata,
-			KurentoTokenOptions kurentoTokenOptions) throws Exception;
-
+			KurentoTokenOptions kurentoTokenOptions) throws Exception {
+		String token = OpenViduServer.wsUrl;
+		token += "?sessionId=" + sessionId;
+		token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
+				+ RandomStringUtils.randomAlphanumeric(15);
+		token += "&role=" + role.name();
+		token += "&version=" + openviduBuildConfig.getOpenViduServerVersion();
+		TurnCredentials turnCredentials = null;
+		if (this.openviduConfig.isTurnadminAvailable()) {
+			turnCredentials = coturnCredentialsService.createUser();
+			if (turnCredentials != null) {
+				token += "&coturnIp=" + openviduConfig.getCoturnIp();
+				token += "&turnUsername=" + turnCredentials.getUsername();
+				token += "&turnCredential=" + turnCredentials.getCredential();
+			}
+		}
+		return new Token(token, role, serverMetadata, turnCredentials, kurentoTokenOptions);
+	}
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java
deleted file mode 100644
index eeb46563..00000000
--- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGeneratorDefault.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io)
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package io.openvidu.server.core;
-
-import org.apache.commons.lang3.RandomStringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import io.openvidu.java.client.OpenViduRole;
-import io.openvidu.server.OpenViduServer;
-import io.openvidu.server.config.OpenviduBuildInfo;
-import io.openvidu.server.config.OpenviduConfig;
-import io.openvidu.server.coturn.CoturnCredentialsService;
-import io.openvidu.server.coturn.TurnCredentials;
-import io.openvidu.server.kurento.core.KurentoTokenOptions;
-
-public class TokenGeneratorDefault implements TokenGenerator {
-
-	@Autowired
-	private CoturnCredentialsService coturnCredentialsService;
-
-	@Autowired
-	protected OpenviduConfig openviduConfig;
-
-	@Autowired
-	protected OpenviduBuildInfo openviduBuildConfig;
-
-	@Override
-	public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata,
-			KurentoTokenOptions kurentoTokenOptions) throws Exception {
-		String token = OpenViduServer.wsUrl;
-		token += "?sessionId=" + sessionId;
-		token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
-				+ RandomStringUtils.randomAlphanumeric(15);
-		token += "&role=" + role.name();
-		token += "&version=" + openviduBuildConfig.getOpenViduServerVersion();
-		TurnCredentials turnCredentials = null;
-		if (this.openviduConfig.isTurnadminAvailable()) {
-			turnCredentials = coturnCredentialsService.createUser();
-			if (turnCredentials != null) {
-				token += "&coturnIp=" + openviduConfig.getCoturnIp();
-				token += "&turnUsername=" + turnCredentials.getUsername();
-				token += "&turnCredential=" + turnCredentials.getCredential();
-			}
-		}
-		return new Token(token, role, serverMetadata, turnCredentials, kurentoTokenOptions);
-	}
-}

From 9536b4bcf19e61ceae36c6eaf18bd623188412f5 Mon Sep 17 00:00:00 2001
From: wm-david-gomez 
Date: Wed, 30 Sep 2020 09:42:16 +0200
Subject: [PATCH 057/435] Resolve promises in pause and resume methods from
 LocalRecorder

---
 openvidu-browser/src/OpenVidu/LocalRecorder.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/openvidu-browser/src/OpenVidu/LocalRecorder.ts b/openvidu-browser/src/OpenVidu/LocalRecorder.ts
index 958cd913..9a9af25f 100644
--- a/openvidu-browser/src/OpenVidu/LocalRecorder.ts
+++ b/openvidu-browser/src/OpenVidu/LocalRecorder.ts
@@ -170,6 +170,7 @@ export class LocalRecorder {
                 }
                 this.mediaRecorder.pause();
                 this.state = LocalRecorderState.PAUSED;
+                resolve();
             } catch (error) {
                 reject(error);
             }
@@ -188,6 +189,7 @@ export class LocalRecorder {
                 }
                 this.mediaRecorder.resume();
                 this.state = LocalRecorderState.RECORDING;
+                resolve();
             } catch (error) {
                 reject(error);
             }

From 6b6d6c2ba48fa23c9b096531dc4fc2a1d4848992 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Wed, 30 Sep 2020 13:07:19 +0200
Subject: [PATCH 058/435] openvidu-browser: sessionDisconnected event on failed
 reconnection with no Connection

---
 openvidu-browser/src/OpenVidu/OpenVidu.ts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts
index bfb971e6..49f028e7 100644
--- a/openvidu-browser/src/OpenVidu/OpenVidu.ts
+++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts
@@ -19,6 +19,7 @@ import { LocalRecorder } from './LocalRecorder';
 import { Publisher } from './Publisher';
 import { Session } from './Session';
 import { Stream } from './Stream';
+import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisconnectedEvent';
 import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent';
 import { Device } from '../OpenViduInternal/Interfaces/Public/Device';
 import { OpenViduAdvancedConfiguration } from '../OpenViduInternal/Interfaces/Public/OpenViduAdvancedConfiguration';
@@ -1039,6 +1040,10 @@ export class OpenVidu {
         });
       } else {
         logger.warn('There was no previous connection when running reconnection callback');
+        // Make Session object dispatch 'sessionDisconnected' event
+        const sessionDisconnectEvent = new SessionDisconnectedEvent(this.session, 'networkDisconnect');
+        this.session.ee.emitEvent('sessionDisconnected', [sessionDisconnectEvent]);
+        sessionDisconnectEvent.callDefaultBehavior();
       }
     } else {
       alert('Connection error. Please reload page.');

From 04c012a327c6ebde2dc91157ef33826086bfa582 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Wed, 30 Sep 2020 18:53:39 +0200
Subject: [PATCH 059/435] openvidu-server: return connectionId on POST
 /api/tokens

---
 .../java/io/openvidu/server/core/Session.java | 16 +++++++++++++-
 .../openvidu/server/core/SessionManager.java  | 22 ++++++++-----------
 .../java/io/openvidu/server/core/Token.java   | 14 +++++++-----
 .../kurento/core/KurentoSessionManager.java   | 18 ++++++++++-----
 .../server/rest/SessionRestController.java    | 15 +++++++++----
 .../io/openvidu/server/rpc/RpcHandler.java    |  3 +++
 .../src/main/resources/application.properties |  2 +-
 7 files changed, 61 insertions(+), 29 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 7edf339c..ddcd6759 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
@@ -18,6 +18,8 @@
 package io.openvidu.server.core;
 
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -157,13 +159,25 @@ public class Session implements SessionInterface {
 		this.tokens.put(token.getToken(), token);
 	}
 
+	public boolean deleteTokenFromConnectionId(String connectionId) {
+		boolean deleted = false;
+		Iterator> iterator = this.tokens.entrySet().iterator();
+		while (iterator.hasNext() && !deleted) {
+			Entry entry = iterator.next();
+			if (connectionId.equals(entry.getValue().getConnetionId())) {
+				iterator.remove();
+				deleted = true;
+			}
+		}
+		return deleted;
+	}
+
 	public boolean isTokenValid(String token) {
 		return this.tokens.containsKey(token);
 	}
 
 	public Token consumeToken(String token) {
 		Token tokenObj = this.tokens.remove(token);
-		showTokens("Token consumed");
 		return tokenObj;
 	}
 
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java
index 91dd8fd6..1b1bc4d6 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java
@@ -32,7 +32,6 @@ import java.util.stream.Collectors;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 
-import org.apache.commons.lang3.RandomStringUtils;
 import org.kurento.jsonrpc.message.Request;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -295,7 +294,7 @@ public abstract class SessionManager {
 		return sessionNotActive;
 	}
 
-	public String newToken(Session session, OpenViduRole role, String serverMetadata,
+	public Token newToken(Session session, OpenViduRole role, String serverMetadata,
 			KurentoTokenOptions kurentoTokenOptions) throws Exception {
 		if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) {
 			log.error("Data invalid format");
@@ -305,7 +304,7 @@ public abstract class SessionManager {
 				kurentoTokenOptions);
 		session.storeToken(tokenObj);
 		session.showTokens("Token created");
-		return tokenObj.getToken();
+		return tokenObj;
 	}
 
 	public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception {
@@ -355,17 +354,13 @@ public abstract class SessionManager {
 
 	public Participant newParticipant(String sessionId, String participantPrivatetId, Token token,
 			String clientMetadata, GeoLocation location, String platform, String finalUserId) {
+
 		if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
-			String participantPublicId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID
-					+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9);
-			Participant p = new Participant(finalUserId, participantPrivatetId, participantPublicId, sessionId, token,
-					clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null);
-			while (this.sessionidParticipantpublicidParticipant.get(sessionId).putIfAbsent(participantPublicId,
-					p) != null) {
-				participantPublicId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID
-						+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9);
-				p.setParticipantPublicId(participantPublicId);
-			}
+
+			Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnetionId(), sessionId,
+					token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null);
+
+			this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p);
 
 			this.sessionidFinalUsers.get(sessionId).computeIfAbsent(finalUserId, k -> {
 				log.info("Participant {} of session {} is a final user connecting to this session for the first time",
@@ -374,6 +369,7 @@ public abstract class SessionManager {
 			}).addConnectionIfAbsent(p);
 
 			return p;
+
 		} else {
 			throw new OpenViduException(Code.ROOM_NOT_FOUND_ERROR_CODE, sessionId);
 		}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
index feeb99af..55330548 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
@@ -17,6 +17,8 @@
 
 package io.openvidu.server.core;
 
+import org.apache.commons.lang3.RandomStringUtils;
+
 import io.openvidu.java.client.OpenViduRole;
 import io.openvidu.server.coturn.TurnCredentials;
 import io.openvidu.server.kurento.core.KurentoTokenOptions;
@@ -27,12 +29,10 @@ public class Token {
 	private OpenViduRole role;
 	private String serverMetadata = "";
 	private TurnCredentials turnCredentials;
-
 	private KurentoTokenOptions kurentoTokenOptions;
 
-	public Token(String token) {
-		this.token = token;
-	}
+	private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID
+			+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9);
 
 	public Token(String token, OpenViduRole role, String serverMetadata, TurnCredentials turnCredentials,
 			KurentoTokenOptions kurentoTokenOptions) {
@@ -50,7 +50,7 @@ public class Token {
 	public void setToken(String token) {
 		this.token = token;
 	}
-	
+
 	public OpenViduRole getRole() {
 		return role;
 	}
@@ -67,6 +67,10 @@ public class Token {
 		return kurentoTokenOptions;
 	}
 
+	public String getConnetionId() {
+		return connectionId;
+	}
+
 	@Override
 	public String toString() {
 		if (this.role != null)
diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java
index cad0d229..222729d4 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java
@@ -30,7 +30,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import io.openvidu.java.client.*;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.kurento.client.GenericMediaElement;
 import org.kurento.client.IceCandidate;
@@ -48,6 +47,12 @@ import com.google.gson.JsonObject;
 import io.openvidu.client.OpenViduException;
 import io.openvidu.client.OpenViduException.Code;
 import io.openvidu.client.internal.ProtocolElements;
+import io.openvidu.java.client.MediaMode;
+import io.openvidu.java.client.Recording;
+import io.openvidu.java.client.RecordingLayout;
+import io.openvidu.java.client.RecordingMode;
+import io.openvidu.java.client.RecordingProperties;
+import io.openvidu.java.client.SessionProperties;
 import io.openvidu.server.core.EndReason;
 import io.openvidu.server.core.FinalUser;
 import io.openvidu.server.core.IdentifierPrefixes;
@@ -142,7 +147,8 @@ public class KurentoSessionManager extends SessionManager {
 
 			// If Recording default layout is COMPOSED_QUICK_START
 			Recording.OutputMode defaultOutputMode = kSession.getSessionProperties().defaultOutputMode();
-			if (openviduConfig.isRecordingModuleEnabled() && defaultOutputMode.equals(Recording.OutputMode.COMPOSED_QUICK_START)) {
+			if (openviduConfig.isRecordingModuleEnabled()
+					&& defaultOutputMode.equals(Recording.OutputMode.COMPOSED_QUICK_START)) {
 				recordingManager.startComposedQuickStartContainer(kSession);
 			}
 
@@ -300,10 +306,12 @@ public class KurentoSessionManager extends SessionManager {
 
 						} else if (remainingParticipants.size() == 1 && openviduConfig.isRecordingModuleEnabled()
 								&& MediaMode.ROUTED.equals(session.getSessionProperties().mediaMode())
-								&& session.getSessionProperties().defaultOutputMode().equals(Recording.OutputMode.COMPOSED_QUICK_START)
+								&& session.getSessionProperties().defaultOutputMode()
+										.equals(Recording.OutputMode.COMPOSED_QUICK_START)
 								&& ProtocolElements.RECORDER_PARTICIPANT_PUBLICID
-								.equals(remainingParticipants.iterator().next().getParticipantPublicId())) {
-							// If no recordings are active in COMPOSED_QUICK_START output mode, stop container
+										.equals(remainingParticipants.iterator().next().getParticipantPublicId())) {
+							// If no recordings are active in COMPOSED_QUICK_START output mode, stop
+							// container
 							recordingManager.stopComposedQuickStartContainer(session, reason);
 						}
 					}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index a8f8adf7..3af12ac1 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -61,6 +61,7 @@ import io.openvidu.server.core.IdentifierPrefixes;
 import io.openvidu.server.core.Participant;
 import io.openvidu.server.core.Session;
 import io.openvidu.server.core.SessionManager;
+import io.openvidu.server.core.Token;
 import io.openvidu.server.kurento.core.KurentoMediaOptions;
 import io.openvidu.server.kurento.core.KurentoTokenOptions;
 import io.openvidu.server.recording.Recording;
@@ -280,7 +281,12 @@ public class SessionRestController {
 			this.sessionManager.evictParticipant(participant, null, null, EndReason.forceDisconnectByServer);
 			return new ResponseEntity<>(HttpStatus.NO_CONTENT);
 		} else {
-			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+			// Try to delete unused token
+			if (session.deleteTokenFromConnectionId(participantPublicId)) {
+				return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+			} else {
+				return new ResponseEntity<>(HttpStatus.NOT_FOUND);
+			}
 		}
 	}
 
@@ -387,14 +393,15 @@ public class SessionRestController {
 		// While closing a session tokens can't be generated
 		if (session.closingLock.readLock().tryLock()) {
 			try {
-				String token = sessionManager.newToken(session, role, metadata, kurentoTokenOptions);
+				Token token = sessionManager.newToken(session, role, metadata, kurentoTokenOptions);
 
 				JsonObject responseJson = new JsonObject();
-				responseJson.addProperty("id", token);
+				responseJson.addProperty("id", token.getToken());
+				responseJson.addProperty("connectionId", token.getConnetionId());
 				responseJson.addProperty("session", sessionId);
 				responseJson.addProperty("role", role.toString());
 				responseJson.addProperty("data", metadata);
-				responseJson.addProperty("token", token);
+				responseJson.addProperty("token", token.getToken());
 
 				if (kurentoOptions != null) {
 					JsonObject kurentoOptsResponse = new JsonObject();
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java
index bece2d68..7c66e35c 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java
@@ -257,6 +257,9 @@ public class RpcHandler extends DefaultJsonRpcHandler {
 
 		Token tokenObj = session.consumeToken(token);
 		if (tokenObj != null) {
+
+			session.showTokens("Token consumed");
+
 			String clientMetadata = getStringParam(request, ProtocolElements.JOINROOM_METADATA_PARAM);
 			if (sessionManager.formatChecker.isServerMetadataFormatCorrect(clientMetadata)) {
 
diff --git a/openvidu-server/src/main/resources/application.properties b/openvidu-server/src/main/resources/application.properties
index 5fdf2cc9..9f9c3c66 100644
--- a/openvidu-server/src/main/resources/application.properties
+++ b/openvidu-server/src/main/resources/application.properties
@@ -22,7 +22,7 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr
 OPENVIDU_WEBHOOK=false
 OPENVIDU_WEBHOOK_ENDPOINT=
 OPENVIDU_WEBHOOK_HEADERS=[]
-OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined","participantLeft","webrtcConnectionCreated","webrtcConnectionDestroyed","recordingStatusChanged","filterEventDispatched","mediaNodeStatusChanged"]
+OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined","participantLeft","webrtcConnectionCreated","webrtcConnectionDestroyed","recordingStatusChanged","filterEventDispatched","mediaNodeStatusChanged","autoscaling"]
 
 OPENVIDU_RECORDING=false
 OPENVIDU_RECORDING_DEBUG=false

From bdd54e01e5e51137f53fe4e57e1b09b636a4442d Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 1 Oct 2020 13:35:05 +0200
Subject: [PATCH 060/435] openvidu-server: new request mapping paths

---
 .../io/openvidu/server/OpenViduServer.java    |  11 ++
 .../server/config/OpenviduConfig.java         |   3 +-
 .../service/ComposedRecordingService.java     |   2 +-
 .../server/resources/CDRHttpHandler.java      |   3 +-
 .../resources/FrontendResourceHandler.java    |  10 +-
 ...RecordingCustomLayoutsResourceHandler.java |   4 +-
 .../resources/RecordingsResourceHandler.java  |   3 +-
 .../server/rest/ApiRestPathRewriteFilter.java | 110 ++++++++++++++++++
 .../server/rest/CDRRestController.java        |   2 +-
 .../rest/CertificateRestController.java       |   2 +-
 .../server/rest/ConfigRestController.java     |  29 +++--
 .../openvidu/server/rest/RequestMappings.java |  16 +++
 .../server/rest/SessionRestController.java    |  37 +++---
 .../io/openvidu/server/utils/RestUtils.java   |  29 +++++
 14 files changed, 214 insertions(+), 47 deletions(-)
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java
 create mode 100644 openvidu-server/src/main/java/io/openvidu/server/utils/RestUtils.java

diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
index b1fe5e82..1ecda7cb 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java
@@ -35,6 +35,7 @@ import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.DependsOn;
@@ -66,6 +67,7 @@ import io.openvidu.server.recording.RecordingUploader;
 import io.openvidu.server.recording.service.RecordingManager;
 import io.openvidu.server.recording.service.RecordingManagerUtils;
 import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage;
+import io.openvidu.server.rest.ApiRestPathRewriteFilter;
 import io.openvidu.server.rpc.RpcHandler;
 import io.openvidu.server.rpc.RpcNotificationService;
 import io.openvidu.server.utils.CommandExecutor;
@@ -225,6 +227,15 @@ public class OpenViduServer implements JsonRpcConfigurer {
 		return new MediaNodeStatusManagerDummy();
 	}
 
+	@Bean
+	@ConditionalOnMissingBean
+	public FilterRegistrationBean filterRegistrationBean() {
+		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+		ApiRestPathRewriteFilter apiRestPathRewriteFilter = new ApiRestPathRewriteFilter();
+		registrationBean.setFilter(apiRestPathRewriteFilter);
+		return registrationBean;
+	}
+
 	@Override
 	public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
 		registry.addHandler(rpcHandler().withPingWatchdog(true).withInterceptors(new HttpHandshakeInterceptor()),
diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
index fd609f87..e48d190f 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java
@@ -57,6 +57,7 @@ import io.openvidu.server.OpenViduServer;
 import io.openvidu.server.cdr.CDREventName;
 import io.openvidu.server.config.Dotenv.DotenvFormatException;
 import io.openvidu.server.recording.RecordingNotification;
+import io.openvidu.server.rest.RequestMappings;
 
 @Component
 public class OpenviduConfig {
@@ -373,7 +374,7 @@ public class OpenviduConfig {
 	}
 
 	public String getOpenViduFrontendDefaultPath() {
-		return "dashboard";
+		return RequestMappings.FRONTEND_CE;
 	}
 
 	// Properties management methods
diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
index 01a64264..13080a2c 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java
@@ -551,7 +551,7 @@ public class ComposedRecordingService extends RecordingService {
 				log.error(e.getMessage());
 			}
 			String defaultPathForDefaultLayout = recordingComposedUrlDefined ? ""
-					: ("/" + openviduConfig.getOpenViduFrontendDefaultPath());
+					: (openviduConfig.getOpenViduFrontendDefaultPath());
 			finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl
 					+ defaultPathForDefaultLayout + "/#/layout-" + layout + "/" + recording.getSessionId() + "/"
 					+ secret + "/" + port + "/" + !recording.hasAudio();
diff --git a/openvidu-server/src/main/java/io/openvidu/server/resources/CDRHttpHandler.java b/openvidu-server/src/main/java/io/openvidu/server/resources/CDRHttpHandler.java
index 151e24ee..a2f94978 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/resources/CDRHttpHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/resources/CDRHttpHandler.java
@@ -23,6 +23,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.rest.RequestMappings;
 
 @Configuration
 public class CDRHttpHandler implements WebMvcConfigurer {
@@ -33,7 +34,7 @@ public class CDRHttpHandler implements WebMvcConfigurer {
 	@Override
 	public void addResourceHandlers(ResourceHandlerRegistry registry) {
 		String cdrPath = openviduConfig.getOpenviduCdrPath();
-		registry.addResourceHandler("/cdr/**.log").addResourceLocations("file:" + cdrPath);
+		registry.addResourceHandler(RequestMappings.CDR + "/**.log").addResourceLocations("file:" + cdrPath);
 	}
 
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/resources/FrontendResourceHandler.java b/openvidu-server/src/main/java/io/openvidu/server/resources/FrontendResourceHandler.java
index 076b4c86..4add4b05 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/resources/FrontendResourceHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/resources/FrontendResourceHandler.java
@@ -29,7 +29,7 @@ import io.openvidu.server.config.OpenviduConfig;
  * /NEW_FRONTEND_PATH. Entrypoint file index.html must have tag
  * 
  * 
- * By default in OpenVidu CE this path is /dashbaord and in OpenVidu PRO is
+ * By default in OpenVidu CE this path is /dashboard and in OpenVidu PRO is
  * /inspector
  *
  * @author Pablo Fuente (pablofuenteperez@gmail.com)
@@ -42,10 +42,10 @@ public class FrontendResourceHandler extends WebMvcConfigurerAdapter {
 
 	@Override
 	public void addViewControllers(ViewControllerRegistry registry) {
-		registry.addViewController("/" + openviduConfig.getOpenViduFrontendDefaultPath())
-				.setViewName("redirect:/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/");
-		registry.addViewController("/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/")
-				.setViewName("forward:/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/index.html");
+		registry.addViewController(openviduConfig.getOpenViduFrontendDefaultPath())
+				.setViewName("redirect:" + openviduConfig.getOpenViduFrontendDefaultPath() + "/");
+		registry.addViewController(openviduConfig.getOpenViduFrontendDefaultPath() + "/")
+				.setViewName("forward:" + openviduConfig.getOpenViduFrontendDefaultPath() + "/index.html");
 		super.addViewControllers(registry);
 	}
 
diff --git a/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingCustomLayoutsResourceHandler.java b/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingCustomLayoutsResourceHandler.java
index dab3e05f..29311660 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingCustomLayoutsResourceHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingCustomLayoutsResourceHandler.java
@@ -24,6 +24,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.rest.RequestMappings;
 
 /**
  * This class serves custom recording layouts from host folder indicated in
@@ -41,7 +42,8 @@ public class RecordingCustomLayoutsResourceHandler implements WebMvcConfigurer {
 	@Override
 	public void addResourceHandlers(ResourceHandlerRegistry registry) {
 		String customLayoutsPath = openviduConfig.getOpenviduRecordingCustomLayout();
-		registry.addResourceHandler("/layouts/custom/**").addResourceLocations("file:" + customLayoutsPath);
+		registry.addResourceHandler(RequestMappings.CUSTOM_LAYOUTS + "/**")
+				.addResourceLocations("file:" + customLayoutsPath);
 	}
 
 }
\ No newline at end of file
diff --git a/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingsResourceHandler.java b/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingsResourceHandler.java
index f1433fa6..9bb6474f 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingsResourceHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/resources/RecordingsResourceHandler.java
@@ -23,6 +23,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.rest.RequestMappings;
 
 /**
  * This class serves recording files from host folder indicated in configuration
@@ -39,7 +40,7 @@ public class RecordingsResourceHandler implements WebMvcConfigurer {
 	@Override
 	public void addResourceHandlers(ResourceHandlerRegistry registry) {
 		String recordingsPath = openviduConfig.getOpenViduRecordingPath();
-		registry.addResourceHandler("/recordings/**").addResourceLocations("file:" + recordingsPath);
+		registry.addResourceHandler(RequestMappings.RECORDINGS + "/**").addResourceLocations("file:" + recordingsPath);
 	}
 
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java
new file mode 100644
index 00000000..0acff13b
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java
@@ -0,0 +1,110 @@
+package io.openvidu.server.rest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.util.WebUtils;
+
+public class ApiRestPathRewriteFilter implements Filter {
+
+	protected static final Logger log = LoggerFactory.getLogger(ApiRestPathRewriteFilter.class);
+
+	protected Map PATH_REDIRECTIONS_MAP = new HashMap() {
+		{
+			// APIs
+			put("/api/", RequestMappings.API + "/");
+			put("/config", RequestMappings.API + "/config");
+			put("/config/", RequestMappings.API + "/config/");
+			put("/cdr", RequestMappings.CDR);
+			// Static resources
+			put("/cdr/", RequestMappings.CDR + "/");
+			put("/recordings/", RequestMappings.RECORDINGS + "/");
+			put("/layouts/custom/", RequestMappings.CUSTOM_LAYOUTS + "/");
+
+			put("/accept-certificate", RequestMappings.ACCEPT_CERTIFICATE); // ??
+		}
+	};
+	protected String[] PATH_REDIRECTIONS_ARRAY;
+
+	public ApiRestPathRewriteFilter() {
+		PATH_REDIRECTIONS_ARRAY = PATH_REDIRECTIONS_MAP.keySet().toArray(new String[PATH_REDIRECTIONS_MAP.size()]);
+	}
+
+	@Override
+	public void init(FilterConfig filterConfig) throws ServletException {
+		log.info("Initializing API REST path rewrite filter");
+	}
+
+	@Override
+	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+			throws IOException, ServletException {
+
+		HttpServletRequest req = (HttpServletRequest) request;
+		HttpServletResponse res = (HttpServletResponse) response;
+		String requestPath = req.getRequestURI();
+
+		String oldBasePath = null;
+		String newBasePath = null;
+
+		for (final String path : PATH_REDIRECTIONS_ARRAY) {
+			if (requestPath.startsWith(path)) {
+				oldBasePath = path;
+				break;
+			}
+		}
+
+		if (oldBasePath != null) {
+
+			newBasePath = PATH_REDIRECTIONS_MAP.get(oldBasePath);
+
+			String redirectURI = newBasePath + requestPath.substring(oldBasePath.length());
+			StringBuffer redirectURL = new StringBuffer(
+					((HttpServletRequest) request).getRequestURL().toString().replaceFirst(oldBasePath, newBasePath));
+
+			log.warn(
+					"Path {} is deprecated. Use path {} instead. Deprecated path will be removed in a major release in the future",
+					oldBasePath, newBasePath);
+
+			chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) {
+				@Override
+				public String getRequestURI() {
+					return redirectURI;
+				}
+
+				@Override
+				public StringBuffer getRequestURL() {
+					return redirectURL;
+				}
+
+				@Override
+				public Object getAttribute(String name) {
+					if (WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE.equals(name))
+						return redirectURI;
+					return super.getAttribute(name);
+				}
+			}, response);
+
+		} else {
+			chain.doFilter(req, res);
+		}
+	}
+
+	@Override
+	public void destroy() {
+		// Nothing to free up...
+	}
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java
index 0ef92fa3..f01ed33e 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java
@@ -47,7 +47,7 @@ import io.openvidu.server.config.OpenviduConfig;
  */
 @RestController
 @CrossOrigin
-@RequestMapping("/cdr")
+@RequestMapping(RequestMappings.CDR)
 public class CDRRestController {
 
 	private static final Logger log = LoggerFactory.getLogger(CDRRestController.class);
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/CertificateRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/CertificateRestController.java
index c5058d9d..542249fa 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/CertificateRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/CertificateRestController.java
@@ -24,7 +24,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 @RestController
 @CrossOrigin
-@RequestMapping("/accept-certificate")
+@RequestMapping(RequestMappings.ACCEPT_CERTIFICATE)
 public class CertificateRestController {
 
 	@RequestMapping(method = RequestMethod.GET)
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java
index c8f4d847..b63980cd 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java
@@ -21,9 +21,8 @@ import org.apache.http.Header;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -36,6 +35,7 @@ import com.google.gson.JsonObject;
 import io.openvidu.server.cdr.CDREventName;
 import io.openvidu.server.config.OpenviduBuildInfo;
 import io.openvidu.server.config.OpenviduConfig;
+import io.openvidu.server.utils.RestUtils;
 
 /**
  *
@@ -43,7 +43,8 @@ import io.openvidu.server.config.OpenviduConfig;
  */
 @RestController
 @CrossOrigin
-@RequestMapping("/config")
+@ConditionalOnMissingBean(name = "configRestControllerPro")
+@RequestMapping(RequestMappings.API + "/config")
 public class ConfigRestController {
 
 	private static final Logger log = LoggerFactory.getLogger(ConfigRestController.class);
@@ -54,6 +55,14 @@ public class ConfigRestController {
 	@Autowired
 	private OpenviduBuildInfo openviduBuildInfo;
 
+	@RequestMapping(method = RequestMethod.GET)
+	public ResponseEntity getOpenViduConfiguration() {
+
+		log.info("REST API: GET /config");
+
+		return this.getConfig();
+	}
+
 	@RequestMapping(value = "/openvidu-version", method = RequestMethod.GET)
 	public String getOpenViduServerVersion() {
 
@@ -94,11 +103,7 @@ public class ConfigRestController {
 		return openviduConfig.isCdrEnabled();
 	}
 
-	@RequestMapping(method = RequestMethod.GET)
-	public ResponseEntity getOpenViduConfiguration() {
-
-		log.info("REST API: GET /config");
-
+	protected ResponseEntity getConfig() {
 		JsonObject json = new JsonObject();
 		json.addProperty("VERSION", openviduBuildInfo.getVersion());
 		json.addProperty("DOMAIN_OR_PUBLIC_IP", openviduConfig.getDomainOrPublicIp());
@@ -141,13 +146,7 @@ public class ConfigRestController {
 			json.add("OPENVIDU_WEBHOOK_EVENTS", webhookEvents);
 		}
 
-		return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
-	}
-
-	protected HttpHeaders getResponseHeaders() {
-		HttpHeaders responseHeaders = new HttpHeaders();
-		responseHeaders.setContentType(MediaType.APPLICATION_JSON);
-		return responseHeaders;
+		return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 	}
 
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java
new file mode 100644
index 00000000..be7936c7
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java
@@ -0,0 +1,16 @@
+package io.openvidu.server.rest;
+
+public class RequestMappings {
+
+	final public static String API = "/openvidu/api";
+	final public static String CDR = "/openvidu/cdr";
+	final public static String API_ELK = "/openvidu/elasticsearch";
+	final public static String API_INSPECTOR = "/openvidu/inspector-api";
+	final public static String RECORDINGS = "/openvidu/recordings";
+	final public static String CUSTOM_LAYOUTS = "/openvidu/layouts";
+	final public static String FRONTEND_CE = "/dashboard";
+	final public static String FRONTEND_PRO = "/inspector";
+
+	final public static String ACCEPT_CERTIFICATE = "/openvidu/accept-certificate"; // ????
+
+}
diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
index 3af12ac1..5882e741 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java
@@ -28,9 +28,7 @@ import org.apache.commons.lang3.RandomStringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.CrossOrigin;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -67,6 +65,7 @@ import io.openvidu.server.kurento.core.KurentoTokenOptions;
 import io.openvidu.server.recording.Recording;
 import io.openvidu.server.recording.service.RecordingManager;
 import io.openvidu.server.utils.RecordingUtils;
+import io.openvidu.server.utils.RestUtils;
 
 /**
  *
@@ -74,7 +73,7 @@ import io.openvidu.server.utils.RecordingUtils;
  */
 @RestController
 @CrossOrigin
-@RequestMapping("/api")
+@RequestMapping(RequestMappings.API)
 public class SessionRestController {
 
 	private static final Logger log = LoggerFactory.getLogger(SessionRestController.class);
@@ -180,7 +179,7 @@ public class SessionRestController {
 		responseJson.addProperty("id", sessionNotActive.getSessionId());
 		responseJson.addProperty("createdAt", sessionNotActive.getStartTime());
 
-		return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK);
+		return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 	}
 
 	@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET)
@@ -192,13 +191,13 @@ public class SessionRestController {
 		Session session = this.sessionManager.getSession(sessionId);
 		if (session != null) {
 			JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson();
-			return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
+			return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 		} else {
 			Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId);
 			if (sessionNotActive != null) {
 				JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson()
 						: sessionNotActive.toJson();
-				return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
+				return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 			} else {
 				return new ResponseEntity<>(HttpStatus.NOT_FOUND);
 			}
@@ -220,7 +219,7 @@ public class SessionRestController {
 		});
 		json.addProperty("numberOfElements", sessions.size());
 		json.add("content", jsonArray);
-		return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
+		return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 	}
 
 	@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE)
@@ -430,7 +429,7 @@ public class SessionRestController {
 					}
 					responseJson.add("kurentoOptions", kurentoOptsResponse);
 				}
-				return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK);
+				return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 			} catch (Exception e) {
 				return this.generateErrorResponse(
 						"Error generating token for session " + sessionId + ": " + e.getMessage(), "/api/tokens",
@@ -593,9 +592,10 @@ public class SessionRestController {
 
 		try {
 			Recording startedRecording = this.recordingManager.startRecording(session, builder.build());
-			return new ResponseEntity<>(startedRecording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
+			return new ResponseEntity<>(startedRecording.toJson().toString(), RestUtils.getResponseHeaders(),
+					HttpStatus.OK);
 		} catch (OpenViduException e) {
-			return new ResponseEntity<>("Error starting recording: " + e.getMessage(), getResponseHeaders(),
+			return new ResponseEntity<>("Error starting recording: " + e.getMessage(), RestUtils.getResponseHeaders(),
 					HttpStatus.INTERNAL_SERVER_ERROR);
 		}
 	}
@@ -638,7 +638,8 @@ public class SessionRestController {
 					session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null, null, null);
 		}
 
-		return new ResponseEntity<>(stoppedRecording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
+		return new ResponseEntity<>(stoppedRecording.toJson().toString(), RestUtils.getResponseHeaders(),
+				HttpStatus.OK);
 	}
 
 	@RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.GET)
@@ -657,7 +658,7 @@ public class SessionRestController {
 					&& recordingManager.getStartingRecording(recording.getId()) != null) {
 				recording.setStatus(io.openvidu.java.client.Recording.Status.starting);
 			}
-			return new ResponseEntity<>(recording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
+			return new ResponseEntity<>(recording.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 		} catch (Exception e) {
 			return new ResponseEntity<>(HttpStatus.NOT_FOUND);
 		}
@@ -685,7 +686,7 @@ public class SessionRestController {
 		});
 		json.addProperty("count", recordings.size());
 		json.add("items", jsonArray);
-		return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
+		return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
 	}
 
 	@RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.DELETE)
@@ -832,7 +833,8 @@ public class SessionRestController {
 					return new ResponseEntity<>(HttpStatus.NOT_FOUND);
 				}
 				Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, data);
-				return new ResponseEntity<>(ipcamParticipant.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
+				return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(),
+						HttpStatus.OK);
 			} catch (MalformedURLException e) {
 				return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri",
 						"/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
@@ -854,12 +856,7 @@ public class SessionRestController {
 		responseJson.addProperty("error", status.getReasonPhrase());
 		responseJson.addProperty("message", errorMessage);
 		responseJson.addProperty("path", path);
-		return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), status);
+		return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), status);
 	}
 
-	private HttpHeaders getResponseHeaders() {
-		HttpHeaders responseHeaders = new HttpHeaders();
-		responseHeaders.setContentType(MediaType.APPLICATION_JSON);
-		return responseHeaders;
-	}
 }
diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/RestUtils.java b/openvidu-server/src/main/java/io/openvidu/server/utils/RestUtils.java
new file mode 100644
index 00000000..66512440
--- /dev/null
+++ b/openvidu-server/src/main/java/io/openvidu/server/utils/RestUtils.java
@@ -0,0 +1,29 @@
+package io.openvidu.server.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+
+public class RestUtils {
+
+	private static final Logger log = LoggerFactory.getLogger(RestUtils.class);
+
+	public static HttpHeaders getResponseHeaders() {
+		HttpHeaders responseHeaders = new HttpHeaders();
+		responseHeaders.setContentType(MediaType.APPLICATION_JSON);
+		return responseHeaders;
+	}
+
+	public static ResponseEntity getErrorResponse(String message, HttpStatus status) {
+		if (!status.is2xxSuccessful()) {
+			log.error(message);
+		}
+		HttpHeaders responseHeaders = new HttpHeaders();
+		responseHeaders.setContentType(MediaType.TEXT_PLAIN);
+		return new ResponseEntity<>(message, responseHeaders, status);
+	}
+
+}

From c38d905a46ed8a580b78c50e3c9ce99bf28fce95 Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 1 Oct 2020 13:47:07 +0200
Subject: [PATCH 061/435] openvidu-test-e2e: recording tests renamed

---
 .../test/e2e/OpenViduTestAppE2eTest.java      | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index f8de5a25..ce3e9ac2 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -1030,12 +1030,12 @@ public class OpenViduTestAppE2eTest {
 	}
 
 	@Test
-	@DisplayName("Local record")
-	void localRecordTest() throws Exception {
+	@DisplayName("Local browser record")
+	void localBrowserRecordTest() throws Exception {
 
 		setupBrowser("chrome");
 
-		log.info("Local record");
+		log.info("Local browser record");
 
 		user.getDriver().findElement(By.id("add-user-btn")).click();
 		user.getDriver().findElement(By.className("join-btn")).click();
@@ -1087,13 +1087,13 @@ public class OpenViduTestAppE2eTest {
 	}
 
 	@Test
-	@DisplayName("Remote composed record")
-	void remoteComposedRecordTest() throws Exception {
+	@DisplayName("Composed record")
+	void composedRecordTest() throws Exception {
 		isRecordingTest = true;
 
 		setupBrowser("chrome");
 
-		log.info("Remote composed record");
+		log.info("Composed record");
 
 		final String sessionName = "COMPOSED_RECORDED_SESSION";
 		final String resolution = "1280x720";
@@ -1238,13 +1238,13 @@ public class OpenViduTestAppE2eTest {
 	}
 
 	@Test
-	@DisplayName("Remote composed quick start record")
-	void remoteComposedQuickStartRecordTest() throws Exception {
+	@DisplayName("Composed quick start record")
+	void composedQuickStartRecordTest() throws Exception {
 		isRecordingTest = true;
 
 		setupBrowser("chrome");
 
-		log.info("Remote composed quick start record");
+		log.info("Composed quick start record");
 
 		CountDownLatch initLatch = new CountDownLatch(1);
 		io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch);
@@ -1413,13 +1413,13 @@ public class OpenViduTestAppE2eTest {
 	}
 
 	@Test
-	@DisplayName("Remote individual record")
-	void remoteIndividualRecordTest() throws Exception {
+	@DisplayName("Individual record")
+	void individualRecordTest() throws Exception {
 		isRecordingTest = true;
 
 		setupBrowser("chrome");
 
-		log.info("Remote individual record");
+		log.info("Individual record");
 
 		final String sessionName = "TestSession";
 		final String recordingName = "CUSTOM_NAME";
@@ -1519,13 +1519,13 @@ public class OpenViduTestAppE2eTest {
 	}
 
 	@Test
-	@DisplayName("Remote record cross-browser audio-only and video-only")
-	void remoteRecordAudioOnlyVideoOnlyTest() throws Exception {
+	@DisplayName("Record cross-browser audio-only and video-only")
+	void recordAudioOnlyVideoOnlyTest() throws Exception {
 		isRecordingTest = true;
 
 		setupBrowser("chromeAlternateScreenShare");
 
-		log.info("Remote record cross-browser audio-only and video-only");
+		log.info("Record cross-browser audio-only and video-only");
 
 		final String SESSION_NAME = "TestSession";
 		final String RECORDING_COMPOSED_VIDEO = "COMPOSED_VIDEO_ONLY";

From b3081d6d43829c7180438d7c4172881e786c6a0d Mon Sep 17 00:00:00 2001
From: pabloFuente 
Date: Thu, 1 Oct 2020 14:05:27 +0200
Subject: [PATCH 062/435] openvidu-test-e2e: RestApiTest extended to test token
 invalidation

---
 .../test/e2e/OpenViduTestAppE2eTest.java      | 85 +++++++++++++++++--
 1 file changed, 77 insertions(+), 8 deletions(-)

diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
index ce3e9ac2..817f599b 100644
--- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
+++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java
@@ -2618,7 +2618,7 @@ public class OpenViduTestAppE2eTest {
 		// 200
 		body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': ['GStreamerFilter']}}";
 		res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK, true,
-				"{'id':'STR','session':'STR','role':'STR','data':'STR','token':'STR','kurentoOptions':{'allowedFilters':['STR']}}");
+				"{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR','kurentoOptions':{'allowedFilters':['STR']}}");
 		final String token1 = res.get("token").getAsString();
 		Assert.assertEquals("JSON return value from /api/tokens should have equal srtings in 'id' and 'token'",
 				res.get("id").getAsString(), token1);
@@ -2627,7 +2627,7 @@ public class OpenViduTestAppE2eTest {
 		// Default values
 		body = "{'session': 'CUSTOM_SESSION_ID'}";
 		res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK, true,
-				"{'id':'STR','session':'STR','role':'STR','data':'STR','token':'STR'}");
+				"{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR'}");
 		final String token2 = res.get("id").getAsString();
 
 		/** POST /api/signal (NOT ACTIVE SESSION) **/
@@ -2687,9 +2687,9 @@ public class OpenViduTestAppE2eTest {
 		Thread.sleep(1000);
 
 		// Set token 1
-		WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
-		tokeInput.clear();
-		tokeInput.sendKeys(token1);
+		WebElement tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
+		tokenInput.clear();
+		tokenInput.sendKeys(token1);
 
 		user.getDriver().findElement(By.id("save-btn")).click();
 		Thread.sleep(1000);
@@ -2697,9 +2697,9 @@ public class OpenViduTestAppE2eTest {
 		Thread.sleep(1000);
 
 		// Set token 2
-		tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
-		tokeInput.clear();
-		tokeInput.sendKeys(token2);
+		tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
+		tokenInput.clear();
+		tokenInput.sendKeys(token2);
 		user.getDriver().findElement(By.id("save-btn")).click();
 		Thread.sleep(1000);
 
@@ -2810,6 +2810,75 @@ public class OpenViduTestAppE2eTest {
 		restClient.rest(HttpMethod.DELETE, "/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND);
 		restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT);
 
+		// GET /api/sessions should return empty again
+		restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true,
+				ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray()));
+
+		/**
+		 * DELETE /api/sessions//connection/ (unused token)
+		 **/
+		body = "{'customSessionId': 'CUSTOM_SESSION_ID'}";
+		restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_OK);
+		body = "{'session': 'CUSTOM_SESSION_ID'}";
+		res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK);
+		final String tokenAConnectionId = res.get("connectionId").getAsString();
+		final String tokenA = res.get("token").getAsString();
+		res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK);
+		final String tokenB = res.get("token").getAsString();
+		final String tokenBConnectionId = res.get("connectionId").getAsString();
+
+		user.getDriver().findElement(By.id("one2one-btn")).click();
+		user.getDriver().findElement(By.id("session-settings-btn-0")).click();
+		Thread.sleep(1000);
+
+		// Set token 1
+		tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
+		tokenInput.clear();
+		tokenInput.sendKeys(tokenA);
+
+		user.getDriver().findElement(By.id("save-btn")).click();
+		Thread.sleep(1000);
+		user.getDriver().findElement(By.id("session-settings-btn-1")).click();
+		Thread.sleep(1000);
+
+		// Set token 2
+		tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
+		tokenInput.clear();
+		tokenInput.sendKeys(tokenB);
+		user.getDriver().findElement(By.id("save-btn")).click();
+		Thread.sleep(1000);
+
+		// Invalidate token
+		restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId,
+				HttpStatus.SC_NO_CONTENT);
+
+		// First user should pop up invalid token
+		user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .join-btn")).sendKeys(Keys.ENTER);
+		try {
+			user.getWaiter().until(ExpectedConditions.alertIsPresent());
+			Alert alert = user.getDriver().switchTo().alert();
+			Assert.assertTrue("Alert does not contain expected text",
+					alert.getText().contains("Token " + tokenA + "is not valid"));
+			alert.accept();
+		} catch (Exception e) {
+			Assert.fail("Alert exception");
+		}
+
+		user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).sendKeys(Keys.ENTER);
+
+		user.getEventManager().waitUntilEventReaches("connectionCreated", 5);
+		user.getEventManager().waitUntilEventReaches("accessAllowed", 3);
+		user.getEventManager().waitUntilEventReaches("streamCreated", 5);
+		user.getEventManager().waitUntilEventReaches("streamPlaying", 5);
+
+		// connectionId should be equal to the one brought by the token
+		Assert.assertEquals("Wrong connectionId", tokenBConnectionId,
+				restClient.rest(HttpMethod.GET, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK).get("connections")
+						.getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject().get("connectionId")
+						.getAsString());
+
+		restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT);
+
 		// GET /api/sessions should return empty again
 		restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true,
 				ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray()));

From 92123d6df5b3bf4e392aaa66445e83330453434c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Fuente=20P=C3=A9rez?= 
Date: Thu, 1 Oct 2020 14:57:23 +0200
Subject: [PATCH 063/435] Add files via upload

---
 .../docker/my-custom-layout/index.html        | 55 +++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 openvidu-test-e2e/docker/my-custom-layout/index.html

diff --git a/openvidu-test-e2e/docker/my-custom-layout/index.html b/openvidu-test-e2e/docker/my-custom-layout/index.html
new file mode 100644
index 00000000..ca45b3f7
--- /dev/null
+++ b/openvidu-test-e2e/docker/my-custom-layout/index.html
@@ -0,0 +1,55 @@
+
+
+
+    
+    
+    
+
+
+
+    
+ + + + + \ No newline at end of file From 6a8670304f1203f0f20e9f3e803a4de2d25c8131 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 16:07:53 +0200 Subject: [PATCH 064/435] openvidu-test-e2e: wait time after alert accepted --- .../test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 817f599b..1b36cab7 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -2864,6 +2864,8 @@ public class OpenViduTestAppE2eTest { Assert.fail("Alert exception"); } + Thread.sleep(500); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).sendKeys(Keys.ENTER); user.getEventManager().waitUntilEventReaches("connectionCreated", 5); From 3056d213202a0062f22f6c8cac294cbea468535c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 18:36:01 +0200 Subject: [PATCH 065/435] openvidu-test-e2e: custom layout recording test --- .../ComposedQuickStartRecordingService.java | 2 +- .../utils/layout/CustomLayoutHandler.java | 41 ++++ .../utils/{ => webhook}/CustomWebhook.java | 4 +- .../aplication-pro-layout-handler.properties | 3 + .../src/main/resources/static/index.html | 55 ++++++ openvidu-test-e2e/jenkins/Jenkinsfile | 5 +- .../test/e2e/OpenViduTestAppE2eTest.java | 176 ++++++++++++++++-- .../session-properties-dialog.component.html | 7 +- 8 files changed, 266 insertions(+), 27 deletions(-) create mode 100644 openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/layout/CustomLayoutHandler.java rename openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/{ => webhook}/CustomWebhook.java (96%) create mode 100644 openvidu-test-browsers/src/main/resources/aplication-pro-layout-handler.properties create mode 100644 openvidu-test-browsers/src/main/resources/static/index.html diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java index 5ab5588e..12b0564d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedQuickStartRecordingService.java @@ -220,7 +220,7 @@ public class ComposedQuickStartRecordingService extends ComposedRecordingService containers.remove(containerId); sessionsContainers.remove(session.getSessionId()); } - log.error("Error while launchig container for COMPOSED_QUICK_START: ({})", e.getMessage()); + log.error("Error while launching container for COMPOSED_QUICK_START: ({})", e.getMessage()); throw e; } return containerId; diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/layout/CustomLayoutHandler.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/layout/CustomLayoutHandler.java new file mode 100644 index 00000000..a1ca17b1 --- /dev/null +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/layout/CustomLayoutHandler.java @@ -0,0 +1,41 @@ +package io.openvidu.test.browsers.utils.layout; + +import java.util.concurrent.CountDownLatch; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.event.EventListener; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@SpringBootApplication +public class CustomLayoutHandler extends WebSecurityConfigurerAdapter implements WebMvcConfigurer { + + private static ConfigurableApplicationContext context; + public static CountDownLatch initLatch; + + public static void main(String[] args, CountDownLatch initLatch) { + CustomLayoutHandler.initLatch = initLatch; + CustomLayoutHandler.context = new SpringApplicationBuilder(CustomLayoutHandler.class) + .properties("spring.config.location:classpath:aplication-pro-layout-handler.properties").build() + .run(args); + } + + @Override + protected void configure(HttpSecurity security) throws Exception { + security.httpBasic().disable(); + } + + @EventListener(ApplicationReadyEvent.class) + public void afterStartup() { + CustomLayoutHandler.initLatch.countDown(); + } + + public static void shutDown() { + CustomLayoutHandler.context.close(); + } + +} diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java similarity index 96% rename from openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java rename to openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java index 0ecf7aca..3cfbbbd6 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomWebhook.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java @@ -15,7 +15,7 @@ * */ -package io.openvidu.test.browsers.utils; +package io.openvidu.test.browsers.utils.webhook; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; @@ -24,7 +24,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ConfigurableApplicationContext; @@ -39,7 +38,6 @@ import org.springframework.web.bind.annotation.RestController; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -@SpringBootApplication public class CustomWebhook { private static ConfigurableApplicationContext context; diff --git a/openvidu-test-browsers/src/main/resources/aplication-pro-layout-handler.properties b/openvidu-test-browsers/src/main/resources/aplication-pro-layout-handler.properties new file mode 100644 index 00000000..10fc87dd --- /dev/null +++ b/openvidu-test-browsers/src/main/resources/aplication-pro-layout-handler.properties @@ -0,0 +1,3 @@ +server.port=5555 +server.ssl.enabled=false +security.basic.enabled=false \ No newline at end of file diff --git a/openvidu-test-browsers/src/main/resources/static/index.html b/openvidu-test-browsers/src/main/resources/static/index.html new file mode 100644 index 00000000..ca45b3f7 --- /dev/null +++ b/openvidu-test-browsers/src/main/resources/static/index.html @@ -0,0 +1,55 @@ + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 37073784..f2b5a606 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -6,6 +6,7 @@ node('container') { sh 'rm -rf /opt/openvidu/* || true' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' + sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://github.com/OpenVidu/openvidu/blob/master/openvidu-test-e2e/docker/my-custom-layout/index.html' docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() @@ -93,10 +94,10 @@ node('container') { sh(script: '''#!/bin/bash if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & else echo "Using default openvidu-recording tag" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & fi '''.stripIndent()) sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 1b36cab7..d2a2514c 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -42,6 +42,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import javax.imageio.ImageIO; @@ -103,9 +104,10 @@ import io.openvidu.test.browsers.FirefoxUser; import io.openvidu.test.browsers.OperaUser; import io.openvidu.test.browsers.utils.CommandLineExecutor; import io.openvidu.test.browsers.utils.CustomHttpClient; -import io.openvidu.test.browsers.utils.CustomWebhook; import io.openvidu.test.browsers.utils.MultimediaFileMetadata; import io.openvidu.test.browsers.utils.Unzipper; +import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler; +import io.openvidu.test.browsers.utils.webhook.CustomWebhook; /** * E2E tests for openvidu-testapp. @@ -1208,9 +1210,10 @@ public class OpenViduTestAppE2eTest { Assert.assertTrue("File " + file3.getAbsolutePath() + " does not exist or is empty", file3.exists() && file3.length() > 0); - Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", - this.recordedFileFine(file1, new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName))); - Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", this.thumbnailIsFine(file3)); + Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedGreenFileFine(file1, + new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName))); + Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", + this.thumbnailIsFine(file3, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen)); // Try to get the stopped recording user.getDriver().findElement(By.id("get-recording-btn")).click(); @@ -1247,7 +1250,7 @@ public class OpenViduTestAppE2eTest { log.info("Composed quick start record"); CountDownLatch initLatch = new CountDownLatch(1); - io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch); + io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch); try { @@ -1520,7 +1523,7 @@ public class OpenViduTestAppE2eTest { @Test @DisplayName("Record cross-browser audio-only and video-only") - void recordAudioOnlyVideoOnlyTest() throws Exception { + void audioOnlyVideoOnlyRecordTest() throws Exception { isRecordingTest = true; setupBrowser("chromeAlternateScreenShare"); @@ -1750,6 +1753,128 @@ public class OpenViduTestAppE2eTest { } } + @Test + @DisplayName("Custom layout recording") + void customLayoutRecordTest() throws Exception { + isRecordingTest = true; + + setupBrowser("chrome"); + + log.info("Custom layout recording"); + + final String SESSION_NAME = "CUSTOM_LAYOUT_SESSION"; + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-name-input-0")).clear(); + user.getDriver().findElement(By.id("session-name-input-0")).sendKeys(SESSION_NAME); + + // Custom layout from local storage + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("recording-mode-select")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("option-ALWAYS")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("recording-layout-select")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("option-CUSTOM")).click(); + Thread.sleep(500); + WebElement tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input")); + tokeInput.clear(); + tokeInput.sendKeys("layout1"); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + + user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); + user.getEventManager().waitUntilEventReaches("recordingStarted", 1); + + Thread.sleep(4000); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + user.getDriver().findElement(By.id("recording-id-field")).clear(); + user.getDriver().findElement(By.id("recording-id-field")).sendKeys(SESSION_NAME); + user.getDriver().findElement(By.id("stop-recording-btn")).click(); + user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", + "Recording stopped [" + SESSION_NAME + "]")); + user.getEventManager().waitUntilEventReaches("recordingStopped", 1); + user.getDriver().findElement(By.id("close-session-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamDestroyed", 1); + user.getEventManager().waitUntilEventReaches("sessionDisconnected", 1); + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + + String recordingsPath = "/opt/openvidu/recordings/" + SESSION_NAME + "/"; + File file1 = new File(recordingsPath + SESSION_NAME + ".mp4"); + File file2 = new File(recordingsPath + SESSION_NAME + ".jpg"); + + Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedRedFileFine(file1, + new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(SESSION_NAME))); + Assert.assertTrue("Thumbnail " + file2.getAbsolutePath() + " is not fine", + this.thumbnailIsFine(file2, OpenViduTestAppE2eTest::checkVideoAverageRgbRed)); + + // Custom layout from external URL + CountDownLatch initLatch = new CountDownLatch(1); + CustomLayoutHandler.main(new String[0], initLatch); + try { + + if (!initLatch.await(30, TimeUnit.SECONDS)) { + Assert.fail("Timeout waiting for webhook springboot app to start"); + CustomLayoutHandler.shutDown(); + return; + } + + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); + tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input")); + tokeInput.clear(); + tokeInput.sendKeys("http://localhost:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET"); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + + user.getDriver().findElement(By.className("join-btn")).sendKeys(Keys.ENTER); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 2); + user.getEventManager().waitUntilEventReaches("accessAllowed", 2); + user.getEventManager().waitUntilEventReaches("streamCreated", 2); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + user.getEventManager().waitUntilEventReaches("recordingStarted", 2); + + Thread.sleep(4000); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + user.getDriver().findElement(By.id("recording-id-field")).clear(); + user.getDriver().findElement(By.id("recording-id-field")).sendKeys(SESSION_NAME + "-1"); + user.getDriver().findElement(By.id("stop-recording-btn")).click(); + user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", + "Recording stopped [" + SESSION_NAME + "-1]")); + user.getEventManager().waitUntilEventReaches("recordingStopped", 2); + user.getDriver().findElement(By.id("close-session-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamDestroyed", 2); + user.getEventManager().waitUntilEventReaches("sessionDisconnected", 2); + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + + recordingsPath = "/opt/openvidu/recordings/" + SESSION_NAME + "-1/"; + file1 = new File(recordingsPath + SESSION_NAME + "-1.mp4"); + file2 = new File(recordingsPath + SESSION_NAME + "-1.jpg"); + + Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", this.recordedRedFileFine( + file1, new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(SESSION_NAME + "-1"))); + Assert.assertTrue("Thumbnail " + file2.getAbsolutePath() + " is not fine", + this.thumbnailIsFine(file2, OpenViduTestAppE2eTest::checkVideoAverageRgbRed)); + + } finally { + CustomLayoutHandler.shutDown(); + } + } + @Test @DisplayName("REST API: Fetch all, fetch one, force disconnect, force unpublish, close session") void restApiFetchForce() throws Exception { @@ -2490,8 +2615,9 @@ public class OpenViduTestAppE2eTest { file3.exists() && file3.length() > 0); Assert.assertTrue("Recorded file " + file1.getAbsolutePath() + " is not fine", - this.recordedFileFine(file1, recording2)); - Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", this.thumbnailIsFine(file3)); + this.recordedGreenFileFine(file1, recording2)); + Assert.assertTrue("Thumbnail " + file3.getAbsolutePath() + " is not fine", + this.thumbnailIsFine(file3, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen)); try { OV.deleteRecording("NOT_EXISTS"); @@ -2506,12 +2632,12 @@ public class OpenViduTestAppE2eTest { try { session.forceUnpublish("NOT_EXISTS"); } catch (OpenViduHttpException e) { - Assert.assertEquals("Wrong HTTP status on Session.fetch()", 404, e.getStatus()); + Assert.assertEquals("Wrong HTTP status on Session.forceUnpublish()", 404, e.getStatus()); } try { session.forceDisconnect("NOT_EXISTS"); } catch (OpenViduHttpException e) { - Assert.assertEquals("Wrong HTTP status on Session.fetch()", 404, e.getStatus()); + Assert.assertEquals("Wrong HTTP status on Session.forceDisconnect()", 404, e.getStatus()); } if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) { @@ -3051,7 +3177,7 @@ public class OpenViduTestAppE2eTest { log.info("Webhook test"); CountDownLatch initLatch = new CountDownLatch(1); - io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch); + io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch); try { @@ -3204,7 +3330,7 @@ public class OpenViduTestAppE2eTest { log.info("IP camera test"); CountDownLatch initLatch = new CountDownLatch(1); - io.openvidu.test.browsers.utils.CustomWebhook.main(new String[0], initLatch); + io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch); try { @@ -3464,12 +3590,12 @@ public class OpenViduTestAppE2eTest { }; } - private boolean checkVideoAverageRgbGreen(Map rgb) { + private static boolean checkVideoAverageRgbGreen(Map rgb) { // GREEN color: {r < 15, g > 130, b <15} return (rgb.get("r") < 15) && (rgb.get("g") > 130) && (rgb.get("b") < 15); } - private boolean checkVideoAverageRgbGray(Map rgb) { + private static boolean checkVideoAverageRgbGray(Map rgb) { // GRAY color: {r < 50, g < 50, b < 50} and the absolute difference between them // not greater than 2 return (rgb.get("r") < 50) && (rgb.get("g") < 50) && (rgb.get("b") < 50) @@ -3477,6 +3603,11 @@ public class OpenViduTestAppE2eTest { && (Math.abs(rgb.get("b") - rgb.get("g")) <= 2); } + private static boolean checkVideoAverageRgbRed(Map rgb) { + // RED color: {r > 240, g < 15, b <15} + return (rgb.get("r") > 240) && (rgb.get("g") < 15) && (rgb.get("b") < 15); + } + private void gracefullyLeaveParticipants(int numberOfParticipants) throws Exception { int accumulatedConnectionDestroyed = 0; for (int j = 1; j <= numberOfParticipants; j++) { @@ -3494,7 +3625,8 @@ public class OpenViduTestAppE2eTest { return "data:image/png;base64," + screenshotBase64; } - private boolean recordedFileFine(File file, Recording recording) throws IOException { + private boolean recordedFileFine(File file, Recording recording, + Function, Boolean> colorCheckFunction) throws IOException { this.checkMultimediaFile(file, recording.hasAudio(), recording.hasVideo(), recording.getDuration(), recording.getResolution(), "aac", "h264", true); @@ -3515,7 +3647,7 @@ public class OpenViduTestAppE2eTest { log.info("Recording map color: {}", colorMap.toString()); log.info("Recording frame below"); System.out.println(bufferedImageToBase64PngString(image)); - isFine = this.checkVideoAverageRgbGreen(colorMap); + isFine = colorCheckFunction.apply(colorMap); } catch (IOException | JCodecException e) { log.warn("Error getting frame from video recording: {}", e.getMessage()); isFine = false; @@ -3523,6 +3655,14 @@ public class OpenViduTestAppE2eTest { return isFine; } + private boolean recordedGreenFileFine(File file, Recording recording) throws IOException { + return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen); + } + + private boolean recordedRedFileFine(File file, Recording recording) throws IOException { + return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbRed); + } + private String bufferedImageToBase64PngString(BufferedImage image) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); String imageString = null; @@ -3654,7 +3794,7 @@ public class OpenViduTestAppE2eTest { Math.abs((metadata.getDuration() - duration)) < difference); } - private boolean thumbnailIsFine(File file) { + private boolean thumbnailIsFine(File file, Function, Boolean> colorCheckFunction) { boolean isFine = false; BufferedImage image = null; try { @@ -3666,7 +3806,7 @@ public class OpenViduTestAppE2eTest { log.info("Recording thumbnail dimensions: {}x{}", image.getWidth(), image.getHeight()); Map colorMap = this.averageColor(image); log.info("Thumbnail map color: {}", colorMap.toString()); - isFine = this.checkVideoAverageRgbGreen(colorMap); + isFine = colorCheckFunction.apply(colorMap); return isFine; } diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index de5608d5..7ca258ce 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -27,16 +27,17 @@ - + - {{ enumerator }} + {{ enumerator }} + [(ngModel)]="sessionProperties.defaultCustomLayout" id="default-custom-layout-input"> From 2aecbf625ebc78f58f4bb252daa445f83f8d9a7e Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 18:55:56 +0200 Subject: [PATCH 066/435] openvidu-test-browsers: fix CustomWebhook --- .../io/openvidu/test/browsers/utils/webhook/CustomWebhook.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java index 3cfbbbd6..06d05e74 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java @@ -24,6 +24,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; +import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ConfigurableApplicationContext; @@ -38,6 +39,7 @@ import org.springframework.web.bind.annotation.RestController; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +@SpringBootApplication public class CustomWebhook { private static ConfigurableApplicationContext context; From 21584e602d2f217cdae453e6677c55cd8632ba82 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 19:33:26 +0200 Subject: [PATCH 067/435] openvidu-server: updated custom layout recording URL with RequestMappings value --- .../server/recording/service/ComposedRecordingService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java index 13080a2c..d767f827 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java @@ -57,6 +57,7 @@ import io.openvidu.server.recording.Recording; import io.openvidu.server.recording.RecordingDownloader; import io.openvidu.server.recording.RecordingInfoUtils; import io.openvidu.server.recording.RecordingUploader; +import io.openvidu.server.rest.RequestMappings; import io.openvidu.server.utils.DockerManager; import io.openvidu.server.utils.QuarantineKiller; @@ -540,8 +541,9 @@ public class ComposedRecordingService extends RecordingService { layout = layout.endsWith("/") ? layout.substring(0, layout.length() - 1) : layout; } layout += "/index.html"; - finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl + "/layouts/custom" - + layout + "?sessionId=" + recording.getSessionId() + "&secret=" + secret; + finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl + + RequestMappings.CUSTOM_LAYOUTS + layout + "?sessionId=" + recording.getSessionId() + "&secret=" + + secret; } else { layout = recording.getRecordingLayout().name().toLowerCase().replaceAll("_", "-"); int port = startsWithHttp ? 80 : 443; From 07b36815242f48595d0e61423727b42d295bc179 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 20:19:10 +0200 Subject: [PATCH 068/435] openvidu-test-e2e: Jenkinsfile fixed --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index f2b5a606..055ee1d5 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -6,7 +6,7 @@ node('container') { sh 'rm -rf /opt/openvidu/* || true' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' - sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://github.com/OpenVidu/openvidu/blob/master/openvidu-test-e2e/docker/my-custom-layout/index.html' + sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://raw.githubusercontent.com/OpenVidu/openvidu/master/openvidu-test-e2e/docker/my-custom-layout/index.html' docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() From 528372e6f61f2e83792960eecc46a5b2280b3fbc Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 21:03:23 +0200 Subject: [PATCH 069/435] openvidu-test-e2e: customLayoutRecordTest parameterized with EXTERNAL_CUSTOM_LAYOUT_URL --- openvidu-test-e2e/jenkins/Jenkinsfile | 4 ++-- .../io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 055ee1d5..a8299ae0 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -10,7 +10,7 @@ node('container') { docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() - mycontainer.inside("--name e2e -p 4200:4200 -p 4443:4443 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged") { + mycontainer.inside("--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged") { stage('Preparation') { sh 'rm -rf ~/.m2 || true' sh 'rm -rf openvidu || true' @@ -104,7 +104,7 @@ node('container') { } stage ('OpenVidu E2E tests') { try { - sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ test' + sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET test' } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index d2a2514c..d07ba5f5 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -123,6 +123,7 @@ public class OpenViduTestAppE2eTest { static String OPENVIDU_SECRET = "MY_SECRET"; static String OPENVIDU_URL = "https://localhost:4443/"; static String APP_URL = "http://localhost:4200/"; + static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET"; static Exception ex = null; private final Object lock = new Object(); @@ -157,6 +158,12 @@ public class OpenViduTestAppE2eTest { } log.info("Using URL {} to connect to openvidu-testapp", APP_URL); + String externalCustomLayoutUrl = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_URL"); + if (externalCustomLayoutUrl != null) { + EXTERNAL_CUSTOM_LAYOUT_URL = externalCustomLayoutUrl; + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); + String openviduUrl = System.getProperty("OPENVIDU_URL"); if (openviduUrl != null) { OPENVIDU_URL = openviduUrl; @@ -1833,7 +1840,7 @@ public class OpenViduTestAppE2eTest { Thread.sleep(1000); tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input")); tokeInput.clear(); - tokeInput.sendKeys("http://localhost:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET"); + tokeInput.sendKeys(EXTERNAL_CUSTOM_LAYOUT_URL); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); From 18848658f597f388c7fa492731c974c3561c4116 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 22:03:01 +0200 Subject: [PATCH 070/435] openvidu-test-e2e: new EXTERNAL_CUSTOM_LAYOUT_PARAMS system property --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- .../test/e2e/OpenViduTestAppE2eTest.java | 49 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index a8299ae0..ee62eac9 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -104,7 +104,7 @@ node('container') { } stage ('OpenVidu E2E tests') { try { - sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET test' + sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test' } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index d07ba5f5..c2b264ae 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -43,6 +43,8 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.imageio.ImageIO; @@ -123,7 +125,8 @@ public class OpenViduTestAppE2eTest { static String OPENVIDU_SECRET = "MY_SECRET"; static String OPENVIDU_URL = "https://localhost:4443/"; static String APP_URL = "http://localhost:4200/"; - static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:5555?sessionId=CUSTOM_LAYOUT_SESSION&secret=MY_SECRET"; + static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:5555"; + static String EXTERNAL_CUSTOM_LAYOUT_PARAMS = "sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET"; static Exception ex = null; private final Object lock = new Object(); @@ -164,6 +167,33 @@ public class OpenViduTestAppE2eTest { } log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); + String externalCustomLayoutParams = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_PARAMS"); + if (externalCustomLayoutParams != null) { + // Parse external layout parameters and build a URL formatted params string + List params = Stream.of(externalCustomLayoutParams.split(",", -1)).collect(Collectors.toList()); + if (params.size() % 2 != 0) { + log.error( + "Wrong configuration property EXTERNAL_CUSTOM_LAYOUT_PARAMS. Must be a comma separated list with an even number of elements. e.g: EXTERNAL_CUSTOM_LAYOUT_PARAMS=param1,value1,param2,value2"); + Assert.fail(); + return; + } else { + EXTERNAL_CUSTOM_LAYOUT_PARAMS = ""; + for (int i = 0; i < params.size(); i++) { + if (i % 2 == 0) { + // Param name + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i) + "="; + } else { + // Param value + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i); + if (i < params.size() - 1) { + EXTERNAL_CUSTOM_LAYOUT_PARAMS += "&"; + } + } + } + } + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_PARAMS); + String openviduUrl = System.getProperty("OPENVIDU_URL"); if (openviduUrl != null) { OPENVIDU_URL = openviduUrl; @@ -1840,7 +1870,7 @@ public class OpenViduTestAppE2eTest { Thread.sleep(1000); tokeInput = user.getDriver().findElement(By.id("default-custom-layout-input")); tokeInput.clear(); - tokeInput.sendKeys(EXTERNAL_CUSTOM_LAYOUT_URL); + tokeInput.sendKeys(EXTERNAL_CUSTOM_LAYOUT_URL + "?" + EXTERNAL_CUSTOM_LAYOUT_PARAMS); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2304,11 +2334,11 @@ public class OpenViduTestAppE2eTest { .allowedFilters(new String[] { "GStreamerFilter" }).build(); TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - String tokenModerator = session.generateToken(tokenOptionsModerator); + String tokenModerator = session.createToken(tokenOptionsModerator).getToken(); TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) .data(serverDataSubscriber).build(); - String tokenSubscriber = session.generateToken(tokenOptionsSubscriber); + String tokenSubscriber = session.createToken(tokenOptionsSubscriber).getToken(); Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch()); @@ -2656,9 +2686,14 @@ public class OpenViduTestAppE2eTest { } pub = connectionModerator.getPublishers().get(0); + // TODO: test delete unused Token, update unused Token and update ongoing + // Connection + session.forceUnpublish(pub); user.getEventManager().waitUntilEventReaches("streamDestroyed", 6); - Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch()); + Assert.assertFalse( + "OpenVidu.fetch() should return false because Session.forceUnpublish() already updates local objects", + OV.fetch()); session.getActiveConnections().forEach(con -> { Assert.assertEquals("Wrong number of Publishers", 0, con.getPublishers().size()); @@ -2668,7 +2703,9 @@ public class OpenViduTestAppE2eTest { session.forceDisconnect(connectionModerator); user.getEventManager().waitUntilEventReaches("sessionDisconnected", 1); user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); - Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch()); + Assert.assertFalse( + "OpenVidu.fetch() should return false because Session.forceDisconnect() already updates local objects", + OV.fetch()); session.close(); From f33cfa7bf2d4678086bcca3ee57052735bf809d8 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 1 Oct 2020 22:10:56 +0200 Subject: [PATCH 071/435] openvidu-test-e2e: reverse breaking change --- .../java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index c2b264ae..dacb9b11 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -2334,11 +2334,11 @@ public class OpenViduTestAppE2eTest { .allowedFilters(new String[] { "GStreamerFilter" }).build(); TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - String tokenModerator = session.createToken(tokenOptionsModerator).getToken(); + String tokenModerator = session.generateToken(tokenOptionsModerator); TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) .data(serverDataSubscriber).build(); - String tokenSubscriber = session.createToken(tokenOptionsSubscriber).getToken(); + String tokenSubscriber = session.generateToken(tokenOptionsSubscriber); Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch()); From 039373dc831609dff36c366256f46fc69ffaab94 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 11:38:14 +0200 Subject: [PATCH 072/435] openvidu-server: REST info log parameterized with RequestMapping value --- .../server/rest/ApiRestPathRewriteFilter.java | 3 +- .../server/rest/CDRRestController.java | 2 +- .../server/rest/ConfigRestController.java | 12 +- .../openvidu/server/rest/RequestMappings.java | 2 +- .../server/rest/SessionRestController.java | 110 +++++++++--------- 5 files changed, 63 insertions(+), 66 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java index 0acff13b..f19c2a11 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java @@ -74,9 +74,10 @@ public class ApiRestPathRewriteFilter implements Filter { StringBuffer redirectURL = new StringBuffer( ((HttpServletRequest) request).getRequestURL().toString().replaceFirst(oldBasePath, newBasePath)); + String logPathEnding = oldBasePath.endsWith("/") ? "**" : "/**"; log.warn( "Path {} is deprecated. Use path {} instead. Deprecated path will be removed in a major release in the future", - oldBasePath, newBasePath); + oldBasePath + logPathEnding, newBasePath + logPathEnding); chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) { @Override diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java index f01ed33e..47d207d2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/CDRRestController.java @@ -58,7 +58,7 @@ public class CDRRestController { @RequestMapping(method = RequestMethod.GET) public ResponseEntity listCdrFiles() { - log.info("REST API: GET /cdr"); + log.info("REST API: GET {}", RequestMappings.CDR); String cdrPath = openviduConfig.getOpenviduCdrPath(); JsonArray cdrFiles = new JsonArray(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java index b63980cd..f343bf16 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ConfigRestController.java @@ -58,7 +58,7 @@ public class ConfigRestController { @RequestMapping(method = RequestMethod.GET) public ResponseEntity getOpenViduConfiguration() { - log.info("REST API: GET /config"); + log.info("REST API: GET {}", RequestMappings.API + "/config"); return this.getConfig(); } @@ -66,7 +66,7 @@ public class ConfigRestController { @RequestMapping(value = "/openvidu-version", method = RequestMethod.GET) public String getOpenViduServerVersion() { - log.info("REST API: GET /config/openvidu-version"); + log.info("REST API: GET {}/openvidu-version", RequestMappings.API + "/config"); return openviduBuildInfo.getOpenViduServerVersion(); } @@ -74,7 +74,7 @@ public class ConfigRestController { @RequestMapping(value = "/openvidu-publicurl", method = RequestMethod.GET) public String getOpenViduPublicUrl() { - log.info("REST API: GET /config/openvidu-publicurl"); + log.info("REST API: GET {}/openvidu-publicurl", RequestMappings.API + "/config"); return openviduConfig.getFinalUrl(); } @@ -82,7 +82,7 @@ public class ConfigRestController { @RequestMapping(value = "/openvidu-recording", method = RequestMethod.GET) public Boolean getOpenViduRecordingEnabled() { - log.info("REST API: GET /config/openvidu-recording"); + log.info("REST API: GET {}/openvidu-recording", RequestMappings.API + "/config"); return openviduConfig.isRecordingModuleEnabled(); } @@ -90,7 +90,7 @@ public class ConfigRestController { @RequestMapping(value = "/openvidu-recording-path", method = RequestMethod.GET) public String getOpenViduRecordingPath() { - log.info("REST API: GET /config/openvidu-recording-path"); + log.info("REST API: GET {}/openvidu-recording-path", RequestMappings.API + "/config"); return openviduConfig.getOpenViduRecordingPath(); } @@ -98,7 +98,7 @@ public class ConfigRestController { @RequestMapping(value = "/openvidu-cdr", method = RequestMethod.GET) public Boolean getOpenViduCdrEnabled() { - log.info("REST API: GET /config/openvidu-cdr"); + log.info("REST API: GET {}/openvidu-cdr", RequestMappings.API + "/config"); return openviduConfig.isCdrEnabled(); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java index be7936c7..f9fc5509 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java @@ -4,7 +4,7 @@ public class RequestMappings { final public static String API = "/openvidu/api"; final public static String CDR = "/openvidu/cdr"; - final public static String API_ELK = "/openvidu/elasticsearch"; + final public static String API_ELK = "/openvidu/elk"; final public static String API_INSPECTOR = "/openvidu/inspector-api"; final public static String RECORDINGS = "/openvidu/recordings"; final public static String CUSTOM_LAYOUTS = "/openvidu/layouts"; diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 5882e741..f2a1a723 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -90,7 +90,7 @@ public class SessionRestController { @RequestMapping(value = "/sessions", method = RequestMethod.POST) public ResponseEntity getSessionId(@RequestBody(required = false) Map params) { - log.info("REST API: POST /api/sessions {}", params != null ? params.toString() : "{}"); + log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}"); SessionProperties.Builder builder = new SessionProperties.Builder(); String customSessionId = null; @@ -110,8 +110,7 @@ public class SessionRestController { defaultCustomLayout = (String) params.get("defaultCustomLayout"); customSessionId = (String) params.get("customSessionId"); } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/api/sessions", - HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in some parameter", "/sessions", HttpStatus.BAD_REQUEST); } try { @@ -145,7 +144,7 @@ public class SessionRestController { if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) { return this.generateErrorResponse( "Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", - "/api/sessions", HttpStatus.BAD_REQUEST); + "/sessions", HttpStatus.BAD_REQUEST); } builder = builder.customSessionId(customSessionId); } @@ -155,7 +154,7 @@ public class SessionRestController { return this.generateErrorResponse("RecordingMode " + params.get("recordingMode") + " | " + "Default OutputMode " + params.get("defaultOutputMode") + " | " + "Default RecordingLayout " + params.get("defaultRecordingLayout") + " | " + "MediaMode " + params.get("mediaMode") - + ". Some parameter is not defined", "/api/sessions", HttpStatus.BAD_REQUEST); + + ". Some parameter is not defined", "/sessions", HttpStatus.BAD_REQUEST); } } @@ -186,7 +185,7 @@ public class SessionRestController { public ResponseEntity getSession(@PathVariable("sessionId") String sessionId, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - log.info("REST API: GET /api/sessions/{}", sessionId); + log.info("REST API: GET {}/sessions/{}", RequestMappings.API, sessionId); Session session = this.sessionManager.getSession(sessionId); if (session != null) { @@ -208,7 +207,7 @@ public class SessionRestController { public ResponseEntity listSessions( @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - log.info("REST API: GET /api/sessions?webRtcStats={}", webRtcStats); + log.info("REST API: GET {}/sessions?webRtcStats={}", RequestMappings.API, webRtcStats); Collection sessions = this.sessionManager.getSessionsWithNotActive(); JsonObject json = new JsonObject(); @@ -225,7 +224,7 @@ public class SessionRestController { @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE) public ResponseEntity closeSession(@PathVariable("sessionId") String sessionId) { - log.info("REST API: DELETE /api/sessions/{}", sessionId); + log.info("REST API: DELETE {}/sessions/{}", RequestMappings.API, sessionId); Session session = this.sessionManager.getSession(sessionId); if (session != null) { @@ -249,15 +248,16 @@ public class SessionRestController { } } else { String errorMsg = "Timeout waiting for Session " + sessionId - + " closing lock to be available for closing from DELETE /api/sessions"; + + " closing lock to be available for closing from DELETE " + RequestMappings.API + + "/sessions"; log.error(errorMsg); - return this.generateErrorResponse(errorMsg, "/api/sessions", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse(errorMsg, "/sessions", HttpStatus.BAD_REQUEST); } } catch (InterruptedException e) { String errorMsg = "InterruptedException while waiting for Session " + sessionId - + " closing lock to be available for closing from DELETE /api/sessions"; + + " closing lock to be available for closing from DELETE " + RequestMappings.API + "/sessions"; log.error(errorMsg); - return this.generateErrorResponse(errorMsg, "/api/sessions", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse(errorMsg, "/sessions", HttpStatus.BAD_REQUEST); } } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -268,7 +268,7 @@ public class SessionRestController { public ResponseEntity disconnectParticipant(@PathVariable("sessionId") String sessionId, @PathVariable("connectionId") String participantPublicId) { - log.info("REST API: DELETE /api/sessions/{}/connection/{}", sessionId, participantPublicId); + log.info("REST API: DELETE {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, participantPublicId); Session session = this.sessionManager.getSessionWithNotActive(sessionId); if (session == null) { @@ -293,7 +293,7 @@ public class SessionRestController { public ResponseEntity unpublishStream(@PathVariable("sessionId") String sessionId, @PathVariable("streamId") String streamId) { - log.info("REST API: DELETE /api/sessions/{}/stream/{}", sessionId, streamId); + log.info("REST API: DELETE {}/sessions/{}/stream/{}", RequestMappings.API, sessionId, streamId); Session session = this.sessionManager.getSessionWithNotActive(sessionId); if (session == null) { @@ -326,11 +326,11 @@ public class SessionRestController { public ResponseEntity newToken(@RequestBody Map params) { if (params == null) { - return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/api/tokens", + return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/tokens", HttpStatus.BAD_REQUEST); } - log.info("REST API: POST /api/tokens {}", params.toString()); + log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString()); String sessionId; String roleString; @@ -340,18 +340,16 @@ public class SessionRestController { roleString = (String) params.get("role"); metadata = (String) params.get("data"); } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/api/tokens", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST); } if (sessionId == null) { - return this.generateErrorResponse("\"session\" parameter is mandatory", "/api/tokens", - HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("\"session\" parameter is mandatory", "/tokens", HttpStatus.BAD_REQUEST); } final Session session = this.sessionManager.getSessionWithNotActive(sessionId); if (session == null) { - return this.generateErrorResponse("Session " + sessionId + " not found", "/api/tokens", - HttpStatus.NOT_FOUND); + return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); } JsonObject kurentoOptions = null; @@ -361,7 +359,7 @@ public class SessionRestController { kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject(); } catch (Exception e) { return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object", - "/api/tokens", HttpStatus.BAD_REQUEST); + "/tokens", HttpStatus.BAD_REQUEST); } } @@ -373,7 +371,7 @@ public class SessionRestController { role = OpenViduRole.PUBLISHER; } } catch (IllegalArgumentException e) { - return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", "/api/tokens", + return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", "/tokens", HttpStatus.BAD_REQUEST); } @@ -382,7 +380,7 @@ public class SessionRestController { try { kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions); } catch (Exception e) { - return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", "/api/tokens", + return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", "/tokens", HttpStatus.BAD_REQUEST); } } @@ -432,15 +430,14 @@ public class SessionRestController { return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (Exception e) { return this.generateErrorResponse( - "Error generating token for session " + sessionId + ": " + e.getMessage(), "/api/tokens", + "Error generating token for session " + sessionId + ": " + e.getMessage(), "/tokens", HttpStatus.INTERNAL_SERVER_ERROR); } finally { session.closingLock.readLock().unlock(); } } else { log.error("Session {} is in the process of closing. Token couldn't be generated", sessionId); - return this.generateErrorResponse("Session " + sessionId + " not found", "/api/tokens", - HttpStatus.NOT_FOUND); + return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); } } @@ -448,11 +445,11 @@ public class SessionRestController { public ResponseEntity startRecordingSession(@RequestBody Map params) { if (params == null) { - return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/api/recordings/start", + return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/recordings/start", HttpStatus.BAD_REQUEST); } - log.info("REST API: POST /api/recordings/start {}", params.toString()); + log.info("REST API: POST {}/recordings/start {}", RequestMappings.API, params.toString()); if (!this.openviduConfig.isRecordingModuleEnabled()) { // OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false @@ -481,20 +478,20 @@ public class SessionRestController { shmSize = new Long(params.get("shmSize").toString()); } } catch (ClassCastException | NumberFormatException e) { - return this.generateErrorResponse("Type error in some parameter", "/api/recordings/start", + return this.generateErrorResponse("Type error in some parameter", "/recordings/start", HttpStatus.BAD_REQUEST); } if (sessionId == null) { // "session" parameter not found - return this.generateErrorResponse("\"session\" parameter is mandatory", "/api/recordings/start", + return this.generateErrorResponse("\"session\" parameter is mandatory", "/recordings/start", HttpStatus.BAD_REQUEST); } if (name != null && !name.isEmpty()) { if (!sessionManager.formatChecker.isValidRecordingName(name)) { return this.generateErrorResponse( - "Parameter 'name' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", "/api/sessions", + "Parameter 'name' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", "/sessions", HttpStatus.BAD_REQUEST); } } @@ -505,7 +502,7 @@ public class SessionRestController { try { finalOutputMode = OutputMode.valueOf(outputModeString); } catch (Exception e) { - return this.generateErrorResponse("Type error in parameter 'outputMode'", "/api/recordings/start", + return this.generateErrorResponse("Type error in parameter 'outputMode'", "/recordings/start", HttpStatus.BAD_REQUEST); } } @@ -513,14 +510,14 @@ public class SessionRestController { if (resolution != null && !sessionManager.formatChecker.isAcceptableRecordingResolution(resolution)) { return this.generateErrorResponse( "Wrong 'resolution' parameter. Acceptable values from 100 to 1999 for both width and height", - "/api/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); + "/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); } if (recordingLayoutString != null && !recordingLayoutString.isEmpty()) { try { recordingLayout = RecordingLayout.valueOf(recordingLayoutString); } catch (Exception e) { - return this.generateErrorResponse("Type error in parameter 'recordingLayout'", - "/api/recordings/start", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in parameter 'recordingLayout'", "/recordings/start", + HttpStatus.BAD_REQUEST); } } } @@ -528,7 +525,7 @@ public class SessionRestController { // Cannot start a recording with both "hasAudio" and "hasVideo" to false return this.generateErrorResponse( "Cannot start a recording with both \"hasAudio\" and \"hasVideo\" set to false", - "/api/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); + "/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); } Session session = sessionManager.getSession(sessionId); @@ -583,7 +580,7 @@ public class SessionRestController { if (shmSize != null) { if (shmSize < 134217728L) { return this.generateErrorResponse("Wrong \"shmSize\" parameter. Must be 134217728 (128 MB) minimum", - "/api/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); + "/recordings/start", HttpStatus.UNPROCESSABLE_ENTITY); } builder.shmSize(shmSize); } @@ -603,7 +600,7 @@ public class SessionRestController { @RequestMapping(value = "/recordings/stop/{recordingId}", method = RequestMethod.POST) public ResponseEntity stopRecordingSession(@PathVariable("recordingId") String recordingId) { - log.info("REST API: POST /api/recordings/stop/{}", recordingId); + log.info("REST API: POST {}/recordings/stop/{}", RequestMappings.API, recordingId); if (!this.openviduConfig.isRecordingModuleEnabled()) { // OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false @@ -645,7 +642,7 @@ public class SessionRestController { @RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.GET) public ResponseEntity getRecording(@PathVariable("recordingId") String recordingId) { - log.info("REST API: GET /api/recordings/{}", recordingId); + log.info("REST API: GET {}/recordings/{}", RequestMappings.API, recordingId); if (!this.openviduConfig.isRecordingModuleEnabled()) { // OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false @@ -667,7 +664,7 @@ public class SessionRestController { @RequestMapping(value = "/recordings", method = RequestMethod.GET) public ResponseEntity getAllRecordings() { - log.info("REST API: GET /api/recordings"); + log.info("REST API: GET {}/recordings", RequestMappings.API); if (!this.openviduConfig.isRecordingModuleEnabled()) { // OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false @@ -692,7 +689,7 @@ public class SessionRestController { @RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.DELETE) public ResponseEntity deleteRecording(@PathVariable("recordingId") String recordingId) { - log.info("REST API: DELETE /api/recordings/{}", recordingId); + log.info("REST API: DELETE {}/recordings/{}", RequestMappings.API, recordingId); if (!this.openviduConfig.isRecordingModuleEnabled()) { // OpenVidu Server configuration property "OPENVIDU_RECORDING" is set to false @@ -706,11 +703,11 @@ public class SessionRestController { public ResponseEntity signal(@RequestBody Map params) { if (params == null) { - return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/api/signal", + return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/signal", HttpStatus.BAD_REQUEST); } - log.info("REST API: POST /api/signal {}", params.toString()); + log.info("REST API: POST {}/signal {}", RequestMappings.API, params.toString()); String sessionId; String type; @@ -722,15 +719,14 @@ public class SessionRestController { type = (String) params.get("type"); data = (String) params.get("data"); } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/api/signal", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in some parameter", "/signal", HttpStatus.BAD_REQUEST); } JsonObject completeMessage = new JsonObject(); if (sessionId == null) { // "session" parameter not found - return this.generateErrorResponse("\"session\" parameter is mandatory", "/api/signal", - HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("\"session\" parameter is mandatory", "/signal", HttpStatus.BAD_REQUEST); } Session session = sessionManager.getSession(sessionId); if (session == null) { @@ -757,7 +753,7 @@ public class SessionRestController { JsonArray toArray = gson.toJsonTree(to).getAsJsonArray(); completeMessage.add("to", toArray); } catch (IllegalStateException exception) { - return this.generateErrorResponse("\"to\" parameter is not a valid JSON array", "/api/signal", + return this.generateErrorResponse("\"to\" parameter is not a valid JSON array", "/signal", HttpStatus.BAD_REQUEST); } } @@ -765,7 +761,7 @@ public class SessionRestController { try { sessionManager.sendMessage(completeMessage.toString(), sessionId); } catch (OpenViduException e) { - return this.generateErrorResponse("\"to\" array has no valid connection identifiers", "/api/signal", + return this.generateErrorResponse("\"to\" array has no valid connection identifiers", "/signal", HttpStatus.NOT_ACCEPTABLE); } @@ -777,10 +773,10 @@ public class SessionRestController { if (params == null) { return this.generateErrorResponse("Error in body parameters. Cannot be empty", - "/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } - log.info("REST API: POST /api/sessions/{}/connection {}", sessionId, params.toString()); + log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString()); Session session = this.sessionManager.getSessionWithNotActive(sessionId); if (session == null) { @@ -801,12 +797,12 @@ public class SessionRestController { networkCache = (Integer) params.get("networkCache"); data = (String) params.get("data"); } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", - "/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in some parameter", "/sessions/" + sessionId + "/connection", + HttpStatus.BAD_REQUEST); } if (rtspUri == null) { return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", - "/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } type = "IPCAM"; // Other possible values in the future @@ -837,9 +833,9 @@ public class SessionRestController { HttpStatus.OK); } catch (MalformedURLException e) { return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri", - "/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } catch (Exception e) { - return this.generateErrorResponse(e.getMessage(), "/api/sessions/" + sessionId + "/connection", + return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", HttpStatus.INTERNAL_SERVER_ERROR); } finally { session.closingLock.readLock().unlock(); @@ -855,7 +851,7 @@ public class SessionRestController { responseJson.addProperty("status", status.value()); responseJson.addProperty("error", status.getReasonPhrase()); responseJson.addProperty("message", errorMessage); - responseJson.addProperty("path", path); + responseJson.addProperty("path", RequestMappings.API + path); return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), status); } From 2d8216fb0d58f4b8be2bbc4e64ace8ea61b3b1dd Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 16:38:51 +0200 Subject: [PATCH 073/435] openvidu-server: Recording.url with new path --- .../recording/service/RecordingManagerUtilsLocalStorage.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java index e69f10e2..4c0fe3a0 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/RecordingManagerUtilsLocalStorage.java @@ -8,6 +8,7 @@ import org.springframework.http.HttpStatus; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.recording.Recording; +import io.openvidu.server.rest.RequestMappings; public class RecordingManagerUtilsLocalStorage extends RecordingManagerUtils { @@ -33,7 +34,8 @@ public class RecordingManagerUtilsLocalStorage extends RecordingManagerUtils { @Override public String getRecordingUrl(Recording recording) { - return openviduConfig.getFinalUrl() + "recordings/" + recording.getId() + "/" + recording.getName() + "." + String basePath = RequestMappings.RECORDINGS.replaceFirst("^/", "") + "/"; + return openviduConfig.getFinalUrl() + basePath + recording.getId() + "/" + recording.getName() + "." + this.getExtensionFromRecording(recording); } From 0e3e82d7e18fe55dcc2c895fcb49e96d6dc238f6 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 16:40:03 +0200 Subject: [PATCH 074/435] OpenVidu SDKs: use new paths to consume REST API --- .../io/openvidu/java/client/OpenVidu.java | 36 +++++----- .../io/openvidu/java/client/Recording.java | 49 +++++++------- .../java/client/RecordingProperties.java | 65 +++++++++++-------- openvidu-node-client/src/OpenVidu.ts | 27 +++++--- openvidu-node-client/src/Recording.ts | 51 +++++++-------- 5 files changed, 125 insertions(+), 103 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 298c07ee..1ba75945 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -70,16 +70,19 @@ public class OpenVidu { protected HttpClient httpClient; protected Map activeSessions = new ConcurrentHashMap<>(); - protected final static String API_SESSIONS = "api/sessions"; - protected final static String API_TOKENS = "api/tokens"; - protected final static String API_RECORDINGS = "api/recordings"; - protected final static String API_RECORDINGS_START = "/start"; - protected final static String API_RECORDINGS_STOP = "/stop"; + protected final static String API_PATH = "openvidu/api"; + protected final static String API_SESSIONS = API_PATH + "/sessions"; + protected final static String API_TOKENS = API_PATH + "/tokens"; + protected final static String API_RECORDINGS = API_PATH + "/recordings"; + protected final static String API_RECORDINGS_START = API_RECORDINGS + "/start"; + protected final static String API_RECORDINGS_STOP = API_RECORDINGS + "/stop"; /** - * @param urlOpenViduServer Public accessible IP where your instance of OpenVidu - * Server is up an running - * @param secret Secret used on OpenVidu Server initialization + * @param hostname URL where your instance of OpenVidu Server is up an running. + * It must be the full URL (e.g. + * https://12.34.56.78:1234/) + * + * @param secret Secret used on OpenVidu Server initialization */ public OpenVidu(String hostname, String secret) { @@ -192,7 +195,7 @@ public class OpenVidu { public Recording startRecording(String sessionId, RecordingProperties properties) throws OpenViduJavaClientException, OpenViduHttpException { - HttpPost request = new HttpPost(this.hostname + API_RECORDINGS + API_RECORDINGS_START); + HttpPost request = new HttpPost(this.hostname + API_RECORDINGS_START); JsonObject json = new JsonObject(); json.addProperty("session", sessionId); @@ -201,7 +204,8 @@ public class OpenVidu { json.addProperty("hasAudio", properties.hasAudio()); json.addProperty("hasVideo", properties.hasVideo()); - if ((Recording.OutputMode.COMPOSED.equals(properties.outputMode()) || (Recording.OutputMode.COMPOSED_QUICK_START.equals(properties.outputMode()))) + if ((Recording.OutputMode.COMPOSED.equals(properties.outputMode()) + || (Recording.OutputMode.COMPOSED_QUICK_START.equals(properties.outputMode()))) && properties.hasVideo()) { json.addProperty("resolution", properties.resolution()); json.addProperty("recordingLayout", @@ -236,8 +240,9 @@ public class OpenVidu { if (activeSession != null) { activeSession.setIsBeingRecorded(true); } else { - log.warn("No active session found for sessionId '" + r.getSessionId() - + "'. This instance of OpenVidu Java Client didn't create this session"); + log.warn( + "No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session", + r.getSessionId()); } return r; } else { @@ -352,7 +357,7 @@ public class OpenVidu { * */ public Recording stopRecording(String recordingId) throws OpenViduJavaClientException, OpenViduHttpException { - HttpPost request = new HttpPost(this.hostname + API_RECORDINGS + API_RECORDINGS_STOP + "/" + recordingId); + HttpPost request = new HttpPost(this.hostname + API_RECORDINGS_STOP + "/" + recordingId); HttpResponse response; try { response = this.httpClient.execute(request); @@ -368,8 +373,9 @@ public class OpenVidu { if (activeSession != null) { activeSession.setIsBeingRecorded(false); } else { - log.warn("No active session found for sessionId '" + r.getSessionId() - + "'. This instance of OpenVidu Java Client didn't create this session"); + log.warn( + "No active session found for sessionId '{}'. This instance of OpenVidu Java Client didn't create this session", + r.getSessionId()); } return r; } else { diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java index 305201c6..b984ed8f 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Recording.java @@ -48,9 +48,8 @@ public class Recording { stopped, /** - * The recording has finished OK and is available for download through OpenVidu - * Server recordings endpoint: - * https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION} + * The recording has finished being processed and is available for download + * through property {@link Recording#getUrl} */ ready, @@ -75,27 +74,25 @@ public class Recording { * Record each stream individually */ INDIVIDUAL, - + /** - * Works the same way as COMPOSED mode, but the necessary recorder - * service module will start some time in advance and won't be terminated - * once a specific session recording has ended. This module will remain - * up and running as long as the session remains active.

+ * Works the same way as COMPOSED mode, but the necessary recorder service + * module will start some time in advance and won't be terminated once a + * specific session recording has ended. This module will remain up and running + * as long as the session remains active.
+ *
* *
    - *
  • - * Pros vs COMPOSED: the process of starting the recording will be noticeably - * faster. This can be very useful in use cases where a session needs to be - * recorded multiple times over time, when a better response time is usually - * desirable. - *
  • - *
  • - * Cons vs COMPOSED: for every session initialized with COMPOSED_QUICK_START - * recording output mode, extra CPU power will be required in OpenVidu Server. - * The recording module will be continuously rendering all of the streams being - * published to the session even when the session is not being recorded. And that - * is for every session configured with COMPOSED_QUICK_START. - *
  • + *
  • Pros vs COMPOSED: the process of starting the recording + * will be noticeably faster. This can be very useful in use cases where a + * session needs to be recorded multiple times over time, when a better response + * time is usually desirable.
  • + *
  • Cons vs COMPOSED: for every session initialized with + * COMPOSED_QUICK_START recording output mode, extra CPU power will be required + * in OpenVidu Server. The recording module will be continuously rendering all + * of the streams being published to the session even when the session is not + * being recorded. And that is for every session configured with + * COMPOSED_QUICK_START.
  • *
*/ COMPOSED_QUICK_START; @@ -129,7 +126,8 @@ public class Recording { OutputMode outputMode = OutputMode.valueOf(json.get("outputMode").getAsString()); RecordingProperties.Builder builder = new RecordingProperties.Builder().name(json.get("name").getAsString()) .outputMode(outputMode).hasAudio(hasAudio).hasVideo(hasVideo); - if ((OutputMode.COMPOSED.equals(outputMode) || OutputMode.COMPOSED_QUICK_START.equals(outputMode)) && hasVideo) { + if ((OutputMode.COMPOSED.equals(outputMode) || OutputMode.COMPOSED_QUICK_START.equals(outputMode)) + && hasVideo) { builder.resolution(json.get("resolution").getAsString()); builder.recordingLayout(RecordingLayout.valueOf(json.get("recordingLayout").getAsString())); JsonElement customLayout = json.get("customLayout"); @@ -219,8 +217,8 @@ public class Recording { /** * URL of the recording. You can access the file from there. It is * null until recording reaches "ready" or "failed" status. If - * OpenVidu Server configuration property + * OpenVidu Server configuration property * OPENVIDU_RECORDING_PUBLIC_ACCESS is false, this path will be * secured with OpenVidu credentials */ @@ -230,7 +228,8 @@ public class Recording { /** * Resolution of the video file. Only defined if OutputMode of the Recording is - * set to {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} + * set to {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} */ public String getResolution() { return this.recordingProperties.resolution(); diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java index 47f526ae..a76ced2c 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/RecordingProperties.java @@ -52,7 +52,8 @@ public class RecordingProperties { * Builder for {@link io.openvidu.java.client.RecordingProperties} */ public RecordingProperties build() { - if (OutputMode.COMPOSED.equals(this.outputMode) || OutputMode.COMPOSED_QUICK_START.equals(this.outputMode)) { + if (OutputMode.COMPOSED.equals(this.outputMode) + || OutputMode.COMPOSED_QUICK_START.equals(this.outputMode)) { this.recordingLayout = this.recordingLayout != null ? this.recordingLayout : RecordingLayout.BEST_FIT; this.resolution = this.resolution != null ? this.resolution : "1920x1080"; if (RecordingLayout.CUSTOM.equals(this.recordingLayout)) { @@ -102,11 +103,14 @@ public class RecordingProperties { * method to set the relative path to the specific custom layout you want to * use.
* Will only have effect if - * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)} - * has been called with value - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.
- * See + * See Custom recording layouts to learn more */ public RecordingProperties.Builder customLayout(String path) { @@ -119,13 +123,15 @@ public class RecordingProperties { * format "WIDTHxHEIGHT", being both WIDTH and HEIGHT the number of pixels * between 100 and 1999.
* Will only have effect if - * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)} - * has been called with value - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. For - * {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all - * individual video files will have the native resolution of the published - * stream + * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode) + * Builder.outputMode()} has been called with value + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED + * OutputMode.COMPOSED} or + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START + * OutputMode.COMPOSED_QUICK_START}. For + * {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL + * OutputMode.INDIVIDUAL} all individual video files will have the native + * resolution of the published stream */ public RecordingProperties.Builder resolution(String resolution) { this.resolution = resolution; @@ -134,7 +140,8 @@ public class RecordingProperties { /** * Call this method to specify whether to record audio or not. Cannot be set to - * false at the same time as {@link hasVideo(boolean)} + * false at the same time as + * {@link RecordingProperties.Builder#hasVideo(boolean)} */ public RecordingProperties.Builder hasAudio(boolean hasAudio) { this.hasAudio = hasAudio; @@ -143,7 +150,8 @@ public class RecordingProperties { /** * Call this method to specify whether to record video or not. Cannot be set to - * false at the same time as {@link hasAudio(boolean)} + * false at the same time as + * {@link RecordingProperties.Builder#hasAudio(boolean)} */ public RecordingProperties.Builder hasVideo(boolean hasVideo) { this.hasVideo = hasVideo; @@ -185,12 +193,12 @@ public class RecordingProperties { /** * Defines the mode of recording: {@link Recording.OutputMode#COMPOSED} or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for a - * single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL} + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START} for + * a single archive in a grid layout or {@link Recording.OutputMode#INDIVIDUAL} * for one archive for each stream.
*
* - * Default to {@link Recording.OutputMode#COMPOSED} + * Default to {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED} */ public Recording.OutputMode outputMode() { return this.outputMode; @@ -199,12 +207,14 @@ public class RecordingProperties { /** * Defines the layout to be used in the recording.
* Will only have effect if - * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)} - * has been called with value {@link Recording.OutputMode#COMPOSED} or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}.
+ * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode) + * Builder.outputMode()} has been called with value + * {@link Recording.OutputMode#COMPOSED OutputMode.COMPOSED} or + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START + * OutputMode.COMPOSED_QUICK_START}.
*
* - * Default to {@link RecordingLayout#BEST_FIT} + * Default to {@link RecordingLayout#BEST_FIT RecordingLayout.BEST_FIT} */ public RecordingLayout recordingLayout() { return this.recordingLayout; @@ -214,7 +224,8 @@ public class RecordingProperties { * If {@link io.openvidu.java.client.RecordingProperties#recordingLayout()} is * set to {@link io.openvidu.java.client.RecordingLayout#CUSTOM}, this property * defines the relative path to the specific custom layout you want to use.
- * See Custom recording layouts to learn more */ public String customLayout() { @@ -227,8 +238,8 @@ public class RecordingProperties { * {@link io.openvidu.java.client.RecordingProperties.Builder#outputMode(Recording.OutputMode)} * has been called with value * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. For - * {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}. + * For {@link io.openvidu.java.client.Recording.OutputMode#INDIVIDUAL} all * individual video files will have the native resolution of the published * stream.
*
@@ -241,7 +252,7 @@ public class RecordingProperties { /** * Defines whether to record audio or not. Cannot be set to false at the same - * time as {@link hasVideo()}.
+ * time as {@link RecordingProperties#hasVideo()}.
*
* * Default to true @@ -252,7 +263,7 @@ public class RecordingProperties { /** * Defines whether to record video or not. Cannot be set to false at the same - * time as {@link hasAudio()}.
+ * time as {@link RecordingProperties#hasAudio()}.
*
* * Default to true diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index f6d6a318..4f572dcb 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -47,23 +47,29 @@ export class OpenVidu { /** * @hidden */ - static readonly API_RECORDINGS: string = '/api/recordings'; + static readonly API_PATH: string = '/openvidu/api'; /** * @hidden */ - static readonly API_RECORDINGS_START: string = '/start'; + static readonly API_SESSIONS = OpenVidu.API_PATH + '/sessions'; /** * @hidden */ - static readonly API_RECORDINGS_STOP: string = '/stop'; + static readonly API_TOKENS = OpenVidu.API_PATH + '/tokens'; /** * @hidden */ - static readonly API_SESSIONS = '/api/sessions'; + static readonly API_RECORDINGS: string = OpenVidu.API_PATH + '/recordings'; /** * @hidden */ - static readonly API_TOKENS = '/api/tokens'; + static readonly API_RECORDINGS_START: string = OpenVidu.API_RECORDINGS + '/start'; + /** + * @hidden + */ + static readonly API_RECORDINGS_STOP: string = OpenVidu.API_RECORDINGS + '/stop'; + + /** @@ -83,7 +89,8 @@ export class OpenVidu { activeSessions: Session[] = []; /** - * @param urlOpenViduServer Public accessible IP where your instance of OpenVidu Server is up an running + * @param urlOpenViduServer URL where your instance of OpenVidu Server is up an running. + * It must be the full URL (e.g. `https://12.34.56.78:1234/`) * @param secret Secret used on OpenVidu Server initialization */ constructor(private urlOpenViduServer: string, secret: string) { @@ -144,8 +151,8 @@ export class OpenVidu { hasAudio: !!(properties.hasAudio), hasVideo: !!(properties.hasVideo) }; - if (data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED] - || data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) { + if (data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED] + || data.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) { data.resolution = !!properties.resolution ? properties.resolution : '1920x1080'; data.recordingLayout = !!properties.recordingLayout ? properties.recordingLayout : RecordingLayout.BEST_FIT; if (data.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) { @@ -169,7 +176,7 @@ export class OpenVidu { } axios.post( - this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_START, + this.host + OpenVidu.API_RECORDINGS_START, data, { headers: { @@ -223,7 +230,7 @@ export class OpenVidu { return new Promise((resolve, reject) => { axios.post( - this.host + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId, + this.host + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId, undefined, { headers: { diff --git a/openvidu-node-client/src/Recording.ts b/openvidu-node-client/src/Recording.ts index 85635e3a..cc0989a6 100644 --- a/openvidu-node-client/src/Recording.ts +++ b/openvidu-node-client/src/Recording.ts @@ -83,7 +83,7 @@ export class Recording { hasVideo: !!json['hasVideo'] }; if (this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED] - || this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) { + || this.properties.outputMode.toString() === Recording.OutputMode[Recording.OutputMode.COMPOSED_QUICK_START]) { this.properties.resolution = !!(json['resolution']) ? json['resolution'] : '1920x1080'; this.properties.recordingLayout = !!(json['recordingLayout']) ? json['recordingLayout'] : RecordingLayout.BEST_FIT; if (this.properties.recordingLayout.toString() === RecordingLayout[RecordingLayout.CUSTOM]) { @@ -103,7 +103,7 @@ export namespace Recording { /** * The recording is starting (cannot be stopped). Some recording may not go - * through this status and directly reach "started" status + * through this status and directly reach "started" status */ starting = 'starting', @@ -113,21 +113,20 @@ export namespace Recording { started = 'started', /** - * The recording has stopped and is being processed. At some point it will reach - * "ready" status - */ + * The recording has stopped and is being processed. At some point it will reach + * "ready" status + */ stopped = 'stopped', /** - * The recording has finished OK and is available for download through OpenVidu - * Server recordings endpoint: - * https://YOUR_OPENVIDUSERVER_IP/recordings/{RECORDING_ID}/{RECORDING_NAME}.{EXTENSION} + * The recording has finished being processed and is available for download through + * property [[Recording.url]] */ ready = 'ready', /** * The recording has failed. This status may be reached from "starting", - * "started" and "stopped" status + * "started" and "stopped" status */ failed = 'failed' } @@ -141,24 +140,24 @@ export namespace Recording { * Record all streams in a grid layout in a single archive */ COMPOSED = 'COMPOSED', - - /** - * Works the same way as COMPOSED mode, but the necessary recorder - * service module will start some time in advance and won't be terminated - * once a specific session recording has ended. This module will remain - * up and running as long as the session remains active. - * - * - **Pros vs COMPOSED**: the process of starting the recording will be noticeably - * faster. This can be very useful in use cases where a session needs to be - * recorded multiple times over time, when a better response time is usually - * desirable. - * - **Cons vs COMPOSED**: for every session initialized with COMPOSED_QUICK_START - * recording output mode, extra CPU power will be required in OpenVidu Server. - * The recording module will be continuously rendering all of the streams being - * published to the session even when the session is not being recorded. And that - * is for every session configured with COMPOSED_QUICK_START. - */ + /** + * Works the same way as COMPOSED mode, but the necessary recorder + * service module will start some time in advance and won't be terminated + * once a specific session recording has ended. This module will remain + * up and running as long as the session remains active. + * + * - **Pros vs COMPOSED**: the process of starting the recording will be noticeably + * faster. This can be very useful in use cases where a session needs to be + * recorded multiple times over time, when a better response time is usually + * desirable. + + * - **Cons vs COMPOSED**: for every session initialized with COMPOSED_QUICK_START + * recording output mode, extra CPU power will be required in OpenVidu Server. + * The recording module will be continuously rendering all of the streams being + * published to the session even when the session is not being recorded. And that + * is for every session configured with COMPOSED_QUICK_START. + */ COMPOSED_QUICK_START = 'COMPOSED_QUICK_START', /** From 3bfbc37d5e4d383bef9653b3b2bcd10080c37f1c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 17:10:59 +0200 Subject: [PATCH 075/435] openvidu-server dashboard updated to use new REST API path --- .../src/dashboard/src/app/services/rest.service.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openvidu-server/src/dashboard/src/app/services/rest.service.ts b/openvidu-server/src/dashboard/src/app/services/rest.service.ts index 0e2425d6..0abfea57 100644 --- a/openvidu-server/src/dashboard/src/app/services/rest.service.ts +++ b/openvidu-server/src/dashboard/src/app/services/rest.service.ts @@ -7,6 +7,7 @@ import { throwError } from 'rxjs'; export class RestService { private openviduPublicUrl: string; + private API_PATH: string = 'openvidu/api'; constructor(private httpClient: HttpClient) { } @@ -16,7 +17,7 @@ export class RestService { resolve(this.openviduPublicUrl); } else { this.httpClient.get(location.protocol + '//' + location.hostname + ((!!location.port) ? (':' + location.port) : '') + - '/config/openvidu-publicurl', { responseType: 'text' }).pipe( + '/' + this.API_PATH + '/config/openvidu-publicurl', { responseType: 'text' }).pipe( catchError(error => { reject(error); return throwError(error); @@ -44,7 +45,7 @@ export class RestService { 'Content-Type': 'application/json' }) }; - this.httpClient.post(this.openviduPublicUrl + 'api/sessions', body, options) + this.httpClient.post(this.openviduPublicUrl + this.API_PATH + '/sessions', body, options) .pipe( catchError(error => { reject(error); @@ -66,7 +67,7 @@ export class RestService { 'Content-Type': 'application/json' }) }; - this.httpClient.post(this.openviduPublicUrl + 'api/tokens', body, options) + this.httpClient.post(this.openviduPublicUrl + this.API_PATH + '/tokens', body, options) .pipe( catchError(error => { reject(error); From aeccab73996cb374339d15667100cd7c899eb0d4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 18:10:49 +0200 Subject: [PATCH 076/435] openvidu-test-e2e: new REST API paths. Improve assertMediaTracks method --- .../test/e2e/OpenViduEventManager.java | 51 ++- .../test/e2e/OpenViduTestAppE2eTest.java | 336 ++++++++++-------- 2 files changed, 227 insertions(+), 160 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java index 1bb933b4..63d453b4 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java @@ -196,6 +196,10 @@ public class OpenViduEventManager { boolean videoTransmission) { boolean success = true; for (WebElement video : videoElements) { + if (!waitUntilSrcObjectDefined(video, "", 5000)) { + System.err.println("srcObject of HTMLVideoElement was not defined!"); + return false; + } success = success && (audioTransmission == this.hasAudioTracks(video, "")) && (videoTransmission == this.hasVideoTracks(video, "")); if (!success) @@ -208,6 +212,10 @@ public class OpenViduEventManager { boolean videoTransmission, String parentSelector) { boolean success = true; for (WebElement video : videoElements) { + if (!waitUntilSrcObjectDefined(video, "", 5000)) { + System.err.println("srcObject of HTMLVideoElement was not defined!"); + return false; + } success = success && (audioTransmission == this.hasAudioTracks(video, parentSelector)) && (videoTransmission == this.hasVideoTracks(video, parentSelector)); if (!success) @@ -314,21 +322,44 @@ public class OpenViduEventManager { } private boolean hasAudioTracks(WebElement videoElement, String parentSelector) { - boolean audioTracks = (boolean) ((JavascriptExecutor) driver).executeScript( - "return ((document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" - + videoElement.getAttribute("id") + "').srcObject.getAudioTracks().length > 0)" - + "&& (document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" - + videoElement.getAttribute("id") + "').srcObject.getAudioTracks()[0].enabled))"); + String script = "return ((document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + + "#" + videoElement.getAttribute("id") + "').srcObject.getAudioTracks().length > 0)" + + " && (document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" + + videoElement.getAttribute("id") + "').srcObject.getAudioTracks()[0].enabled))"; + boolean audioTracks = (boolean) ((JavascriptExecutor) driver).executeScript(script); return audioTracks; } private boolean hasVideoTracks(WebElement videoElement, String parentSelector) { - boolean videoTracks = (boolean) ((JavascriptExecutor) driver).executeScript( - "return ((document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" - + videoElement.getAttribute("id") + "').srcObject.getVideoTracks().length > 0)" - + "&& (document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" - + videoElement.getAttribute("id") + "').srcObject.getVideoTracks()[0].enabled))"); + String script = "return ((document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + + "#" + videoElement.getAttribute("id") + "').srcObject.getVideoTracks().length > 0)" + + " && (document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + "#" + + videoElement.getAttribute("id") + "').srcObject.getVideoTracks()[0].enabled))"; + boolean videoTracks = (boolean) ((JavascriptExecutor) driver).executeScript(script); return videoTracks; } + private boolean waitUntilSrcObjectDefined(WebElement videoElement, String parentSelector, int maxMsWait) { + final int sleepInterval = 50; + int maxIterations = maxMsWait / sleepInterval; + int counter = 0; + boolean defined = srcObjectDefined(videoElement, parentSelector); + while (!defined && counter < maxIterations) { + try { + Thread.sleep(sleepInterval); + } catch (InterruptedException e) { + } + defined = srcObjectDefined(videoElement, parentSelector); + counter++; + } + return defined; + } + + private boolean srcObjectDefined(WebElement videoElement, String parentSelector) { + String script = "return (!!(document.querySelector('" + parentSelector + (parentSelector.isEmpty() ? "" : " ") + + "#" + videoElement.getAttribute("id") + "').srcObject))"; + boolean defined = (boolean) ((JavascriptExecutor) driver).executeScript(script); + return defined; + } + } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index dacb9b11..3980b7ad 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -544,8 +544,6 @@ public class OpenViduTestAppE2eTest { @DisplayName("Cross-Browser test") void crossBrowserTest() throws Exception { - setupBrowser("chrome"); - log.info("Cross-Browser test"); Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() { @@ -557,7 +555,9 @@ public class OpenViduTestAppE2eTest { } }; - Thread t = new Thread(() -> { + final CountDownLatch latch = new CountDownLatch(2); + + Thread threadFirefox = new Thread(() -> { MyUser user2 = new MyUser(new FirefoxUser("TestUser", 30)); otherUsers.add(user2); user2.getDriver().get(APP_URL); @@ -583,36 +583,61 @@ public class OpenViduTestAppE2eTest { Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + latch.countDown(); + if (!latch.await(30, TimeUnit.SECONDS)) { + Assert.fail("The other browser didn't play the stream within the timeout"); + } + user2.getEventManager().waitUntilEventReaches("streamDestroyed", 1); user2.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); user2.getDriver().findElement(By.id("remove-user-btn")).click(); user2.getEventManager().waitUntilEventReaches("sessionDisconnected", 1); } catch (Exception e) { e.printStackTrace(); - user2.dispose(); Thread.currentThread().interrupt(); + Assert.fail("Exception on Firefox participant: " + e.getMessage()); + } finally { + user2.dispose(); } - user2.dispose(); }); - t.setUncaughtExceptionHandler(h); - t.start(); - user.getDriver().findElement(By.id("add-user-btn")).click(); - user.getDriver().findElement(By.className("join-btn")).click(); + Thread threadChrome = new Thread(() -> { + setupBrowser("chrome"); + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.className("join-btn")).click(); - user.getEventManager().waitUntilEventReaches("connectionCreated", 2); - user.getEventManager().waitUntilEventReaches("accessAllowed", 1); - user.getEventManager().waitUntilEventReaches("streamCreated", 2); - user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + try { + user.getEventManager().waitUntilEventReaches("connectionCreated", 2); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 2); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); - final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); - Assert.assertEquals("Expected 2 videos but found " + numberOfVideos, 2, numberOfVideos); - Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() - .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); + Assert.assertEquals("Expected 2 videos but found " + numberOfVideos, 2, numberOfVideos); + Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() + .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); - gracefullyLeaveParticipants(1); + latch.countDown(); + if (!latch.await(30, TimeUnit.SECONDS)) { + Assert.fail("The other browser didn't play the stream within the timeout"); + } - t.join(); + gracefullyLeaveParticipants(1); + } catch (Exception e) { + e.printStackTrace(); + Assert.fail("Exception on Chrome participant: " + e.getMessage()); + Thread.currentThread().interrupt(); + } finally { + user.dispose(); + } + }); + + threadFirefox.setUncaughtExceptionHandler(h); + threadChrome.setUncaughtExceptionHandler(h); + threadFirefox.start(); + threadChrome.start(); + threadFirefox.join(); + threadChrome.join(); synchronized (lock) { if (OpenViduTestAppE2eTest.ex != null) { @@ -2729,126 +2754,128 @@ public class OpenViduTestAppE2eTest { String wrongCredentials = "Basic " + Base64.getEncoder().encodeToString(("OPENVIDUAPP:WRONG_SECRET").getBytes()); Assert.assertEquals("Expected unauthorized status", HttpStatus.SC_UNAUTHORIZED, - restClient.getAndReturnStatus("/config", wrongCredentials)); + restClient.getAndReturnStatus("/openvidu/api/config", wrongCredentials)); - /** GET /api/sessions (before session created) **/ - restClient.rest(HttpMethod.GET, "/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, + /** GET /openvidu/api/sessions (before session created) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); - /** POST /api/sessions **/ + /** POST /openvidu/api/sessions **/ // 400 String body = "{'mediaMode': 'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); body = "{'mediaMode': 'ROUTED', 'recordingMode': false}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'customSessionId': 999}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); body = "{'mediaMode': 'ROUTED', 'recordingMode': 'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'defaultOutputMode': 'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); body = "{'mediaMode': 'ROUTED', 'recordingMode': 'ALWAYS', 'defaultOutputMode': 'INDIVIDUAL', 'defaultRecordingLayout': 'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_BAD_REQUEST); // 200 body = "{'mediaMode': 'ROUTED', 'recordingMode': 'MANUAL', 'customSessionId': 'CUSTOM_SESSION_ID', 'defaultOutputMode': 'COMPOSED', 'defaultRecordingLayout': 'BEST_FIT'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK, true, "{'id': 'STR', 'createdAt': 0}"); // Default values - JsonObject res = restClient.rest(HttpMethod.POST, "/api/sessions", "{}", HttpStatus.SC_OK, true, + JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{}", HttpStatus.SC_OK, true, "{'id': 'STR', 'createdAt': 0}"); - restClient.rest(HttpMethod.DELETE, "/api/sessions/" + res.get("id").getAsString(), HttpStatus.SC_NO_CONTENT); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), + HttpStatus.SC_NO_CONTENT); // 409 body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_CONFLICT); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_CONFLICT); - /** GET /api/sessions (after session created) **/ - restClient.rest(HttpMethod.GET, "/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, + /** GET /openvidu/api/sessions (after session created) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, "{'sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':true}"); - restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, ImmutableMap.of("numberOfElements", new Integer(1), "content", new JsonArray())); - /** POST /api/tokens **/ + /** POST /openvidu/api/tokens **/ // 400 body = "{}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': true}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 999}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': false}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': 'NOT_EXISTS'}}"; - restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); // 200 body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': ['GStreamerFilter']}}"; - res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK, true, + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR','kurentoOptions':{'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); - Assert.assertEquals("JSON return value from /api/tokens should have equal srtings in 'id' and 'token'", + Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); // Default values body = "{'session': 'CUSTOM_SESSION_ID'}"; - res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK, true, + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR'}"); final String token2 = res.get("id").getAsString(); - /** POST /api/signal (NOT ACTIVE SESSION) **/ + /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ body = "{}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': true}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'CUSTOM_SESSION_ID','to':12}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'CUSTOM_SESSION_ID','to':[],'data':false}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'CUSTOM_SESSION_ID','to':[],'data': 'SERVERMESSAGE', 'type': true}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No connections + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No connections - /** POST /api/recordings/start (NOT ACTIVE SESSION) **/ + /** POST /openvidu/api/recordings/start (NOT ACTIVE SESSION) **/ // 400 body = "{}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); body = "{'session': true}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'SESSION_ID','name':999}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'SESSION_ID','name':'NAME','outputMode':'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'SESSION_ID','name':'NAME','outputMode':'COMPOSED','recordingLayout':'NOT_EXISTS'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); body = "{'session':'SESSION_ID','name':'NAME','outputMode':'COMPOSED','recordingLayout':'BEST_FIT','customLayout':'CUSTOM_LAYOUT','hasAudio':true,'hasVideo':true,'resolution':999}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_BAD_REQUEST); // 422 body = "{'session':'SESSION_ID','name':'NAME','outputMode':'COMPOSED','recordingLayout':'BEST_FIT','customLayout':'CUSTOM_LAYOUT','hasAudio':false,'hasVideo':false}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_UNPROCESSABLE_ENTITY); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_UNPROCESSABLE_ENTITY); body = "{'session':'SESSION_ID','name':'NAME','outputMode':'COMPOSED','recordingLayout':'BEST_FIT','customLayout':'CUSTOM_LAYOUT','hasAudio':true,'hasVideo':true,'resolution':'1920x2000'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_UNPROCESSABLE_ENTITY); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_UNPROCESSABLE_ENTITY); // 404 body = "{'session':'SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_NOT_FOUND); // 406 body = "{'session':'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_NOT_ACCEPTABLE); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_NOT_ACCEPTABLE); // 409 (RELAYED media mode) - res = restClient.rest(HttpMethod.POST, "/api/sessions", "{'mediaMode':'RELAYED'}", HttpStatus.SC_OK, true, - "{'id': 'STR', 'createdAt': 0}"); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'mediaMode':'RELAYED'}", HttpStatus.SC_OK, + true, "{'id': 'STR', 'createdAt': 0}"); body = "{'session':'" + res.get("id").getAsString() + "'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_CONFLICT); - restClient.rest(HttpMethod.DELETE, "/api/sessions/" + res.get("id").getAsString(), HttpStatus.SC_NO_CONTENT); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_CONFLICT); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), + HttpStatus.SC_NO_CONTENT); // Start session setupBrowser("chrome"); @@ -2885,15 +2912,15 @@ public class OpenViduTestAppE2eTest { Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); - /** GET /api/recordings (before recording started) **/ - restClient.rest(HttpMethod.GET, "/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.GET, "/api/recordings", null, HttpStatus.SC_OK, true, + /** GET /openvidu/api/recordings (before recording started) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, ImmutableMap.of("count", new Integer(0), "items", new JsonArray())); - /** POST /api/recordings/start (ACTIVE SESSION) **/ + /** POST /openvidu/api/recordings/start (ACTIVE SESSION) **/ // 200 body = "{'session':'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_OK, true, "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':null,'status':'STR'}"); user.getEventManager().waitUntilEventReaches("recordingStarted", 2); @@ -2901,41 +2928,43 @@ public class OpenViduTestAppE2eTest { Thread.sleep(2000); // 409 (already recording) - restClient.rest(HttpMethod.POST, "/api/recordings/start", body, HttpStatus.SC_CONFLICT); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_CONFLICT); - /** POST /api/recordings/stop **/ + /** POST /openvidu/api/recordings/stop **/ // 405 - restClient.rest(HttpMethod.POST, "/api/recordings/stop", body, HttpStatus.SC_METHOD_NOT_ALLOWED); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop", body, HttpStatus.SC_METHOD_NOT_ALLOWED); // 404 - restClient.rest(HttpMethod.POST, "/api/recordings/stop/NOT_EXISTS", body, HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/NOT_EXISTS", body, HttpStatus.SC_NOT_FOUND); // 200 - restClient.rest(HttpMethod.DELETE, "/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_CONFLICT); - restClient.rest(HttpMethod.POST, "/api/recordings/stop/CUSTOM_SESSION_ID", body, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_CONFLICT); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/CUSTOM_SESSION_ID", body, HttpStatus.SC_OK, + true, "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); - /** GET /api/recordings (after recording created) **/ - restClient.rest(HttpMethod.GET, "/api/recordings/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, + /** GET /openvidu/api/recordings (after recording created) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); - restClient.rest(HttpMethod.GET, "/api/recordings", null, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, ImmutableMap.of("count", new Integer(1), "items", new JsonArray())); user.getEventManager().waitUntilEventReaches("recordingStopped", 2); - /** DELETE /api/recordings **/ - restClient.rest(HttpMethod.DELETE, "/api/recordings", HttpStatus.SC_METHOD_NOT_ALLOWED); - restClient.rest(HttpMethod.DELETE, "/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.DELETE, "/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); + /** DELETE /openvidu/api/recordings **/ + restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings", HttpStatus.SC_METHOD_NOT_ALLOWED); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); - // GET /api/recordings should return empty again - restClient.rest(HttpMethod.GET, "/api/recordings", null, HttpStatus.SC_OK, true, + // GET /openvidu/api/recordings should return empty again + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, ImmutableMap.of("count", new Integer(0), "items", new JsonArray())); - /** DELETE /api/sessions//stream/ **/ - restClient.rest(HttpMethod.DELETE, "/api/sessions/NOT_EXISTS/stream/NOT_EXISTS", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/stream/NOT_EXISTS", + /** DELETE /openvidu/api/sessions//stream/ **/ + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/NOT_EXISTS/stream/NOT_EXISTS", + HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/stream/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - res = restClient.rest(HttpMethod.GET, "/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, + res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, "{'sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':2,'content'" + ":[{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','token':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[" + "{'createdAt':0,'streamId':'STR','mediaOptions':{'hasAudio':false,'audioActive':false,'hasVideo':false,'videoActive':false,'typeOfVideo':'STR','frameRate':0," @@ -2945,55 +2974,59 @@ public class OpenViduTestAppE2eTest { String streamId = res.get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0) .getAsJsonObject().get("publishers").getAsJsonArray().get(0).getAsJsonObject().get("streamId") .getAsString(); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/stream/" + streamId, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/stream/" + streamId, HttpStatus.SC_NO_CONTENT); final String connectionId = res.get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0) .getAsJsonObject().get("connectionId").getAsString(); - /** POST /api/signal (ACTIVE SESSION) **/ + /** POST /openvidu/api/signal (ACTIVE SESSION) **/ body = "{'session':'CUSTOM_SESSION_ID','to':['wrongConnectionId']}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No valid connectionId + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No valid + // connectionId body = "{'session':'CUSTOM_SESSION_ID','to':['" + connectionId + "','wrongConnectionId']}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No valid connectionId + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_NOT_ACCEPTABLE); // No valid + // connectionId body = "{'session':'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("signal", 2); body = "{'session':'CUSTOM_SESSION_ID','to':[],'type':'server1','data':'SERVER EVENT!'}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("signal:server1", 2); body = "{'session':'CUSTOM_SESSION_ID','to':['" + connectionId + "'],'type':'server2','data':'SERVER EVENT!'}"; - restClient.rest(HttpMethod.POST, "/api/signal", body, HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", body, HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("signal:server2", 1); Assert.assertEquals("", 1, user.getDriver() .findElements(By.xpath("//*[text()='server - signal:server2 - SERVER EVENT!']")).size()); - /** DELETE /api/sessions//connection/ **/ - restClient.rest(HttpMethod.DELETE, "/api/sessions/NOT_EXISTS/connection/NOT_EXISTS", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/connection/NOT_EXISTS", + /** DELETE /openvidu/api/sessions//connection/ **/ + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/NOT_EXISTS/connection/NOT_EXISTS", + HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, HttpStatus.SC_NO_CONTENT); - /** DELETE /api/sessions **/ - restClient.rest(HttpMethod.DELETE, "/api/sessions", HttpStatus.SC_METHOD_NOT_ALLOWED); - restClient.rest(HttpMethod.DELETE, "/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); + /** DELETE /openvidu/api/sessions **/ + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions", HttpStatus.SC_METHOD_NOT_ALLOWED); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); - // GET /api/sessions should return empty again - restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, + // GET /openvidu/api/sessions should return empty again + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); /** - * DELETE /api/sessions//connection/ (unused token) + * DELETE /openvidu/api/sessions//connection/ (unused + * token) **/ body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/api/sessions", body, HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); body = "{'session': 'CUSTOM_SESSION_ID'}"; - res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String tokenAConnectionId = res.get("connectionId").getAsString(); final String tokenA = res.get("token").getAsString(); - res = restClient.rest(HttpMethod.POST, "/api/tokens", body, HttpStatus.SC_OK); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String tokenB = res.get("token").getAsString(); final String tokenBConnectionId = res.get("connectionId").getAsString(); @@ -3019,7 +3052,7 @@ public class OpenViduTestAppE2eTest { Thread.sleep(1000); // Invalidate token - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId, HttpStatus.SC_NO_CONTENT); // First user should pop up invalid token @@ -3045,18 +3078,18 @@ public class OpenViduTestAppE2eTest { // connectionId should be equal to the one brought by the token Assert.assertEquals("Wrong connectionId", tokenBConnectionId, - restClient.rest(HttpMethod.GET, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK).get("connections") - .getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject().get("connectionId") - .getAsString()); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK) + .get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject() + .get("connectionId").getAsString()); - restClient.rest(HttpMethod.DELETE, "/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); - // GET /api/sessions should return empty again - restClient.rest(HttpMethod.GET, "/api/sessions", null, HttpStatus.SC_OK, true, + // GET /openvidu/api/sessions should return empty again + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); - /** GET /config **/ - restClient.rest(HttpMethod.GET, "/config", null, HttpStatus.SC_OK, true, + /** GET /openvidu/api/config **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, "{'VERSION':'STR','DOMAIN_OR_PUBLIC_IP':'STR','HTTPS_PORT':0,'OPENVIDU_PUBLICURL':'STR','OPENVIDU_CDR':false,'OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH':0," + "'OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH':0,'OPENVIDU_SESSIONS_GARBAGE_INTERVAL':0,'OPENVIDU_SESSIONS_GARBAGE_THRESHOLD':0," + "'OPENVIDU_RECORDING':false,'OPENVIDU_RECORDING_VERSION':'STR','OPENVIDU_RECORDING_PATH':'STR','OPENVIDU_RECORDING_PUBLIC_ACCESS':false,'OPENVIDU_RECORDING_NOTIFICATION':'STR'," @@ -3390,24 +3423,25 @@ public class OpenViduTestAppE2eTest { CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); // Wrong session [404] - restClient.rest(HttpMethod.POST, "/api/sessions/WRONG_SESSION/connection", "{}", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/WRONG_SESSION/connection", "{}", + HttpStatus.SC_NOT_FOUND); // Init a session and publish IP camera AS FIRST PARTICIPANT - restClient.rest(HttpMethod.POST, "/api/sessions", "{'customSessionId':'IP_CAM_SESSION'}", HttpStatus.SC_OK, - true, "{'id': 'STR', 'createdAt': 0}"); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'IP_CAM_SESSION'}", + HttpStatus.SC_OK, true, "{'id': 'STR', 'createdAt': 0}"); // No rtspUri [400] - restClient.rest(HttpMethod.POST, "/api/sessions/IP_CAM_SESSION/connection", "{}", + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", "{}", HttpStatus.SC_BAD_REQUEST); // Wrong rtspUri (invalid url format) [400] - restClient.rest(HttpMethod.POST, "/api/sessions/IP_CAM_SESSION/connection", "{'rtspUri': 'NOT_A_URL'}", - HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", + "{'rtspUri': 'NOT_A_URL'}", HttpStatus.SC_BAD_REQUEST); // Publish IP camera. Dummy URL because no user will subscribe to it [200] String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; - JsonObject response = restClient.rest(HttpMethod.POST, "/api/sessions/IP_CAM_SESSION/connection", ipCamBody, - HttpStatus.SC_OK, true, + JsonObject response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", + ipCamBody, HttpStatus.SC_OK, true, "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); CustomWebhook.waitForEvent("sessionCreated", 1); @@ -3432,12 +3466,12 @@ public class OpenViduTestAppE2eTest { // Can't delete the stream [405] restClient.rest(HttpMethod.DELETE, - "/api/sessions/IP_CAM_SESSION/stream/" + ipCamPublisher.get("streamId").getAsString(), + "/openvidu/api/sessions/IP_CAM_SESSION/stream/" + ipCamPublisher.get("streamId").getAsString(), HttpStatus.SC_METHOD_NOT_ALLOWED); // Can delete the connection [204] restClient.rest(HttpMethod.DELETE, - "/api/sessions/IP_CAM_SESSION/connection/" + response.get("connectionId").getAsString(), + "/openvidu/api/sessions/IP_CAM_SESSION/connection/" + response.get("connectionId").getAsString(), HttpStatus.SC_NO_CONTENT); response = CustomWebhook.waitForEvent("webrtcConnectionDestroyed", 1); @@ -3475,36 +3509,37 @@ public class OpenViduTestAppE2eTest { CustomWebhook.waitForEvent("webrtcConnectionCreated", 1); // Composed recording to get an MP4 file AUDIO + VIDEO - restClient.rest(HttpMethod.POST, "/api/recordings/start", + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", "{'session':'TestSession','name':'audioVideo','hasAudio':true,'hasVideo':true}", HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("recordingStarted", 1); // Started CustomWebhook.waitForEvent("recordingStatusChanged", 1); Thread.sleep(4000); - restClient.rest(HttpMethod.POST, "/api/recordings/stop/TestSession", HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/TestSession", HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("recordingStopped", 1); CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Stopped CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Ready // Composed recording to get an MP4 file ONLY VIDEO - restClient.rest(HttpMethod.POST, "/api/recordings/start", + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", "{'session':'TestSession','name':'videoOnly','hasAudio':false,'hasVideo':true}", HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("recordingStarted", 1); // Started CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Started Thread.sleep(4000); - restClient.rest(HttpMethod.POST, "/api/recordings/stop/TestSession-1", HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/TestSession-1", HttpStatus.SC_OK); user.getEventManager().waitUntilEventReaches("recordingStopped", 1); CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Stopped CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Ready // Publish the MP4 file as an IPCAM - String recPath = restClient.rest(HttpMethod.GET, "/config", HttpStatus.SC_OK).get("OPENVIDU_RECORDING_PATH") - .getAsString(); + String recPath = restClient.rest(HttpMethod.GET, "/openvidu/api/config", HttpStatus.SC_OK) + .get("OPENVIDU_RECORDING_PATH").getAsString(); recPath = recPath.endsWith("/") ? recPath : (recPath + "/"); String fullRecordingPath = "file://" + recPath + "TestSession/audioVideo.mp4"; ipCamBody = "{'type':'IPCAM','rtspUri':'" + fullRecordingPath + "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; - restClient.rest(HttpMethod.POST, "/api/sessions/TestSession/connection", ipCamBody, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, + HttpStatus.SC_OK, true, "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); user.getEventManager().waitUntilEventReaches("connectionCreated", 2); @@ -3531,7 +3566,7 @@ public class OpenViduTestAppE2eTest { user.getWaiter().until(ExpectedConditions.numberOfElementsToBe(By.tagName("video"), 1)); // Publish again the IPCAM - response = restClient.rest(HttpMethod.POST, "/api/sessions/TestSession/connection", ipCamBody, + response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, HttpStatus.SC_OK, true, "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); user.getEventManager().waitUntilEventReaches("connectionCreated", 3); @@ -3551,17 +3586,17 @@ public class OpenViduTestAppE2eTest { CustomWebhook.waitForEvent("webrtcConnectionDestroyed", 1); CustomWebhook.waitForEvent("participantLeft", 1); - restClient.rest(HttpMethod.GET, "/api/sessions/TestSession", null, HttpStatus.SC_OK); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/TestSession", null, HttpStatus.SC_OK); // Test IPCAM individual recording (IPCAM audio+video, recording audio+video) - response = restClient.rest(HttpMethod.POST, "/api/recordings/start", + response = restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", "{'session':'TestSession','outputMode':'INDIVIDUAL','hasAudio':true,'hasVideo':true}", HttpStatus.SC_OK); String recId = response.get("id").getAsString(); CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Started Thread.sleep(2000); - restClient.rest(HttpMethod.POST, "/api/recordings/stop/" + recId, HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/" + recId, HttpStatus.SC_OK); CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Stopped CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Ready @@ -3571,7 +3606,7 @@ public class OpenViduTestAppE2eTest { // Test IPCAM individual recording (IPCAM video only, recording audio and video) // Disconnect audio+video IPCAM - restClient.rest(HttpMethod.DELETE, "/api/sessions/TestSession/connection/" + connectionId, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/TestSession/connection/" + connectionId, HttpStatus.SC_NO_CONTENT); // Session is closed (create new session) @@ -3579,12 +3614,13 @@ public class OpenViduTestAppE2eTest { CustomWebhook.waitForEvent("participantLeft", 1); CustomWebhook.waitForEvent("sessionDestroyed", 1); - restClient.rest(HttpMethod.POST, "/api/sessions", "{'customSessionId':'TestSession'}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'TestSession'}", + HttpStatus.SC_OK); // Publish video only IPCAM fullRecordingPath = "file://" + recPath + "TestSession-1/videoOnly.mp4"; ipCamBody = "{'rtspUri':'" + fullRecordingPath + "'}"; - response = restClient.rest(HttpMethod.POST, "/api/sessions/TestSession/connection", ipCamBody, + response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, HttpStatus.SC_OK); CustomWebhook.waitForEvent("sessionCreated", 1); CustomWebhook.waitForEvent("participantJoined", 1); @@ -3592,21 +3628,21 @@ public class OpenViduTestAppE2eTest { // Record audio and video // TODO: THIS SHOULD WORK -// response = restClient.rest(HttpMethod.POST, "/api/recordings/start", +// response = restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", // "{'session':'TestSession','outputMode':'INDIVIDUAL','hasAudio':true,'hasVideo':true}", // HttpStatus.SC_OK); // recId = response.get("id").getAsString(); // CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Started // // Thread.sleep(2000); -// restClient.rest(HttpMethod.POST, "/api/recordings/stop/TestSession-2", HttpStatus.SC_OK); +// restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/TestSession-2", HttpStatus.SC_OK); // CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Stopped // CustomWebhook.waitForEvent("recordingStatusChanged", 1); // Ready // // recording = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(recId); // this.checkIndividualRecording(recPath + recId + "/", recording, 1, "opus", "vp8", true); - restClient.rest(HttpMethod.DELETE, "/api/sessions/TestSession", HttpStatus.SC_NO_CONTENT); + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/TestSession", HttpStatus.SC_NO_CONTENT); CustomWebhook.waitForEvent("webrtcConnectionDestroyed", 1); CustomWebhook.waitForEvent("participantLeft", 1); From 683511ba2768298cadb5a160413556098ef57f3d Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 18:12:25 +0200 Subject: [PATCH 077/435] openvidu-testapp: new REST API paths --- .../components/test-scenarios/test-scenarios.component.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openvidu-testapp/src/app/components/test-scenarios/test-scenarios.component.ts b/openvidu-testapp/src/app/components/test-scenarios/test-scenarios.component.ts index 62b48932..8de48df9 100644 --- a/openvidu-testapp/src/app/components/test-scenarios/test-scenarios.component.ts +++ b/openvidu-testapp/src/app/components/test-scenarios/test-scenarios.component.ts @@ -84,6 +84,8 @@ export class TestScenariosComponent implements OnInit, OnDestroy { textAreaValue = ''; isFocusedOnReport = false; + private API_PATH = 'openvidu/api'; + constructor( private openviduParamsService: OpenviduParamsService, private testFeedService: TestFeedService, @@ -368,7 +370,7 @@ export class TestScenariosComponent implements OnInit, OnDestroy { private updateRemoteStreamsInfo() { let headers = new HttpHeaders(); headers = headers.append('Authorization', 'Basic ' + btoa('OPENVIDUAPP:' + this.openviduSecret)); - this.http.get(this.openviduUrl + 'api/sessions/' + this.fixedSessionId + '?webRtcStats=true', { headers }).subscribe( + this.http.get(this.openviduUrl + this.API_PATH + '/sessions/' + this.fixedSessionId + '?webRtcStats=true', { headers }).subscribe( sessionInfo => { this.report.streamsOut.content.forEach(report => { @@ -445,7 +447,7 @@ export class TestScenariosComponent implements OnInit, OnDestroy { /*addReportForStreamConcurrent(event: StreamManagerWrapper) { let headers = new HttpHeaders(); headers = headers.append('Authorization', 'Basic ' + btoa('OPENVIDUAPP:' + this.openviduSecret)); - this.http.get(this.openviduUrl + 'api/sessions/' + this.fixedSessionId + '?webRtcStats=true', { headers }).subscribe( + this.http.get(this.openviduUrl + this.API_PATH + '/sessions/' + this.fixedSessionId + '?webRtcStats=true', { headers }).subscribe( sessionInfo => { event.streamManager.stream.getSelectedIceCandidate() From 287fe79debdb67456db0da9cde8f031df55e9cae Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 18:41:24 +0200 Subject: [PATCH 078/435] openvidu-server: parameterized deprecated API support with SUPPORT_DEPRECATED_API --- .../src/main/java/io/openvidu/server/OpenViduServer.java | 2 ++ .../java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java | 3 ++- openvidu-server/src/main/resources/application.properties | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index 1ecda7cb..b1e70c02 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -34,6 +34,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.ConfigurableApplicationContext; @@ -229,6 +230,7 @@ public class OpenViduServer implements JsonRpcConfigurer { @Bean @ConditionalOnMissingBean + @ConditionalOnProperty(name = "SUPPORT_DEPRECATED_API", havingValue = "true") public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); ApiRestPathRewriteFilter apiRestPathRewriteFilter = new ApiRestPathRewriteFilter(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java index f19c2a11..7d33ae9d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java @@ -45,7 +45,8 @@ public class ApiRestPathRewriteFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { - log.info("Initializing API REST path rewrite filter"); + log.warn("Support for deprecated REST API paths enabled. Update your REST API clients to use the new paths"); + log.warn("Deprecated path support will be removed in a future version. You can disable old path support to test compatibility with property SUPPORT_DEPRECATED_API=false"); } @Override diff --git a/openvidu-server/src/main/resources/application.properties b/openvidu-server/src/main/resources/application.properties index 9f9c3c66..d82ef7ee 100644 --- a/openvidu-server/src/main/resources/application.properties +++ b/openvidu-server/src/main/resources/application.properties @@ -8,6 +8,8 @@ server.ssl.key-alias=openvidu-selfsigned logging.level.root=info spring.main.allow-bean-definition-overriding=true +SUPPORT_DEPRECATED_API=true + DOTENV_PATH=. DOMAIN_OR_PUBLIC_IP= From 47e6e58ba23fb417326d2b1672f4ad8a987d3c0e Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 2 Oct 2020 18:48:55 +0200 Subject: [PATCH 079/435] openvidu-server: filter rewrite path warnings updated --- .../io/openvidu/server/rest/ApiRestPathRewriteFilter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java index 7d33ae9d..8d7a9bcf 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java @@ -46,7 +46,8 @@ public class ApiRestPathRewriteFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.warn("Support for deprecated REST API paths enabled. Update your REST API clients to use the new paths"); - log.warn("Deprecated path support will be removed in a future version. You can disable old path support to test compatibility with property SUPPORT_DEPRECATED_API=false"); + log.warn( + "Deprecated path support will be removed in a future release. You can disable old path support to test compatibility with property SUPPORT_DEPRECATED_API=false"); } @Override @@ -76,8 +77,7 @@ public class ApiRestPathRewriteFilter implements Filter { ((HttpServletRequest) request).getRequestURL().toString().replaceFirst(oldBasePath, newBasePath)); String logPathEnding = oldBasePath.endsWith("/") ? "**" : "/**"; - log.warn( - "Path {} is deprecated. Use path {} instead. Deprecated path will be removed in a major release in the future", + log.warn("Path {} is deprecated. Use path {} instead. Deprecated path will be removed in a future release", oldBasePath + logPathEnding, newBasePath + logPathEnding); chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) { From a48778ba919d5d59c4dd7ca45b3b76b84604c9e9 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 2 Oct 2020 19:03:56 +0200 Subject: [PATCH 080/435] Deployment: Minor fix deployment Kibana basic auth --- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 33b369cf..a8bd1e1b 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -105,6 +105,7 @@ services: restart: always environment: - SERVER_BASEPATH="/kibana" + - xpack.security.enabled=true - ELASTICSEARCH_USERNAME=${ELASTICSEARCH_USERNAME} - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD} ports: From 7e75a6568a874e82dfe9e0348d12b6073d13c259 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 3 Oct 2020 14:32:15 +0200 Subject: [PATCH 081/435] openvidu-test-e2e: browser event polling thread reset method --- .../io/openvidu/test/browsers/ChromeUser.java | 5 +++- .../test/e2e/OpenViduEventManager.java | 30 ++++++++++++++++--- .../test/e2e/OpenViduTestAppE2eTest.java | 9 +++--- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java index b6fe64e1..3ffca920 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/ChromeUser.java @@ -51,7 +51,7 @@ public class ChromeUser extends BrowserUser { options.setUnhandledPromptBehaviour(UnexpectedAlertBehaviour.IGNORE); options.addArguments("--disable-infobars"); - options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"}); + options.setExperimentalOption("excludeSwitches", new String[] { "enable-automation" }); Map prefs = new HashMap(); prefs.put("profile.default_content_setting_values.media_stream_mic", 1); @@ -84,6 +84,9 @@ public class ChromeUser extends BrowserUser { // This flag selects the entire screen as video source when screen sharing options.addArguments("--auto-select-desktop-capture-source=Entire screen"); + // Background Chrome + // options.addArguments("--headless"); + if (runningAsRoot) { options.addArguments("--no-sandbox"); } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java index 63d453b4..4105fdab 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java @@ -83,6 +83,7 @@ public class OpenViduEventManager { private Map eventNumbers; private Map eventCountdowns; private AtomicBoolean isInterrupted = new AtomicBoolean(false); + private CountDownLatch pollingLatch = new CountDownLatch(1); private int timeOfWaitInSeconds; public OpenViduEventManager(WebDriver driver, int timeOfWaitInSeconds) { @@ -130,20 +131,21 @@ public class OpenViduEventManager { e.printStackTrace(); } } + log.info("Polling thread is now interrupted!"); + this.pollingLatch.countDown(); }); this.pollingThread.setUncaughtExceptionHandler(h); this.pollingThread.start(); } public void stopPolling(boolean stopThread) { - this.eventCallbacks.clear(); - this.eventCountdowns.clear(); - this.eventNumbers.clear(); - if (stopThread) { this.isInterrupted.set(true); this.pollingThread.interrupt(); } + this.eventCallbacks.clear(); + this.eventCountdowns.clear(); + this.eventNumbers.clear(); } public void on(String eventName, Consumer callback) { @@ -186,6 +188,26 @@ public class OpenViduEventManager { this.setCountDown(eventName, new CountDownLatch(0)); } + public synchronized void clearAllCurrentEvents() { + this.eventNumbers.keySet().forEach(eventName -> { + this.clearCurrentEvents(eventName); + }); + } + + public void resetEventThread() throws InterruptedException { + this.stopPolling(true); + this.pollingLatch.await(); + this.execService.shutdownNow(); + this.execService.awaitTermination(10, TimeUnit.SECONDS); + this.execService = Executors.newCachedThreadPool(); + this.stopPolling(false); + this.clearAllCurrentEvents(); + this.isInterrupted.set(false); + this.pollingLatch = new CountDownLatch(1); + this.eventQueue.clear(); + this.startPolling(); + } + public boolean assertMediaTracks(WebElement videoElement, boolean audioTransmission, boolean videoTransmission, String parentSelector) { return this.assertMediaTracks(Collections.singleton(videoElement), audioTransmission, videoTransmission, diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 3980b7ad..dc47cd32 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -3068,13 +3068,14 @@ public class OpenViduTestAppE2eTest { } Thread.sleep(500); + user.getEventManager().resetEventThread(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).sendKeys(Keys.ENTER); - user.getEventManager().waitUntilEventReaches("connectionCreated", 5); - user.getEventManager().waitUntilEventReaches("accessAllowed", 3); - user.getEventManager().waitUntilEventReaches("streamCreated", 5); - user.getEventManager().waitUntilEventReaches("streamPlaying", 5); + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); // connectionId should be equal to the one brought by the token Assert.assertEquals("Wrong connectionId", tokenBConnectionId, From baa7e37c2c77849f1c75e3ef906f59ba73758a90 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 11:16:36 +0200 Subject: [PATCH 082/435] openvidu-server: record Token option --- .../io/openvidu/server/core/Participant.java | 1 + .../java/io/openvidu/server/core/Session.java | 17 +++++-- .../openvidu/server/core/SessionManager.java | 6 +-- .../java/io/openvidu/server/core/Token.java | 10 ++++- .../openvidu/server/core/TokenGenerator.java | 4 +- .../kurento/core/KurentoParticipant.java | 6 +-- .../server/kurento/core/KurentoSession.java | 2 +- .../recording/service/RecordingManager.java | 3 +- .../service/SingleStreamRecordingService.java | 8 ++-- .../server/rest/SessionRestController.java | 6 ++- ...essionGarbageCollectorIntegrationTest.java | 2 +- .../test/e2e/OpenViduTestAppE2eTest.java | 44 ++++++++++++++++++- .../session-properties-dialog.component.css | 4 ++ .../session-properties-dialog.component.html | 6 ++- .../openvidu-instance.component.ts | 3 +- 15 files changed, 96 insertions(+), 26 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 4c17cebe..092ceb43 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -244,6 +244,7 @@ public class Participant { } json.addProperty("role", this.token.getRole().name()); json.addProperty("serverData", this.serverMetadata); + json.addProperty("record", this.token.record()); json.addProperty("clientData", this.clientMetadata); return json; } 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 ddcd6759..4a3221a2 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 @@ -62,6 +62,7 @@ public class Session implements SessionInterface { protected volatile boolean closed = false; protected AtomicInteger activePublishers = new AtomicInteger(0); + protected AtomicInteger activeIndividualRecordedPublishers = new AtomicInteger(0); /** * This lock protects the following operations with read lock: [REST API](POST @@ -147,12 +148,22 @@ public class Session implements SessionInterface { return activePublishers.get(); } - public void registerPublisher() { - this.activePublishers.incrementAndGet(); + public int getActiveIndividualRecordedPublishers() { + return activeIndividualRecordedPublishers.get(); } - public void deregisterPublisher() { + public void registerPublisher(Participant participant) { + this.activePublishers.incrementAndGet(); + if (participant.getToken().record()) { + activeIndividualRecordedPublishers.incrementAndGet(); + } + } + + public void deregisterPublisher(Participant participant) { this.activePublishers.decrementAndGet(); + if (participant.getToken().record()) { + activeIndividualRecordedPublishers.decrementAndGet(); + } } public void storeToken(Token token) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 1b1bc4d6..6ce7c2c3 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -294,13 +294,13 @@ public abstract class SessionManager { return sessionNotActive; } - public Token newToken(Session session, OpenViduRole role, String serverMetadata, + public Token newToken(Session session, OpenViduRole role, String serverMetadata, boolean record, KurentoTokenOptions kurentoTokenOptions) throws Exception { if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { log.error("Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); } - Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), role, serverMetadata, + Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), role, serverMetadata, record, kurentoTokenOptions); session.storeToken(tokenObj); session.showTokens("Token created"); @@ -308,7 +308,7 @@ public abstract class SessionManager { } public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception { - Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "", + Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "", true, this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null); session.storeToken(tokenObj); session.showTokens("Token created for insecure user"); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 55330548..bffd6a1e 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -28,17 +28,19 @@ public class Token { private String token; private OpenViduRole role; private String serverMetadata = ""; + private boolean record; private TurnCredentials turnCredentials; private KurentoTokenOptions kurentoTokenOptions; private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); - public Token(String token, OpenViduRole role, String serverMetadata, TurnCredentials turnCredentials, - KurentoTokenOptions kurentoTokenOptions) { + public Token(String token, OpenViduRole role, String serverMetadata, boolean record, + TurnCredentials turnCredentials, KurentoTokenOptions kurentoTokenOptions) { this.token = token; this.role = role; this.serverMetadata = serverMetadata; + this.record = record; this.turnCredentials = turnCredentials; this.kurentoTokenOptions = kurentoTokenOptions; } @@ -59,6 +61,10 @@ public class Token { return serverMetadata; } + public boolean record() { + return record; + } + public TurnCredentials getTurnCredentials() { return turnCredentials; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 6320f7bf..540f8e94 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -39,7 +39,7 @@ public class TokenGenerator { @Autowired protected OpenviduBuildInfo openviduBuildConfig; - public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, + public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, boolean record, KurentoTokenOptions kurentoTokenOptions) throws Exception { String token = OpenViduServer.wsUrl; token += "?sessionId=" + sessionId; @@ -56,6 +56,6 @@ public class TokenGenerator { token += "&turnCredential=" + turnCredentials.getCredential(); } } - return new Token(token, role, serverMetadata, turnCredentials, kurentoTokenOptions); + return new Token(token, role, serverMetadata, record, turnCredentials, kurentoTokenOptions); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 0e24020b..493543d2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -181,7 +181,7 @@ public class KurentoParticipant extends Participant { log.info("PARTICIPANT {}: Is now publishing video in room {}", this.getParticipantPublicId(), this.session.getSessionId()); - if (this.openviduConfig.isRecordingModuleEnabled() + if (this.openviduConfig.isRecordingModuleEnabled() && this.token.record() && this.recordingManager.sessionIsBeingRecorded(session.getSessionId())) { this.recordingManager.startOneIndividualStreamRecording(session, this); } @@ -447,7 +447,7 @@ public class KurentoParticipant extends Participant { // Remove streamId from publisher's map this.session.publishedStreamIds.remove(this.getPublisherStreamId()); - if (this.openviduConfig.isRecordingModuleEnabled() + if (this.openviduConfig.isRecordingModuleEnabled() && this.token.record() && this.recordingManager.sessionIsBeingRecorded(session.getSessionId())) { this.recordingManager.stopOneIndividualStreamRecording(session, this.getPublisherStreamId(), kmsDisconnectionTime); @@ -461,7 +461,7 @@ public class KurentoParticipant extends Participant { } releaseElement(getParticipantPublicId(), publisher.getEndpoint()); this.streaming = false; - this.session.deregisterPublisher(); + this.session.deregisterPublisher(this); endpointConfig.getCdr().stopPublisher(this.getParticipantPublicId(), publisher.getStreamId(), reason); publisher = null; diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java index e0ad8cb4..64bd7349 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java @@ -88,7 +88,7 @@ public class KurentoSession extends Session { } public void newPublisher(Participant participant) { - registerPublisher(); + registerPublisher(participant); log.debug("SESSION {}: Virtually subscribed other participants {} to new publisher {}", sessionId, participants.values(), participant.getParticipantPublicId()); } 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 21cfc13e..bd1e77a8 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 @@ -288,8 +288,7 @@ public class RecordingManager { this.sessionHandler.sendRecordingStartedNotification(session, recording); } if (session.getActivePublishers() == 0) { - // Init automatic recording stop if there are now publishers when starting - // recording + // Init automatic recording stop if no publishers when starting the recording log.info("No publisher in session {}. Starting {} seconds countdown for stopping recording", session.getSessionId(), this.openviduConfig.getOpenviduRecordingAutostopTimeout()); this.initAutomaticRecordingStopThread(session); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java index 4cb7e1ab..362599fa 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java @@ -100,11 +100,11 @@ public class SingleStreamRecordingService extends RecordingService { activeRecorders.put(recording.getId(), new ConcurrentHashMap()); storedRecorders.put(recording.getId(), new ConcurrentHashMap()); - final int activePublishers = session.getActivePublishers(); - final CountDownLatch recordingStartedCountdown = new CountDownLatch(activePublishers); + int activePublishersToRecord = session.getActiveIndividualRecordedPublishers(); + final CountDownLatch recordingStartedCountdown = new CountDownLatch(activePublishersToRecord); for (Participant p : session.getParticipants()) { - if (p.isStreaming()) { + if (p.isStreaming() && p.getToken().record()) { MediaProfileSpecType profile = null; try { @@ -299,7 +299,7 @@ public class SingleStreamRecordingService extends RecordingService { if (storedRecorders.get(recordingId).containsKey(streamId)) { log.info("Stream {} recording of recording {} was already stopped", streamId, recordingId); } else { - log.error("Stream {} wasn't being recorded in recording {}", streamId, recordingId); + log.info("Stream {} wasn't being recorded in recording {}", streamId, recordingId); } } globalStopLatch.countDown(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index f2a1a723..7fc8c41a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -335,10 +335,12 @@ public class SessionRestController { String sessionId; String roleString; String metadata; + Boolean record; try { sessionId = (String) params.get("session"); roleString = (String) params.get("role"); metadata = (String) params.get("data"); + record = (Boolean) params.get("record"); } catch (ClassCastException e) { return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST); } @@ -386,11 +388,12 @@ public class SessionRestController { } metadata = (metadata != null) ? metadata : ""; + record = (record != null) ? record : true; // While closing a session tokens can't be generated if (session.closingLock.readLock().tryLock()) { try { - Token token = sessionManager.newToken(session, role, metadata, kurentoTokenOptions); + Token token = sessionManager.newToken(session, role, metadata, record, kurentoTokenOptions); JsonObject responseJson = new JsonObject(); responseJson.addProperty("id", token.getToken()); @@ -398,6 +401,7 @@ public class SessionRestController { responseJson.addProperty("session", sessionId); responseJson.addProperty("role", role.toString()); responseJson.addProperty("data", metadata); + responseJson.addProperty("record", record); responseJson.addProperty("token", token.getToken()); if (kurentoOptions != null) { diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 6b1527c8..5e36c975 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -115,7 +115,7 @@ public class SessionGarbageCollectorIntegrationTest { } private void joinParticipant(String sessionId, String token) { - Token t = new Token(token, OpenViduRole.PUBLISHER, "SERVER_METADATA", null, null); + Token t = new Token(token, OpenViduRole.PUBLISHER, "SERVER_METADATA", true, null, null); String uuid = UUID.randomUUID().toString(); String participantPrivateId = "PARTICIPANT_PRIVATE_ID_" + uuid; String finalUserId = "FINAL_USER_ID_" + uuid; diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index dc47cd32..f90eaa56 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -1583,6 +1583,46 @@ public class OpenViduTestAppE2eTest { gracefullyLeaveParticipants(2); } + @Test + @DisplayName("Individual dynamic record") + void individualDynamicRecordTest() throws Exception { + isRecordingTest = true; + + setupBrowser("chrome"); + + log.info("Individual dynamic record"); + + // Connect 3 users. Two of them not recorded + for (int i = 0; i < 3; i++) { + user.getDriver().findElement(By.id("add-user-btn")).click(); + if (i < 2) { + user.getDriver().findElement(By.id("session-settings-btn-" + i)).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("record-checkbox")).click(); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + } + } + + String sessionName = "TestSession"; + + user.getDriver().findElements(By.className("join-btn")).forEach(el -> el.sendKeys(Keys.ENTER)); + user.getEventManager().waitUntilEventReaches("streamPlaying", 6); + + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", + "{'session':'" + sessionName + "','outputMode':'INDIVIDUAL'}", HttpStatus.SC_OK); + user.getEventManager().waitUntilEventReaches("recordingStarted", 3); + Thread.sleep(2000); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/" + sessionName, HttpStatus.SC_OK); + user.getEventManager().waitUntilEventReaches("recordingStopped", 3); + + String recPath = "/opt/openvidu/recordings/" + sessionName + "/"; + Recording recording = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName); + this.checkIndividualRecording(recPath, recording, 1, "opus", "vp8", true); + + } + @Test @DisplayName("Record cross-browser audio-only and video-only") void audioOnlyVideoOnlyRecordTest() throws Exception { @@ -2814,7 +2854,7 @@ public class OpenViduTestAppE2eTest { // 200 body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': ['GStreamerFilter']}}"; res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, - "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR','kurentoOptions':{'allowedFilters':['STR']}}"); + "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); @@ -2823,7 +2863,7 @@ public class OpenViduTestAppE2eTest { // Default values body = "{'session': 'CUSTOM_SESSION_ID'}"; res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, - "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','token':'STR'}"); + "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR'}"); final String token2 = res.get("id").getAsString(); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css index 5c4c9594..f83aa643 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.css @@ -36,4 +36,8 @@ mat-radio-button:first-child { #role-div { padding-top: 6px; padding-bottom: 15px; +} + +#record-div { + padding-bottom: 20px; } \ No newline at end of file diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index 7ca258ce..b1b02bb5 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -107,6 +107,10 @@ +
+ Record +
+
@@ -120,6 +124,6 @@ + [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, tokenOptions: generateTokenOptions(), customToken: customToken, record: record}">SAVE
diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index eda242a8..5184a4db 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -129,6 +129,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { customToken: string; tokenOptions: TokenOptions = { role: OpenViduRole.PUBLISHER, + record: true, kurentoOptions: { videoMaxRecvBandwidth: 1000, videoMinRecvBandwidth: 300, @@ -684,7 +685,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { return this.OV_NodeClient.createSession(this.sessionProperties) .then(session_NodeClient => { this.sessionAPI = session_NodeClient; - return session_NodeClient.generateToken({ role: this.tokenOptions.role, kurentoOptions: this.tokenOptions.kurentoOptions }); + return session_NodeClient.generateToken(this.tokenOptions); }); } From 0ae577ce6e3aa1e04bdb9d734408336392d05998 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 13:58:13 +0200 Subject: [PATCH 083/435] openvidu-server: refactor kmsDisconnectionTime parameter --- .../kurento/core/KurentoParticipant.java | 8 +-- .../server/kurento/core/KurentoSession.java | 6 +- .../kurento/core/KurentoSessionManager.java | 2 +- .../recording/RecorderEndpointWrapper.java | 63 +++++++++---------- .../service/ComposedRecordingService.java | 6 +- .../recording/service/RecordingManager.java | 9 ++- .../service/SingleStreamRecordingService.java | 31 ++++----- 7 files changed, 56 insertions(+), 69 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 493543d2..9748d353 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -194,7 +194,7 @@ public class KurentoParticipant extends Participant { return sdpResponse; } - public void unpublishMedia(EndReason reason, long kmsDisconnectionTime) { + public void unpublishMedia(EndReason reason, Long kmsDisconnectionTime) { log.info("PARTICIPANT {}: unpublishing media stream from room {}", this.getParticipantPublicId(), this.session.getSessionId()); final MediaOptions mediaOptions = this.getPublisher().getMediaOptions(); @@ -347,7 +347,7 @@ public class KurentoParticipant extends Participant { } } - public void close(EndReason reason, boolean definitelyClosed, long kmsDisconnectionTime) { + public void close(EndReason reason, boolean definitelyClosed, Long kmsDisconnectionTime) { log.debug("PARTICIPANT {}: Closing user", this.getParticipantPublicId()); if (isClosed()) { log.warn("PARTICIPANT {}: Already closed", this.getParticipantPublicId()); @@ -420,7 +420,7 @@ public class KurentoParticipant extends Participant { session.sendMediaError(this.getParticipantPrivateId(), desc); } - private void releasePublisherEndpoint(EndReason reason, long kmsDisconnectionTime) { + private void releasePublisherEndpoint(EndReason reason, Long kmsDisconnectionTime) { if (publisher != null && publisher.getEndpoint() != null) { final ReadWriteLock closingLock = publisher.closingLock; try { @@ -443,7 +443,7 @@ public class KurentoParticipant extends Participant { } } - private void releasePublisherEndpointAux(EndReason reason, long kmsDisconnectionTime) { + private void releasePublisherEndpointAux(EndReason reason, Long kmsDisconnectionTime) { // Remove streamId from publisher's map this.session.publishedStreamIds.remove(this.getPublisherStreamId()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java index 64bd7349..e1771c7f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSession.java @@ -122,7 +122,7 @@ public class KurentoSession extends Session { log.info("PARTICIPANT {}: Leaving session {}", participant.getParticipantPublicId(), this.sessionId); this.removeParticipant(participant, reason); - participant.close(reason, true, 0); + participant.close(reason, true, null); } @Override @@ -133,7 +133,7 @@ public class KurentoSession extends Session { for (Participant participant : participants.values()) { ((KurentoParticipant) participant).releaseAllFilters(); - ((KurentoParticipant) participant).close(reason, true, 0); + ((KurentoParticipant) participant).close(reason, true, null); } participants.clear(); @@ -280,7 +280,7 @@ public class KurentoSession extends Session { return this.publishedStreamIds.get(streamId); } - public void restartStatusInKurento(long kmsDisconnectionTime) { + public void restartStatusInKurento(Long kmsDisconnectionTime) { log.info("Resetting process: resetting remote media objects for active session {}", this.sessionId); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 222729d4..d689cd81 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -495,7 +495,7 @@ public class KurentoSessionManager extends SessionManager { throw new OpenViduException(Code.USER_NOT_STREAMING_ERROR_CODE, "Participant '" + participant.getParticipantPublicId() + "' is not streaming media"); } - kParticipant.unpublishMedia(reason, 0); + kParticipant.unpublishMedia(reason, null); session.cancelPublisher(participant, reason); Set participants = session.getParticipants(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index 51577e2c..55a123f6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -21,41 +21,34 @@ import org.kurento.client.RecorderEndpoint; import com.google.gson.JsonObject; +import io.openvidu.server.kurento.core.KurentoParticipant; + public class RecorderEndpointWrapper { private RecorderEndpoint recorder; - private String connectionId; + private KurentoParticipant kParticipant; private String recordingId; - private String streamId; - private String clientData; - private String serverData; - private boolean hasAudio; - private boolean hasVideo; - private String typeOfVideo; private long startTime; private long endTime; private long size; - public RecorderEndpointWrapper(RecorderEndpoint recorder, String connectionId, String recordingId, String streamId, - String clientData, String serverData, boolean hasAudio, boolean hasVideo, String typeOfVideo) { + public RecorderEndpointWrapper(RecorderEndpoint recorder, KurentoParticipant kParticipant, String recordingId) { this.recorder = recorder; - this.connectionId = connectionId; + this.kParticipant = kParticipant; this.recordingId = recordingId; - this.streamId = streamId; - this.clientData = clientData; - this.serverData = serverData; - this.hasAudio = hasAudio; - this.hasVideo = hasVideo; - this.typeOfVideo = typeOfVideo; } public RecorderEndpoint getRecorder() { return recorder; } + + public KurentoParticipant getParticipant() { + return this.kParticipant; + } public String getConnectionId() { - return connectionId; + return kParticipant.getParticipantPublicId(); } public String getRecordingId() { @@ -63,15 +56,15 @@ public class RecorderEndpointWrapper { } public String getStreamId() { - return streamId; + return kParticipant.getPublisherStreamId(); } public String getClientData() { - return clientData; + return kParticipant.getClientMetadata(); } public String getServerData() { - return serverData; + return kParticipant.getServerMetadata(); } public long getStartTime() { @@ -99,31 +92,31 @@ public class RecorderEndpointWrapper { } public boolean hasAudio() { - return hasAudio; + return kParticipant.getPublisher().getMediaOptions().hasAudio(); } public boolean hasVideo() { - return hasVideo; + return kParticipant.getPublisher().getMediaOptions().hasVideo(); } public String getTypeOfVideo() { - return typeOfVideo; + return kParticipant.getPublisher().getMediaOptions().getTypeOfVideo(); } public JsonObject toJson() { JsonObject json = new JsonObject(); - json.addProperty("connectionId", this.connectionId); - json.addProperty("streamId", this.streamId); - json.addProperty("clientData", this.clientData); - json.addProperty("serverData", this.serverData); - json.addProperty("startTime", this.startTime); - json.addProperty("endTime", this.endTime); - json.addProperty("duration", this.endTime - this.startTime); - json.addProperty("size", this.size); - json.addProperty("hasAudio", this.hasAudio); - json.addProperty("hasVideo", this.hasVideo); - if (this.hasVideo) { - json.addProperty("typeOfVideo", this.typeOfVideo); + json.addProperty("connectionId", this.getConnectionId()); + json.addProperty("streamId", this.getStreamId()); + json.addProperty("clientData", this.getClientData()); + json.addProperty("serverData", this.getServerData()); + json.addProperty("startTime", this.getStartTime()); + json.addProperty("endTime", this.getEndTime()); + json.addProperty("duration", this.getEndTime() - this.getStartTime()); + json.addProperty("size", this.getSize()); + json.addProperty("hasAudio", this.hasAudio()); + json.addProperty("hasVideo", this.hasVideo()); + if (this.hasVideo()) { + json.addProperty("typeOfVideo", this.getTypeOfVideo()); } return json; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java index d767f827..9ecb3062 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/ComposedRecordingService.java @@ -109,11 +109,11 @@ public class ComposedRecordingService extends RecordingService { if (recording.hasVideo()) { return this.stopRecordingWithVideo(session, recording, reason); } else { - return this.stopRecordingAudioOnly(session, recording, reason, 0); + return this.stopRecordingAudioOnly(session, recording, reason, null); } } - public Recording stopRecording(Session session, Recording recording, EndReason reason, long kmsDisconnectionTime) { + public Recording stopRecording(Session session, Recording recording, EndReason reason, Long kmsDisconnectionTime) { if (recording.hasVideo()) { return this.stopRecordingWithVideo(session, recording, reason); } else { @@ -322,7 +322,7 @@ public class ComposedRecordingService extends RecordingService { } private Recording stopRecordingAudioOnly(Session session, Recording recording, EndReason reason, - long kmsDisconnectionTime) { + Long kmsDisconnectionTime) { log.info("Stopping composed (audio-only) recording {} of session {}. Reason: {}", recording.getId(), recording.getSessionId(), reason); 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 bd1e77a8..f4a09720 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 @@ -67,7 +67,6 @@ import io.openvidu.server.core.Participant; import io.openvidu.server.core.Session; import io.openvidu.server.core.SessionEventsHandler; import io.openvidu.server.core.SessionManager; -import io.openvidu.server.kurento.core.KurentoSession; import io.openvidu.server.kurento.kms.Kms; import io.openvidu.server.kurento.kms.KmsManager; import io.openvidu.server.recording.Recording; @@ -351,7 +350,7 @@ public class RecordingManager { return recording; } - public Recording forceStopRecording(Session session, EndReason reason, long kmsDisconnectionTime) { + public Recording forceStopRecording(Session session, EndReason reason, Long kmsDisconnectionTime) { Recording recording; recording = this.sessionsRecordings.get(session.getSessionId()); switch (recording.getOutputMode()) { @@ -409,8 +408,8 @@ public class RecordingManager { return; } - this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(session, recording.getId(), - profile, participant, startedCountDown); + this.singleStreamRecordingService.startRecorderEndpointForPublisherEndpoint(recording.getId(), profile, + participant, startedCountDown); } else if (RecordingUtils.IS_COMPOSED(recording.getOutputMode()) && !recording.hasVideo()) { // Connect this stream to existing Composite recorder log.info("Joining PublisherEndpoint to existing Composite in session {} for new stream of participant {}", @@ -419,7 +418,7 @@ public class RecordingManager { } } - public void stopOneIndividualStreamRecording(KurentoSession session, String streamId, long kmsDisconnectionTime) { + public void stopOneIndividualStreamRecording(Session session, String streamId, Long kmsDisconnectionTime) { Recording recording = this.sessionsRecordings.get(session.getSessionId()); if (recording == null) { recording = this.sessionsRecordingsStarting.get(session.getSessionId()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java index 362599fa..e49a054a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java @@ -116,7 +116,7 @@ public class SingleStreamRecordingService extends RecordingService { recordingStartedCountdown.countDown(); continue; } - this.startRecorderEndpointForPublisherEndpoint(session, recording.getId(), profile, p, + this.startRecorderEndpointForPublisherEndpoint(recording.getId(), profile, p, recordingStartedCountdown); } } @@ -141,10 +141,10 @@ public class SingleStreamRecordingService extends RecordingService { @Override public Recording stopRecording(Session session, Recording recording, EndReason reason) { - return this.stopRecording(session, recording, reason, 0); + return this.stopRecording(session, recording, reason, null); } - public Recording stopRecording(Session session, Recording recording, EndReason reason, long kmsDisconnectionTime) { + public Recording stopRecording(Session session, Recording recording, EndReason reason, Long kmsDisconnectionTime) { log.info("Stopping individual ({}) recording {} of session {}. Reason: {}", recording.hasVideo() ? (recording.hasAudio() ? "video+audio" : "video-only") : "audioOnly", recording.getId(), recording.getSessionId(), reason); @@ -205,18 +205,18 @@ public class SingleStreamRecordingService extends RecordingService { return finalRecordingArray[0]; } - public void startRecorderEndpointForPublisherEndpoint(final Session session, final String recordingId, - MediaProfileSpecType profile, final Participant participant, CountDownLatch globalStartLatch) { + public void startRecorderEndpointForPublisherEndpoint(final String recordingId, MediaProfileSpecType profile, + final Participant participant, CountDownLatch globalStartLatch) { log.info("Starting single stream recorder for stream {} in session {}", participant.getPublisherStreamId(), - session.getSessionId()); + participant.getSessionId()); try { if (participant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) { try { if (this.activeRecorders.get(recordingId).containsKey(participant.getPublisherStreamId())) { log.warn("Concurrent initialization of RecorderEndpoint for stream {} of session {}. Returning", - participant.getPublisherStreamId(), session.getSessionId()); + participant.getPublisherStreamId(), participant.getSessionId()); return; } @@ -244,13 +244,8 @@ public class SingleStreamRecordingService extends RecordingService { } }); - RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder, - participant.getParticipantPublicId(), recordingId, participant.getPublisherStreamId(), - participant.getClientMetadata(), participant.getServerMetadata(), - kurentoParticipant.getPublisher().getMediaOptions().hasAudio(), - kurentoParticipant.getPublisher().getMediaOptions().hasVideo(), - kurentoParticipant.getPublisher().getMediaOptions().getTypeOfVideo()); - + RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder, kurentoParticipant, + recordingId); activeRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper); storedRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper); @@ -262,13 +257,13 @@ public class SingleStreamRecordingService extends RecordingService { } } else { log.error( - "Timeout waiting for individual recording lock to be available for participant {} of session {}", - participant.getParticipantPublicId(), session.getSessionId()); + "Timeout waiting for individual recording lock to be available to start stream recording for participant {} of session {}", + participant.getParticipantPublicId(), participant.getSessionId()); } } catch (InterruptedException e) { log.error( - "InterruptedException waiting for individual recording lock to be available for participant {} of session {}", - participant.getParticipantPublicId(), session.getSessionId()); + "InterruptedException waiting for individual recording lock to be available to start stream recording for participant {} of session {}", + participant.getParticipantPublicId(), participant.getSessionId()); } } From d493112f1259a7059d3b74ed83fe8b061dabe9f0 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 13:59:22 +0200 Subject: [PATCH 084/435] openvidu-node-client: TokenOptions.record --- openvidu-node-client/src/Session.ts | 8 ++++---- openvidu-node-client/src/TokenOptions.ts | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index a9fead7b..09cde2ee 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -102,11 +102,11 @@ export class Session { const data = JSON.stringify({ session: this.sessionId, - role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : OpenViduRole.PUBLISHER, - data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : '', - kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : {}, + role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null, + data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : null, + record: !!tokenOptions ? tokenOptions.record : null, + kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : null }); - axios.post( this.ov.host + OpenVidu.API_TOKENS, data, diff --git a/openvidu-node-client/src/TokenOptions.ts b/openvidu-node-client/src/TokenOptions.ts index 910cd657..51fa4d0d 100644 --- a/openvidu-node-client/src/TokenOptions.ts +++ b/openvidu-node-client/src/TokenOptions.ts @@ -22,6 +22,13 @@ import { OpenViduRole } from './OpenViduRole'; */ export interface TokenOptions { + /** + * The role assigned to this token + * + * @default PUBLISHER + */ + role?: OpenViduRole; + /** * Secure (server-side) data associated to this token. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object. * - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[TokenOptions.data]] property. @@ -31,9 +38,12 @@ export interface TokenOptions { data?: string; /** - * The role assigned to this token + * Whether to record the streams published by the participant owning this token or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) + * + * @default true */ - role?: OpenViduRole; + record?: boolean; + /** * **WARNING**: experimental option. This interface may change in the near future From 412c169b1b034a5ce5b04241cffee445ada1699f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 14:12:00 +0200 Subject: [PATCH 085/435] openvidu-testapp: fix SessionPropertiesDialogComponent --- .../session-properties-dialog.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index b1b02bb5..b0d1b333 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -124,6 +124,6 @@ + [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, tokenOptions: generateTokenOptions(), customToken: customToken}">SAVE From c31f80c2c72918207a606e305278f72e12dd2543 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 18:43:42 +0200 Subject: [PATCH 086/435] openvidu-server: prepare SessionRestController to be inheritable --- .../io/openvidu/server/rest/SessionRestController.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 7fc8c41a..7cc2bac3 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -28,6 +28,7 @@ import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; @@ -73,19 +74,20 @@ import io.openvidu.server.utils.RestUtils; */ @RestController @CrossOrigin +@ConditionalOnMissingBean(name = "sessionRestControllerPro") @RequestMapping(RequestMappings.API) public class SessionRestController { private static final Logger log = LoggerFactory.getLogger(SessionRestController.class); @Autowired - private SessionManager sessionManager; + protected SessionManager sessionManager; @Autowired - private RecordingManager recordingManager; + protected RecordingManager recordingManager; @Autowired - private OpenviduConfig openviduConfig; + protected OpenviduConfig openviduConfig; @RequestMapping(value = "/sessions", method = RequestMethod.POST) public ResponseEntity getSessionId(@RequestBody(required = false) Map params) { @@ -849,7 +851,7 @@ public class SessionRestController { } } - private ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { + protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { JsonObject responseJson = new JsonObject(); responseJson.addProperty("timestamp", System.currentTimeMillis()); responseJson.addProperty("status", status.value()); From cf6c71a71c130e9c74d1db9dd3c5253e058b2d4c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 18:46:38 +0200 Subject: [PATCH 087/435] openvidu-server: rollback RecorderEndpointWrapper --- .../recording/RecorderEndpointWrapper.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index 55a123f6..83393369 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -27,7 +27,14 @@ public class RecorderEndpointWrapper { private RecorderEndpoint recorder; private KurentoParticipant kParticipant; + private String connectionId; private String recordingId; + private String streamId; + private String clientData; + private String serverData; + private boolean hasAudio; + private boolean hasVideo; + private String typeOfVideo; private long startTime; private long endTime; @@ -37,18 +44,25 @@ public class RecorderEndpointWrapper { this.recorder = recorder; this.kParticipant = kParticipant; this.recordingId = recordingId; + this.connectionId = kParticipant.getParticipantPublicId(); + this.streamId = kParticipant.getPublisherStreamId(); + this.clientData = kParticipant.getClientMetadata(); + this.serverData = kParticipant.getServerMetadata(); + this.hasAudio = kParticipant.getPublisher().getMediaOptions().hasAudio(); + this.hasVideo = kParticipant.getPublisher().getMediaOptions().hasVideo(); + this.typeOfVideo = kParticipant.getPublisher().getMediaOptions().getTypeOfVideo(); } public RecorderEndpoint getRecorder() { return recorder; } - + public KurentoParticipant getParticipant() { return this.kParticipant; } public String getConnectionId() { - return kParticipant.getParticipantPublicId(); + return connectionId; } public String getRecordingId() { @@ -56,15 +70,15 @@ public class RecorderEndpointWrapper { } public String getStreamId() { - return kParticipant.getPublisherStreamId(); + return streamId; } public String getClientData() { - return kParticipant.getClientMetadata(); + return clientData; } public String getServerData() { - return kParticipant.getServerMetadata(); + return serverData; } public long getStartTime() { @@ -92,15 +106,15 @@ public class RecorderEndpointWrapper { } public boolean hasAudio() { - return kParticipant.getPublisher().getMediaOptions().hasAudio(); + return hasAudio; } public boolean hasVideo() { - return kParticipant.getPublisher().getMediaOptions().hasVideo(); + return hasVideo; } public String getTypeOfVideo() { - return kParticipant.getPublisher().getMediaOptions().getTypeOfVideo(); + return typeOfVideo; } public JsonObject toJson() { From 4b2c50c8f20e725be2f0872345d18cbe648f2b53 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 18:52:19 +0200 Subject: [PATCH 088/435] openvidu-server: remove unused method Participant#setToken --- .../src/main/java/io/openvidu/server/core/Participant.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 092ceb43..b8906a5c 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -122,10 +122,6 @@ public class Participant { return this.token; } - public void setToken(Token token) { - this.token = token; - } - public GeoLocation getLocation() { return this.location; } From ca915fa321afb72ec7adbdac7a417295799b8f5f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 5 Oct 2020 19:04:12 +0200 Subject: [PATCH 089/435] openvidu-server: Token and Session getters and setters update --- .../src/main/java/io/openvidu/server/core/Session.java | 4 ++++ .../src/main/java/io/openvidu/server/core/Token.java | 8 ++++++++ 2 files changed, 12 insertions(+) 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 4a3221a2..6feb9736 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 @@ -192,6 +192,10 @@ public class Session implements SessionInterface { return tokenObj; } + public Iterator> getTokenIterator() { + return this.tokens.entrySet().iterator(); + } + public void showTokens(String preMessage) { log.info("{} { Session: {} | Tokens: {} }", preMessage, this.sessionId, this.tokens.keySet().toString()); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index bffd6a1e..d5ed9ca6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -77,6 +77,14 @@ public class Token { return connectionId; } + public void setRole(OpenViduRole role) { + this.role = role; + } + + public void setRecord(boolean record) { + this.record = record; + } + @Override public String toString() { if (this.role != null) From 087a2a0d06e0a2822309460941dd4c4ecd6fed8e Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 6 Oct 2020 00:40:01 +0200 Subject: [PATCH 090/435] deployment-openvidu-pro: Minor fix configuring different openvidu pro clusters with the same Elastic Stack --- .../pro/docker-compose/media-node/beats/filebeat.yml | 1 + .../media-node/beats/metricbeat-elasticsearch.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/.env | 7 ++++++- .../docker-compose/openvidu-server-pro/beats/filebeat.yml | 3 +++ .../docker-compose/openvidu-server-pro/docker-compose.yml | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml index c09e980b..5a2f4f59 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml @@ -19,6 +19,7 @@ processors: - add_fields: fields: ip: ${MEDIA_NODE_IP} + cluster-id: ${CLUSTER_ID} output: elasticsearch: diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml index d30028c1..0c9b773c 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/metricbeat-elasticsearch.yml @@ -5,7 +5,7 @@ metricbeat.modules: period: ${OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL}s processes: ['.*'] cpu.metrics: [normalized_percentages] -fields: {ip: "${MEDIA_NODE_IP}"} +fields: {ip: "${MEDIA_NODE_IP}", cluster-id: "${CLUSTER_ID}"} pipeline: queue.mem.events: 0 setup.ilm.enabled: false \ No newline at end of file diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 7e59b016..2799c02a 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -71,6 +71,12 @@ OPENVIDU_PRO_CLUSTER_MODE=manual # Possibles values: aws, on_premise OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise +# Unique identifier of your cluster. Each OpenVidu Server Pro instance corresponds to one cluster. +# You can launch as many clusters as you want with your license key. +# Cluster ID will always be stored to disk so restarting OpenVidu Server Pro will keep the same previous cluster ID +# if this configuration parameter is not given a distinct value. +# OPENVIDU_PRO_CLUSTER_ID= + # The desired number of Media Nodes on startup. First the autodiscovery process is performed. # If there are too many Media Nodes after that, they will be dropped until this number is reached. # If there are not enough, more will be launched. @@ -85,7 +91,6 @@ OPENVIDU_PRO_CLUSTER_ENVIRONMENT=on_premise # Type: number >= 0 # OPENVIDU_PRO_CLUSTER_LOAD_INTERVAL= - # Whether to enable or disable autoscaling. With autoscaling the number of Media Nodes will # be automatically adjusted according to existing load # Values: true | false diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml index 42fc9710..24297f04 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml @@ -13,6 +13,9 @@ processors: fields: ["message"] target: "json" overwrite_keys: true + - add_fields: + fields: + cluster-id: ${OPENVIDU_PRO_CLUSTER_ID:undefined} output: elasticsearch: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index a8bd1e1b..c0d4a03b 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -116,6 +116,8 @@ services: network_mode: host restart: always user: root + env_file: + - .env environment: - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} volumes: From ffd1f7f5b7b4f028035f5540f2999c3d30874f9b Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 6 Oct 2020 21:13:18 +0200 Subject: [PATCH 091/435] deployment-openvidu-pro: S3 support --- ...penvidu-server-pro-no-market.yaml.template | 99 ++++++++++++++++++- .../docker-compose/openvidu-server-pro/.env | 28 ++++++ 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 25489e9d..c5b98e37 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -41,6 +41,18 @@ Parameters: LetsEncryptEmail: Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications" Type: String + + RecordingStorage: + Description: "If 's3', recordings will be stored in a S3 bucket" + Type: String + AllowedValues: + - local + - s3 + Default: local + + S3RecordingsBucketName: + Description: "If RecordingStorage is 's3', this will be the name of s3 bucket to store recordings" + Type: String # OpenVidu Configuration @@ -212,6 +224,8 @@ Metadata: - OpenViduLicense - OpenViduSecret - MediaNodesStartNumber + - RecordingStorage + - S3RecordingsBucketName - Label: default: Elasticsearch and Kibana configuration Parameters: @@ -247,6 +261,10 @@ Metadata: default: "URL to the key file (owncert)" LetsEncryptEmail: default: "Email for Let's Encrypt (letsencrypt)" + RecordingStorage: + default: "Recording storage" + S3RecordingsBucketName: + default: "S3 Bucket where recordings will be stored" # OpenVidu configuration OpenViduLicense: default: "OpenVidu Pro License key" @@ -276,8 +294,20 @@ Metadata: default: "Deploy OpenVidu Call application" Conditions: - WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ""] ] - PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ] + WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ""] ] + PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ] + RecordingStorageIsS3: !Equals [!Ref RecordingStorage, "s3" ] + S3RecordingsBucketNamePresent: !Not [ !Equals [!Ref S3RecordingsBucketName, ""] ] + CreateS3Bucket: !And [ !Equals [!Ref RecordingStorage, "s3" ], !Equals [!Ref S3RecordingsBucketName, ""] ] + +Rules: + ValidateParametersS3Local: + RuleCondition: + Fn::Equals: [!Ref RecordingStorage, "local" ] + Assertions: + - AssertDescription: If Recording Storage is 'local', you don't need to define an S3 bucket + Assert: + Fn::Equals: [!Ref S3RecordingsBucketName, ""] Resources: @@ -312,6 +342,42 @@ Resources: - 'route53:ChangeResourceRecordSets' - 'route53:ListHostedZones' Resource: '*' + - Fn::If: + # Only apply this policies if S3 is configured + - RecordingStorageIsS3 + - Effect: Allow + Action: + - 's3:DeleteObject' + - 's3:GetObject' + - 's3:PutObject' + Resource: + - Fn::If: + # Get bucket name depending if the user defines a bucket name or not + - S3RecordingsBucketNamePresent + - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName, '/*'] ] + - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings', '/*'] ] + - Ref: AWS::NoValue + - Fn::If: + # Only apply this policies if S3 is configured + - RecordingStorageIsS3 + - Effect: Allow + Action: + - 's3:ListBucket' + Resource: + - Fn::If: + # Get bucket name depending if the user defines a bucket name or not + - S3RecordingsBucketNamePresent + - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName ] ] + - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings' ] ] + - Ref: AWS::NoValue + - Fn::If: + # Only apply this policies if S3 is configured + - RecordingStorageIsS3 + - Effect: Allow + Action: + - s3:ListAllMyBuckets + Resource: 'arn:aws:s3:::' + - Ref: AWS::NoValue RoleName: !Join [ "-", [ OpenViduManageEC2Role, !Ref 'AWS::StackName', !Ref 'AWS::Region'] ] OpenviduInstancesProfile: @@ -324,6 +390,20 @@ Resources: DependsOn: - OpenViduManageEC2Role + S3bucket: + Type: 'AWS::S3::Bucket' + Properties: + BucketName: !Join [ "", [ !Ref 'AWS::StackName', '-recordings' ] ] + AccessControl: Private + PublicAccessBlockConfiguration: + BlockPublicAcls: true + BlockPublicPolicy: true + IgnorePublicAcls : true + RestrictPublicBuckets: true + DeletionPolicy: Retain + UpdateReplacePolicy: Retain + Condition: CreateS3Bucket + OpenViduServer: Type: AWS::EC2::Instance Metadata: @@ -404,7 +484,18 @@ Resources: sed -i "s/WITH_APP=true/WITH_APP=false/" $WORKINGDIR/docker-compose.yml rm $WORKINGDIR/docker-compose.override.yml fi + + # S3 Configuration + if [ "${RecordingStorage}" == "s3" ]; then + sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=s3" $WORKINGDIR/.env + if [ ! -z "${S3RecordingsBucketName}" ]; then + sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}" $WORKINGDIR/.env + else + sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${s3BucketName}" $WORKINGDIR/.env + fi + fi - kmsAmi: !FindInMap [KMSAMIMAP, !Ref 'AWS::Region', AMI] + s3BucketName: !Join [ "", [ !Ref 'AWS::StackName', '-recordings' ] ] mode: "000755" owner: "root" group: "root" @@ -453,7 +544,7 @@ Resources: owner: "root" group: "root" '/usr/local/bin/create_security_group_rules.sh': - content: !Sub | + content: | #!/bin/bash -x SECGRPIDKMS=$(/usr/local/bin/getSecurityGroupKms.sh) SECGRPIDOV=$(/usr/local/bin/getSecurityGroupOpenVidu.sh) @@ -471,7 +562,7 @@ Resources: owner: "root" group: "root" '/usr/local/bin/restartPRO.sh': - content: !Sub | + content: | #!/bin/bash -x WORKINGDIR=/opt/openvidu diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 2799c02a..3cb782ae 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -138,6 +138,34 @@ OPENVIDU_RECORDING=false # Use recording module with debug mode. OPENVIDU_RECORDING_DEBUG=false +# Where to store recording files. Can be “local” (local storage) or “s3” (AWS bucket). +# You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it. +#OPENVIDU_PRO_RECORDING_STORAGE= + +# S3 Bucket where to store recording files. May include paths to allow navigating +# folder structures inside the bucket. This property is only taken into account +# if OPENVIDU_PRO_RECORDING_STORAGE=s3 +#OPENVIDU_PRO_AWS_S3_BUCKET= + +# AWS credentials access key. Must have read and write permissions over the bucket. +# If not provided, then the internal S3 client will try to use the default AWS credentials +# of the machine (if available). This property is only taken into account if +# OPENVIDU_PRO_RECORDING_STORAGE=s3 +# If you're instance has a role which has access to read +# and write into the s3 bucket, you don't need this parameter +# OPENVIDU_PRO_AWS_ACCESS_KEY= + +# AWS credentials secret key from OPENVIDU_PRO_AWS_ACCESS_KEY. This property is only +# taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3 +# If you're instance has a role which has access to read +# and write into the s3 bucket, you don't need this parameter +# OPENVIDU_PRO_AWS_SECRET_KEY= + +# AWS region in which the S3 bucket is located (e.g. eu-west-1). If not provided, +# the region will try to be discovered automatically, although this is not always possible. +# This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3 +# OPENVIDU_PRO_AWS_REGION= + # Openvidu Folder Record used for save the openvidu recording videos. Change it # with the folder you want to use from your host. OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings From 8102784df324335a2f2d66feb96705ed5e3c12ed Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 6 Oct 2020 22:20:52 +0200 Subject: [PATCH 092/435] deployment-openvidu-pro: Minor fix UserData script replacing s3 variables --- .../cfn-openvidu-server-pro-no-market.yaml.template | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index c5b98e37..f62256b5 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -343,7 +343,7 @@ Resources: - 'route53:ListHostedZones' Resource: '*' - Fn::If: - # Only apply this policies if S3 is configured + # Only apply this policy if S3 is configured - RecordingStorageIsS3 - Effect: Allow Action: @@ -358,7 +358,7 @@ Resources: - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings', '/*'] ] - Ref: AWS::NoValue - Fn::If: - # Only apply this policies if S3 is configured + # Only apply this policy if S3 is configured - RecordingStorageIsS3 - Effect: Allow Action: @@ -371,7 +371,7 @@ Resources: - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings' ] ] - Ref: AWS::NoValue - Fn::If: - # Only apply this policies if S3 is configured + # Only apply this policy if S3 is configured - RecordingStorageIsS3 - Effect: Allow Action: @@ -487,11 +487,11 @@ Resources: # S3 Configuration if [ "${RecordingStorage}" == "s3" ]; then - sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=s3" $WORKINGDIR/.env + sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=s3/" $WORKINGDIR/.env if [ ! -z "${S3RecordingsBucketName}" ]; then - sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}" $WORKINGDIR/.env + sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}/" $WORKINGDIR/.env else - sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${s3BucketName}" $WORKINGDIR/.env + sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${s3BucketName}/" $WORKINGDIR/.env fi fi - kmsAmi: !FindInMap [KMSAMIMAP, !Ref 'AWS::Region', AMI] From 2e919b69e689f930808a61917b0ff124d27df2e1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 12:09:26 +0200 Subject: [PATCH 093/435] openvidu-server: SingleStreamRecordingService refactoring for dynamic records --- .../kurento/core/KurentoParticipant.java | 12 +- .../recording/DummyRecordingDownloader.java | 2 +- .../recording/RecorderEndpointWrapper.java | 34 ++++- .../server/recording/RecordingDownloader.java | 2 +- .../recording/service/RecordingManager.java | 2 +- .../service/SingleStreamRecordingService.java | 134 ++++++++++++------ 6 files changed, 136 insertions(+), 50 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 9748d353..560d8808 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -88,11 +88,15 @@ public class KurentoParticipant extends Participant { if (!OpenViduRole.SUBSCRIBER.equals(participant.getToken().getRole())) { // Initialize a PublisherEndpoint - this.publisher = new PublisherEndpoint(endpointType, this, participant.getParticipantPublicId(), - this.session.getPipeline(), this.openviduConfig, null); + initPublisherEndpoint(); } } + public void initPublisherEndpoint() { + this.publisher = new PublisherEndpoint(endpointType, this, this.participantPublicId, this.session.getPipeline(), + this.openviduConfig, null); + } + public void createPublishingEndpoint(MediaOptions mediaOptions, String streamId) { String type = mediaOptions.hasVideo() ? mediaOptions.getTypeOfVideo() : "MICRO"; if (streamId == null) { @@ -136,6 +140,10 @@ public class KurentoParticipant extends Participant { } } + public boolean isPublisherEndpointDefined() { + return this.publisher != null; + } + public PublisherEndpoint getPublisher() { try { if (!publisherLatch.await(KurentoSession.ASYNC_LATCH_TIMEOUT, TimeUnit.SECONDS)) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingDownloader.java b/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingDownloader.java index d62cb0ee..20ddbd0a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingDownloader.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/DummyRecordingDownloader.java @@ -23,7 +23,7 @@ import java.util.Collection; public class DummyRecordingDownloader implements RecordingDownloader { @Override - public void downloadRecording(Recording recording, Collection streamIds, Runnable callback) + public void downloadRecording(Recording recording, Collection wrappers, Runnable callback) throws IOException { // Just immediately run callback function callback.run(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index 83393369..655ba4a9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -17,16 +17,19 @@ package io.openvidu.server.recording; +import org.apache.commons.lang3.StringUtils; import org.kurento.client.RecorderEndpoint; import com.google.gson.JsonObject; import io.openvidu.server.kurento.core.KurentoParticipant; +import io.openvidu.server.recording.service.SingleStreamRecordingService; public class RecorderEndpointWrapper { private RecorderEndpoint recorder; private KurentoParticipant kParticipant; + private String name; private String connectionId; private String recordingId; private String streamId; @@ -40,7 +43,9 @@ public class RecorderEndpointWrapper { private long endTime; private long size; - public RecorderEndpointWrapper(RecorderEndpoint recorder, KurentoParticipant kParticipant, String recordingId) { + public RecorderEndpointWrapper(RecorderEndpoint recorder, KurentoParticipant kParticipant, String recordingId, + String name) { + this.name = name; this.recorder = recorder; this.kParticipant = kParticipant; this.recordingId = recordingId; @@ -53,6 +58,24 @@ public class RecorderEndpointWrapper { this.typeOfVideo = kParticipant.getPublisher().getMediaOptions().getTypeOfVideo(); } + public RecorderEndpointWrapper(JsonObject json) { + String nameAux = json.get("name").getAsString(); + // If the name includes the extension, remove it + this.name = StringUtils.removeEnd(nameAux, SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION); + this.connectionId = json.get("connectionId").getAsString(); + this.streamId = json.get("streamId").getAsString(); + this.clientData = json.get("clientData").getAsString(); + this.serverData = json.get("serverData").getAsString(); + this.startTime = json.get("startTime").getAsLong(); + this.endTime = json.get("endTime").getAsLong(); + this.size = json.get("size").getAsLong(); + this.hasAudio = json.get("hasAudio").getAsBoolean(); + this.hasVideo = json.get("hasVideo").getAsBoolean(); + if (this.hasVideo) { + this.typeOfVideo = json.get("typeOfVideo").getAsString(); + } + } + public RecorderEndpoint getRecorder() { return recorder; } @@ -61,6 +84,14 @@ public class RecorderEndpointWrapper { return this.kParticipant; } + public String getName() { + return this.name; + } + + public String getNameWithExtension() { + return this.name + SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION; + } + public String getConnectionId() { return connectionId; } @@ -119,6 +150,7 @@ public class RecorderEndpointWrapper { public JsonObject toJson() { JsonObject json = new JsonObject(); + json.addProperty("name", this.getNameWithExtension()); json.addProperty("connectionId", this.getConnectionId()); json.addProperty("streamId", this.getStreamId()); json.addProperty("clientData", this.getClientData()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingDownloader.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingDownloader.java index 65c750b5..71d392c5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingDownloader.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingDownloader.java @@ -22,7 +22,7 @@ import java.util.Collection; public interface RecordingDownloader { - public void downloadRecording(Recording recording, Collection streamIds, Runnable callback) + public void downloadRecording(Recording recording, Collection wrappers, Runnable callback) throws IOException; public void cancelDownload(String recordingId); 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 f4a09720..a7127cf4 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 @@ -726,7 +726,7 @@ public class RecordingManager { } final String testFolderPath = openviduRecordingPath + "/TEST_RECORDING_PATH_" + System.currentTimeMillis(); - final String testFilePath = testFolderPath + "/TEST_RECORDING_PATH.webm"; + final String testFilePath = testFolderPath + "/TEST_RECORDING_PATH" + SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION; // Check Kurento Media Server write permissions in recording path if (this.kmsManager.getKmss().isEmpty()) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java index e49a054a..b395dc70 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/service/SingleStreamRecordingService.java @@ -24,7 +24,9 @@ import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.Reader; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; @@ -49,6 +51,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; @@ -71,10 +74,13 @@ public class SingleStreamRecordingService extends RecordingService { private static final Logger log = LoggerFactory.getLogger(SingleStreamRecordingService.class); + // One recorder endpoint active at a time per stream private Map> activeRecorders = new ConcurrentHashMap<>(); - private Map> storedRecorders = new ConcurrentHashMap<>(); + // Multiple recorder endpoints per stream during a recording + private Map>> storedRecorders = new ConcurrentHashMap<>(); private final String INDIVIDUAL_STREAM_METADATA_FILE = ".stream."; + public static final String INDIVIDUAL_RECORDING_EXTENSION = ".webm"; public SingleStreamRecordingService(RecordingManager recordingManager, RecordingDownloader recordingDownloader, RecordingUploader recordingUploader, OpenviduConfig openviduConfig, CallDetailRecord cdr, @@ -97,8 +103,8 @@ public class SingleStreamRecordingService extends RecordingService { Recording recording = new Recording(session.getSessionId(), recordingId, properties); this.recordingManager.recordingToStarting(recording); - activeRecorders.put(recording.getId(), new ConcurrentHashMap()); - storedRecorders.put(recording.getId(), new ConcurrentHashMap()); + activeRecorders.put(recording.getId(), new ConcurrentHashMap<>()); + storedRecorders.put(recording.getId(), new ConcurrentHashMap<>()); int activePublishersToRecord = session.getActiveIndividualRecordedPublishers(); final CountDownLatch recordingStartedCountdown = new CountDownLatch(activePublishersToRecord); @@ -149,10 +155,13 @@ public class SingleStreamRecordingService extends RecordingService { recording.hasVideo() ? (recording.hasAudio() ? "video+audio" : "video-only") : "audioOnly", recording.getId(), recording.getSessionId(), reason); - final HashMap wrappers = new HashMap<>(storedRecorders.get(recording.getId())); + final List wrappers = new ArrayList<>(); + storedRecorders.get(recording.getId()).values().forEach(list -> { + wrappers.addAll(list); + }); final CountDownLatch stoppedCountDown = new CountDownLatch(wrappers.size()); - for (RecorderEndpointWrapper wrapper : wrappers.values()) { + for (RecorderEndpointWrapper wrapper : wrappers) { this.stopRecorderEndpointOfPublisherEndpoint(recording.getId(), wrapper.getStreamId(), stoppedCountDown, kmsDisconnectionTime); } @@ -171,9 +180,9 @@ public class SingleStreamRecordingService extends RecordingService { final Recording[] finalRecordingArray = new Recording[1]; finalRecordingArray[0] = recording; try { - this.recordingDownloader.downloadRecording(finalRecordingArray[0], wrappers.keySet(), () -> { + this.recordingDownloader.downloadRecording(finalRecordingArray[0], wrappers, () -> { // Update recording entity files with final file size - for (RecorderEndpointWrapper wrapper : wrappers.values()) { + for (RecorderEndpointWrapper wrapper : wrappers) { if (wrapper.getSize() == 0) { updateIndividualMetadataFile(wrapper); } @@ -211,28 +220,36 @@ public class SingleStreamRecordingService extends RecordingService { log.info("Starting single stream recorder for stream {} in session {}", participant.getPublisherStreamId(), participant.getSessionId()); + final String streamId = participant.getPublisherStreamId(); + try { if (participant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) { try { - if (this.activeRecorders.get(recordingId).containsKey(participant.getPublisherStreamId())) { + if (this.activeRecorders.get(recordingId).containsKey(streamId)) { log.warn("Concurrent initialization of RecorderEndpoint for stream {} of session {}. Returning", - participant.getPublisherStreamId(), participant.getSessionId()); + streamId, participant.getSessionId()); return; } + // Update stream recording counter + final List wrapperList = storedRecorders.get(recordingId).get(streamId); + final int streamCounter = wrapperList != null ? wrapperList.size() : 0; + String fileName = streamCounter == 0 ? streamId : (streamId + "-" + streamCounter); + KurentoParticipant kurentoParticipant = (KurentoParticipant) participant; MediaPipeline pipeline = kurentoParticipant.getPublisher().getPipeline(); RecorderEndpoint recorder = new RecorderEndpoint.Builder(pipeline, - "file://" + openviduConfig.getOpenViduRemoteRecordingPath() + recordingId + "/" - + participant.getPublisherStreamId() + ".webm").withMediaProfile(profile).build(); + "file://" + openviduConfig.getOpenViduRemoteRecordingPath() + recordingId + "/" + fileName + + SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION) + .withMediaProfile(profile).build(); recorder.addRecordingListener(new EventListener() { @Override public void onEvent(RecordingEvent event) { - activeRecorders.get(recordingId).get(participant.getPublisherStreamId()) + activeRecorders.get(recordingId).get(streamId) .setStartTime(Long.parseLong(event.getTimestampMillis())); - log.info("Recording started event for stream {}", participant.getPublisherStreamId()); + log.info("Recording started event for stream {}", streamId); globalStartLatch.countDown(); } }); @@ -245,9 +262,13 @@ public class SingleStreamRecordingService extends RecordingService { }); RecorderEndpointWrapper wrapper = new RecorderEndpointWrapper(recorder, kurentoParticipant, - recordingId); - activeRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper); - storedRecorders.get(recordingId).put(participant.getPublisherStreamId(), wrapper); + recordingId, fileName); + activeRecorders.get(recordingId).put(streamId, wrapper); + if (wrapperList != null) { + wrapperList.add(wrapper); + } else { + storedRecorders.get(recordingId).put(streamId, new ArrayList<>(Arrays.asList(wrapper))); + } connectAccordingToProfile(kurentoParticipant.getPublisher(), recorder, profile); wrapper.getRecorder().record(); @@ -269,33 +290,55 @@ public class SingleStreamRecordingService extends RecordingService { public void stopRecorderEndpointOfPublisherEndpoint(String recordingId, String streamId, CountDownLatch globalStopLatch, Long kmsDisconnectionTime) { + log.info("Stopping single stream recorder for stream {} in recording {}", streamId, recordingId); + final RecorderEndpointWrapper finalWrapper = activeRecorders.get(recordingId).remove(streamId); - if (finalWrapper != null && kmsDisconnectionTime == 0) { - finalWrapper.getRecorder().addStoppedListener(new EventListener() { - @Override - public void onEvent(StoppedEvent event) { - finalWrapper.setEndTime(Long.parseLong(event.getTimestampMillis())); - generateIndividualMetadataFile(finalWrapper); - log.info("Recording stopped event for stream {}", streamId); - finalWrapper.getRecorder().release(); - globalStopLatch.countDown(); - } - }); - finalWrapper.getRecorder().stop(); - } else { - if (kmsDisconnectionTime != 0) { - // Stopping recorder endpoint because of a KMS disconnection - finalWrapper.setEndTime(kmsDisconnectionTime); - generateIndividualMetadataFile(finalWrapper); - log.warn("Forcing individual recording stop after KMS restart for stream {} in recording {}", streamId, - recordingId); - } else { - if (storedRecorders.get(recordingId).containsKey(streamId)) { - log.info("Stream {} recording of recording {} was already stopped", streamId, recordingId); + if (finalWrapper != null) { + KurentoParticipant kParticipant = finalWrapper.getParticipant(); + try { + if (kParticipant.singleRecordingLock.tryLock(15, TimeUnit.SECONDS)) { + try { + if (kmsDisconnectionTime == null) { + finalWrapper.getRecorder().addStoppedListener(new EventListener() { + @Override + public void onEvent(StoppedEvent event) { + finalWrapper.setEndTime(Long.parseLong(event.getTimestampMillis())); + generateIndividualMetadataFile(finalWrapper); + log.info("Recording stopped event for stream {}", streamId); + finalWrapper.getRecorder().release(); + globalStopLatch.countDown(); + } + }); + finalWrapper.getRecorder().stop(); + } else { + // Stopping recorder endpoint because of a KMS disconnection + finalWrapper.setEndTime(kmsDisconnectionTime); + generateIndividualMetadataFile(finalWrapper); + globalStopLatch.countDown(); + log.warn( + "Forcing individual recording stop after KMS restart for stream {} in recording {}", + streamId, recordingId); + } + } finally { + kParticipant.singleRecordingLock.unlock(); + } } else { - log.info("Stream {} wasn't being recorded in recording {}", streamId, recordingId); + log.error( + "Timeout waiting for individual recording lock to be available to stop stream recording for participant {} of session {}", + kParticipant.getParticipantPublicId(), kParticipant.getSessionId()); } + } catch (InterruptedException e) { + log.error( + "InterruptedException waiting for individual recording lock to be available to stop stream recording for participant {} of session {}", + kParticipant.getParticipantPublicId(), kParticipant.getSessionId()); + } + } else { + // The streamId has no associated RecorderEndpoint + if (storedRecorders.get(recordingId).containsKey(streamId)) { + log.info("Stream {} recording of recording {} was already stopped", streamId, recordingId); + } else { + log.info("Stream {} wasn't being recorded in recording {}", streamId, recordingId); } globalStopLatch.countDown(); } @@ -384,9 +427,9 @@ public class SingleStreamRecordingService extends RecordingService { private void commonWriteIndividualMetadataFile(RecorderEndpointWrapper wrapper, BiFunction writeFunction) { String filesPath = this.openviduConfig.getOpenViduRecordingPath() + wrapper.getRecordingId() + "/"; - File videoFile = new File(filesPath + wrapper.getStreamId() + ".webm"); + File videoFile = new File(filesPath + wrapper.getNameWithExtension()); wrapper.setSize(videoFile.length()); - String metadataFilePath = filesPath + INDIVIDUAL_STREAM_METADATA_FILE + wrapper.getStreamId(); + String metadataFilePath = filesPath + INDIVIDUAL_STREAM_METADATA_FILE + wrapper.getName(); String metadataFileContent = wrapper.toJson().toString(); writeFunction.apply(metadataFilePath, metadataFileContent); } @@ -426,12 +469,14 @@ public class SingleStreamRecordingService extends RecordingService { } catch (FileNotFoundException e) { log.error("Error reading file {}. Error: {}", files[i].getAbsolutePath(), e.getMessage()); } - RecorderEndpointWrapper wr = gson.fromJson(reader, RecorderEndpointWrapper.class); + RecorderEndpointWrapper wr = new RecorderEndpointWrapper( + JsonParser.parseReader(reader).getAsJsonObject()); minStartTime = Math.min(minStartTime, wr.getStartTime()); maxEndTime = Math.max(maxEndTime, wr.getEndTime()); accumulatedSize += wr.getSize(); JsonObject jsonFile = new JsonObject(); + jsonFile.addProperty("name", wr.getNameWithExtension()); jsonFile.addProperty("connectionId", wr.getConnectionId()); jsonFile.addProperty("streamId", wr.getStreamId()); jsonFile.addProperty("size", wr.getSize()); @@ -474,7 +519,8 @@ public class SingleStreamRecordingService extends RecordingService { for (int i = 0; i < files.length; i++) { String fileExtension = FilenameUtils.getExtension(files[i].getName()); - if (files[i].isFile() && (fileExtension.equals("json") || fileExtension.equals("webm"))) { + if (files[i].isFile() && (fileExtension.equals("json") + || SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION.equals("." + fileExtension))) { // Zip video files and json sync metadata file FileInputStream fis = new FileInputStream(files[i]); From 63a6261d887f0729cf023c69e52d1b802c740f12 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 12:12:28 +0200 Subject: [PATCH 094/435] openvidu-test-e2e: new Pro class. Parent class AbstractOpenViduTestAppE2eTest --- .../e2e/AbstractOpenViduTestAppE2eTest.java | 546 +++++++++++++++++ .../test/e2e/OpenViduProTestAppE2eTest.java | 263 ++++++++ .../test/e2e/OpenViduTestAppE2eTest.java | 575 +----------------- 3 files changed, 812 insertions(+), 572 deletions(-) create mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java create mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java new file mode 100644 index 00000000..3634ad71 --- /dev/null +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java @@ -0,0 +1,546 @@ +package io.openvidu.test.e2e; + +import static org.openqa.selenium.OutputType.BASE64; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.math.RoundingMode; +import java.nio.file.Path; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.imageio.ImageIO; + +import org.apache.commons.io.FileUtils; +import org.jcodec.api.FrameGrab; +import org.jcodec.api.JCodecException; +import org.jcodec.common.model.Picture; +import org.jcodec.scale.AWTUtil; +import org.junit.Assert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonReader; + +import io.github.bonigarcia.wdm.WebDriverManager; +import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduJavaClientException; +import io.openvidu.java.client.Recording; +import io.openvidu.test.browsers.BrowserUser; +import io.openvidu.test.browsers.ChromeAndroidUser; +import io.openvidu.test.browsers.ChromeUser; +import io.openvidu.test.browsers.FirefoxUser; +import io.openvidu.test.browsers.OperaUser; +import io.openvidu.test.browsers.utils.CommandLineExecutor; +import io.openvidu.test.browsers.utils.MultimediaFileMetadata; +import io.openvidu.test.browsers.utils.Unzipper; + +public class AbstractOpenViduTestAppE2eTest { + + protected static String OPENVIDU_SECRET = "MY_SECRET"; + protected static String OPENVIDU_URL = "https://localhost:4443/"; + protected static String APP_URL = "http://localhost:4200/"; + protected static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:5555"; + protected static String EXTERNAL_CUSTOM_LAYOUT_PARAMS = "sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET"; + protected static Exception ex = null; + protected final Object lock = new Object(); + + protected static final Logger log = LoggerFactory.getLogger(OpenViduTestAppE2eTest.class); + protected static final CommandLineExecutor commandLine = new CommandLineExecutor(); + protected static final String RECORDING_IMAGE = "openvidu/openvidu-recording"; + + protected MyUser user; + protected Collection otherUsers = new ArrayList<>(); + protected volatile static boolean isRecordingTest; + protected volatile static boolean isKurentoRestartTest; + protected static OpenVidu OV; + + @BeforeAll() + protected static void setupAll() { + + String ffmpegOutput = commandLine.executeCommand("which ffmpeg"); + if (ffmpegOutput == null || ffmpegOutput.isEmpty()) { + log.error("ffmpeg package is not installed in the host machine"); + Assert.fail(); + return; + } else { + log.info("ffmpeg is installed and accesible"); + } + + WebDriverManager.chromedriver().setup(); + WebDriverManager.firefoxdriver().setup(); + + String appUrl = System.getProperty("APP_URL"); + if (appUrl != null) { + APP_URL = appUrl; + } + log.info("Using URL {} to connect to openvidu-testapp", APP_URL); + + String externalCustomLayoutUrl = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_URL"); + if (externalCustomLayoutUrl != null) { + EXTERNAL_CUSTOM_LAYOUT_URL = externalCustomLayoutUrl; + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); + + String externalCustomLayoutParams = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_PARAMS"); + if (externalCustomLayoutParams != null) { + // Parse external layout parameters and build a URL formatted params string + List params = Stream.of(externalCustomLayoutParams.split(",", -1)).collect(Collectors.toList()); + if (params.size() % 2 != 0) { + log.error( + "Wrong configuration property EXTERNAL_CUSTOM_LAYOUT_PARAMS. Must be a comma separated list with an even number of elements. e.g: EXTERNAL_CUSTOM_LAYOUT_PARAMS=param1,value1,param2,value2"); + Assert.fail(); + return; + } else { + EXTERNAL_CUSTOM_LAYOUT_PARAMS = ""; + for (int i = 0; i < params.size(); i++) { + if (i % 2 == 0) { + // Param name + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i) + "="; + } else { + // Param value + EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i); + if (i < params.size() - 1) { + EXTERNAL_CUSTOM_LAYOUT_PARAMS += "&"; + } + } + } + } + } + log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_PARAMS); + + String openviduUrl = System.getProperty("OPENVIDU_URL"); + if (openviduUrl != null) { + OPENVIDU_URL = openviduUrl; + } + log.info("Using URL {} to connect to openvidu-server", OPENVIDU_URL); + + String openvidusecret = System.getProperty("OPENVIDU_SECRET"); + if (openvidusecret != null) { + OPENVIDU_SECRET = openvidusecret; + } + log.info("Using secret {} to connect to openvidu-server", OPENVIDU_SECRET); + + try { + log.info("Cleaning folder /opt/openvidu/recordings"); + FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); + } catch (IOException e) { + log.error(e.getMessage()); + } + OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + protected void setupBrowser(String browser) { + + BrowserUser browserUser; + + switch (browser) { + case "chrome": + browserUser = new ChromeUser("TestUser", 50, false); + break; + case "firefox": + browserUser = new FirefoxUser("TestUser", 50); + break; + case "opera": + browserUser = new OperaUser("TestUser", 50); + break; + case "chromeAndroid": + browserUser = new ChromeAndroidUser("TestUser", 50); + break; + case "chromeAlternateScreenShare": + browserUser = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false); + break; + case "chromeAsRoot": + browserUser = new ChromeUser("TestUser", 50, true); + break; + default: + browserUser = new ChromeUser("TestUser", 50, false); + } + + this.user = new MyUser(browserUser); + + user.getDriver().get(APP_URL); + + WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + + user.getEventManager().startPolling(); + } + + protected void setupChromeWithFakeVideo(Path videoFileLocation) { + this.user = new MyUser(new ChromeUser("TestUser", 50, videoFileLocation)); + user.getDriver().get(APP_URL); + WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys(OPENVIDU_URL); + WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + user.getEventManager().startPolling(); + } + + @AfterEach + protected void dispose() { + if (user != null) { + user.dispose(); + } + Iterator it = otherUsers.iterator(); + while (it.hasNext()) { + MyUser other = it.next(); + other.dispose(); + it.remove(); + } + try { + OV.fetch(); + } catch (OpenViduJavaClientException | OpenViduHttpException e1) { + log.error("Error fetching sessions: {}", e1.getMessage()); + } + OV.getActiveSessions().forEach(session -> { + try { + session.close(); + log.info("Session {} successfully closed", session.getSessionId()); + } catch (OpenViduJavaClientException e) { + log.error("Error closing session: {}", e.getMessage()); + } catch (OpenViduHttpException e) { + log.error("Error closing session: {}", e.getMessage()); + } + }); + if (isRecordingTest) { + removeAllRecordingContiners(); + try { + FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); + } catch (IOException e) { + log.error(e.getMessage()); + } + isRecordingTest = false; + } + if (isKurentoRestartTest) { + this.restartKms(); + isKurentoRestartTest = false; + } + OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + protected void listEmptyRecordings() { + // List existing recordings (empty) + user.getDriver().findElement(By.id("list-recording-btn")).click(); + user.getWaiter() + .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Recording list []")); + } + + protected ExpectedCondition waitForVideoDuration(WebElement element, int durationInSeconds) { + return new ExpectedCondition() { + @Override + public Boolean apply(WebDriver input) { + return element.getAttribute("duration").matches( + durationInSeconds - 1 + "\\.[5-9][0-9]{0,5}|" + durationInSeconds + "\\.[0-5][0-9]{0,5}"); + } + }; + } + + protected static boolean checkVideoAverageRgbGreen(Map rgb) { + // GREEN color: {r < 15, g > 130, b <15} + return (rgb.get("r") < 15) && (rgb.get("g") > 130) && (rgb.get("b") < 15); + } + + protected static boolean checkVideoAverageRgbGray(Map rgb) { + // GRAY color: {r < 50, g < 50, b < 50} and the absolute difference between them + // not greater than 2 + return (rgb.get("r") < 50) && (rgb.get("g") < 50) && (rgb.get("b") < 50) + && (Math.abs(rgb.get("r") - rgb.get("g")) <= 2) && (Math.abs(rgb.get("r") - rgb.get("b")) <= 2) + && (Math.abs(rgb.get("b") - rgb.get("g")) <= 2); + } + + protected static boolean checkVideoAverageRgbRed(Map rgb) { + // RED color: {r > 240, g < 15, b <15} + return (rgb.get("r") > 240) && (rgb.get("g") < 15) && (rgb.get("b") < 15); + } + + protected void gracefullyLeaveParticipants(int numberOfParticipants) throws Exception { + int accumulatedConnectionDestroyed = 0; + for (int j = 1; j <= numberOfParticipants; j++) { + user.getDriver().findElement(By.id("remove-user-btn")).sendKeys(Keys.ENTER); + user.getEventManager().waitUntilEventReaches("sessionDisconnected", j); + accumulatedConnectionDestroyed = (j != numberOfParticipants) + ? (accumulatedConnectionDestroyed + numberOfParticipants - j) + : (accumulatedConnectionDestroyed); + user.getEventManager().waitUntilEventReaches("connectionDestroyed", accumulatedConnectionDestroyed); + } + } + + protected String getBase64Screenshot(MyUser user) throws Exception { + String screenshotBase64 = ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64); + return "data:image/png;base64," + screenshotBase64; + } + + protected boolean recordedFileFine(File file, Recording recording, + Function, Boolean> colorCheckFunction) throws IOException { + this.checkMultimediaFile(file, recording.hasAudio(), recording.hasVideo(), recording.getDuration(), + recording.getResolution(), "aac", "h264", true); + + boolean isFine = false; + Picture frame; + try { + // Get a frame at 75% duration and check that it has the expected color + frame = FrameGrab.getFrameAtSec(file, (double) (recording.getDuration() * 0.75)); + BufferedImage image = AWTUtil.toBufferedImage(frame); + Map colorMap = this.averageColor(image); + + String realResolution = image.getWidth() + "x" + image.getHeight(); + Assert.assertEquals( + "Resolution (" + recording.getResolution() + + ") of recording entity is not equal to real video resolution (" + realResolution + ")", + recording.getResolution(), realResolution); + + log.info("Recording map color: {}", colorMap.toString()); + log.info("Recording frame below"); + System.out.println(bufferedImageToBase64PngString(image)); + isFine = colorCheckFunction.apply(colorMap); + } catch (IOException | JCodecException e) { + log.warn("Error getting frame from video recording: {}", e.getMessage()); + isFine = false; + } + return isFine; + } + + protected boolean recordedGreenFileFine(File file, Recording recording) throws IOException { + return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen); + } + + protected boolean recordedRedFileFine(File file, Recording recording) throws IOException { + return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbRed); + } + + protected String bufferedImageToBase64PngString(BufferedImage image) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String imageString = null; + try { + ImageIO.write(image, "png", bos); + byte[] imageBytes = bos.toByteArray(); + imageString = "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes); + bos.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return imageString; + } + + protected void checkIndividualRecording(String recPath, Recording recording, int numberOfVideoFiles, + String audioDecoder, String videoDecoder, boolean checkAudio) throws IOException { + + // Should be only 2 files: zip and metadata + File folder = new File(recPath); + Assert.assertEquals("There are more than 2 files (ZIP and metadata) inside individual recording folder " + + recPath + ": " + Arrays.toString(folder.listFiles()), 2, folder.listFiles().length); + + File file1 = new File(recPath + recording.getName() + ".zip"); + File file2 = new File(recPath + ".recording." + recording.getId()); + + Assert.assertTrue("File " + file1.getAbsolutePath() + " does not exist or is empty", + file1.exists() && file1.length() > 0); + Assert.assertTrue("File " + file2.getAbsolutePath() + " does not exist or is empty", + file2.exists() && file2.length() > 0); + + List unzippedWebmFiles = new Unzipper().unzipFile(recPath, recording.getName() + ".zip"); + + Assert.assertEquals("Expecting " + numberOfVideoFiles + " videos inside ZIP file but " + + unzippedWebmFiles.size() + " found: " + unzippedWebmFiles.toString(), numberOfVideoFiles, + unzippedWebmFiles.size()); + + File jsonSyncFile = new File(recPath + recording.getName() + ".json"); + Assert.assertTrue("JSON sync file " + jsonSyncFile.getAbsolutePath() + "does not exist or is empty", + jsonSyncFile.exists() && jsonSyncFile.length() > 0); + + JsonObject jsonSyncMetadata; + try { + Gson gson = new Gson(); + JsonReader reader = new JsonReader(new FileReader(jsonSyncFile)); + jsonSyncMetadata = gson.fromJson(reader, JsonObject.class); + } catch (Exception e) { + log.error("Cannot read JSON sync metadata file from {}. Error: {}", jsonSyncFile.getAbsolutePath(), + e.getMessage()); + Assert.fail("Cannot read JSON sync metadata file from " + jsonSyncFile.getAbsolutePath()); + return; + } + + long totalFileSize = 0; + JsonArray syncArray = jsonSyncMetadata.get("files").getAsJsonArray(); + for (File webmFile : unzippedWebmFiles) { + totalFileSize += webmFile.length(); + + Assert.assertTrue("WEBM file " + webmFile.getAbsolutePath() + " does not exist or is empty", + webmFile.exists() && webmFile.length() > 0); + + double durationInSeconds = 0; + boolean found = false; + for (int i = 0; i < syncArray.size(); i++) { + JsonObject j = syncArray.get(i).getAsJsonObject(); + if (webmFile.getName().contains(j.get("streamId").getAsString())) { + durationInSeconds = (double) (j.get("endTimeOffset").getAsDouble() + - j.get("startTimeOffset").getAsDouble()) / 1000; + found = true; + break; + } + } + + Assert.assertTrue("Couldn't find in JSON sync object information for webm file " + webmFile.getName(), + found); + + log.info("Duration of {} according to sync metadata json file: {} s", webmFile.getName(), + durationInSeconds); + this.checkMultimediaFile(webmFile, recording.hasAudio(), recording.hasVideo(), durationInSeconds, + recording.getResolution(), audioDecoder, videoDecoder, checkAudio); + webmFile.delete(); + } + + Assert.assertEquals("Size of recording entity (" + recording.getSessionId() + + ") is not equal to real file size (" + totalFileSize + ")", recording.getSize(), totalFileSize); + + jsonSyncFile.delete(); + } + + protected void checkMultimediaFile(File file, boolean hasAudio, boolean hasVideo, double duration, + String resolution, String audioDecoder, String videoDecoder, boolean checkAudio) throws IOException { + // Check tracks, duration, resolution, framerate and decoders + MultimediaFileMetadata metadata = new MultimediaFileMetadata(file.getAbsolutePath()); + + if (hasVideo) { + if (checkAudio) { + if (hasAudio) { + Assert.assertTrue("Media file " + file.getAbsolutePath() + " should have audio", + metadata.hasAudio() && metadata.hasVideo()); + Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); + } else { + Assert.assertTrue("Media file " + file.getAbsolutePath() + " should have video", + metadata.hasVideo()); + Assert.assertFalse(metadata.hasAudio()); + } + } + if (resolution != null) { + Assert.assertEquals(resolution, metadata.getVideoWidth() + "x" + metadata.getVideoHeight()); + } + Assert.assertTrue(metadata.getVideoDecoder().toLowerCase().contains(videoDecoder)); + } else if (hasAudio && checkAudio) { + Assert.assertTrue(metadata.hasAudio()); + Assert.assertFalse(metadata.hasVideo()); + Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); + } else { + Assert.fail("Cannot check a file witho no audio and no video"); + } + // Check duration with 1 decimal precision + DecimalFormat df = new DecimalFormat("#0.0"); + df.setRoundingMode(RoundingMode.UP); + log.info("Duration of {} according to ffmpeg: {} s", file.getName(), metadata.getDuration()); + log.info("Duration of {} according to 'duration' property: {} s", file.getName(), duration); + log.info("Difference in s duration: {}", Math.abs(metadata.getDuration() - duration)); + final double difference = 10; + Assert.assertTrue( + "Difference between recording entity duration (" + duration + ") and real video duration (" + + metadata.getDuration() + ") is greater than " + difference + " in file " + file.getName(), + Math.abs((metadata.getDuration() - duration)) < difference); + } + + protected boolean thumbnailIsFine(File file, Function, Boolean> colorCheckFunction) { + boolean isFine = false; + BufferedImage image = null; + try { + image = ImageIO.read(file); + } catch (IOException e) { + log.error(e.getMessage()); + return false; + } + log.info("Recording thumbnail dimensions: {}x{}", image.getWidth(), image.getHeight()); + Map colorMap = this.averageColor(image); + log.info("Thumbnail map color: {}", colorMap.toString()); + isFine = colorCheckFunction.apply(colorMap); + return isFine; + } + + protected Map averageColor(BufferedImage bi) { + int x0 = 0; + int y0 = 0; + int w = bi.getWidth(); + int h = bi.getHeight(); + int x1 = x0 + w; + int y1 = y0 + h; + long sumr = 0, sumg = 0, sumb = 0; + for (int x = x0; x < x1; x++) { + for (int y = y0; y < y1; y++) { + Color pixel = new Color(bi.getRGB(x, y)); + sumr += pixel.getRed(); + sumg += pixel.getGreen(); + sumb += pixel.getBlue(); + } + } + int num = w * h; + Map colorMap = new HashMap<>(); + colorMap.put("r", (long) (sumr / num)); + colorMap.put("g", (long) (sumg / num)); + colorMap.put("b", (long) (sumb / num)); + return colorMap; + } + + protected void startKms() { + log.info("Starting KMS"); + commandLine.executeCommand("/usr/bin/kurento-media-server &>> /kms.log &"); + } + + protected void stopKms() { + log.info("Stopping KMS"); + commandLine.executeCommand("kill -9 $(pidof kurento-media-server)"); + } + + protected void restartKms() { + this.stopKms(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + this.startKms(); + } + + protected void checkDockerContainerRunning(String imageName, int amount) { + int number = Integer.parseInt(commandLine.executeCommand("docker ps | grep " + imageName + " | wc -l")); + Assert.assertEquals("Wrong number of Docker containers for image " + imageName + " running", amount, number); + } + + protected void removeAllRecordingContiners() { + commandLine.executeCommand("docker ps -a | awk '{ print $1,$2 }' | grep " + RECORDING_IMAGE + + " | awk '{print $1 }' | xargs -I {} docker rm -f {}"); + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java new file mode 100644 index 00000000..00774e0f --- /dev/null +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -0,0 +1,263 @@ +package io.openvidu.test.e2e; + +import java.io.File; +import java.io.FileReader; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.http.HttpStatus; +import org.junit.Assert; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.openqa.selenium.Alert; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedConditions; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonReader; +import com.mashape.unirest.http.HttpMethod; + +import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.Recording; +import io.openvidu.test.browsers.utils.CustomHttpClient; +import io.openvidu.test.browsers.utils.Unzipper; + +public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + + @Test + @DisplayName("Individual dynamic record") + void individualDynamicRecordTest() throws Exception { + isRecordingTest = true; + + setupBrowser("chrome"); + + log.info("Individual dynamic record"); + + CustomHttpClient restClient = new CustomHttpClient(OpenViduTestAppE2eTest.OPENVIDU_URL, "OPENVIDUAPP", + OpenViduTestAppE2eTest.OPENVIDU_SECRET); + + // Connect 3 users. Record only the first one + for (int i = 0; i < 3; i++) { + user.getDriver().findElement(By.id("add-user-btn")).click(); + if (i > 0) { + user.getDriver().findElement(By.id("session-settings-btn-" + i)).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("record-checkbox")).click(); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + } + } + + String sessionName = "TestSession"; + + user.getDriver().findElements(By.className("join-btn")).forEach(el -> el.sendKeys(Keys.ENTER)); + user.getEventManager().waitUntilEventReaches("streamPlaying", 9); + + // Start the recording for one of the not recorded users + JsonObject sessionInfo = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/" + sessionName, + HttpStatus.SC_OK); + JsonArray connections = sessionInfo.get("connections").getAsJsonObject().get("content").getAsJsonArray(); + String connectionId1 = null; + String streamId1 = null; + // Get connectionId and streamId + for (JsonElement connection : connections) { + if (connection.getAsJsonObject().get("record").getAsBoolean()) { + connectionId1 = connection.getAsJsonObject().get("connectionId").getAsString(); + streamId1 = connection.getAsJsonObject().get("publishers").getAsJsonArray().get(0).getAsJsonObject() + .get("streamId").getAsString(); + break; + } + } + + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", + "{'session':'" + sessionName + "','outputMode':'INDIVIDUAL'}", HttpStatus.SC_OK); + user.getEventManager().waitUntilEventReaches("recordingStarted", 3); + Thread.sleep(1000); + + // Start the recording for one of the not recorded users + sessionInfo = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/" + sessionName, HttpStatus.SC_OK); + connections = sessionInfo.get("connections").getAsJsonObject().get("content").getAsJsonArray(); + String connectionId2 = null; + String streamId2 = null; + // Get connectionId and streamId + for (JsonElement connection : connections) { + if (!connection.getAsJsonObject().get("record").getAsBoolean()) { + connectionId2 = connection.getAsJsonObject().get("connectionId").getAsString(); + streamId2 = connection.getAsJsonObject().get("publishers").getAsJsonArray().get(0).getAsJsonObject() + .get("streamId").getAsString(); + break; + } + } + + // Generate 3 total recordings of 1 second length for this same stream + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/" + sessionName + "/connection/" + connectionId2, + "{'record':true}", HttpStatus.SC_OK); + Thread.sleep(1000); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/" + sessionName + "/connection/" + connectionId2, + "{'record':false}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/" + sessionName + "/connection/" + connectionId2, + "{'record':true}", HttpStatus.SC_OK); + Thread.sleep(1000); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/" + sessionName + "/connection/" + connectionId2, + "{'record':false}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/" + sessionName + "/connection/" + connectionId2, + "{'record':true}", HttpStatus.SC_OK); + Thread.sleep(1000); + + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/" + sessionName, HttpStatus.SC_OK); + user.getEventManager().waitUntilEventReaches("recordingStopped", 3); + + gracefullyLeaveParticipants(3); + + String recPath = "/opt/openvidu/recordings/" + sessionName + "/"; + Recording recording = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET) + .getRecording(sessionName); + checkIndividualRecording(recPath, recording, 4, "opus", "vp8", true); + + // Analyze INDIVIDUAL recording metadata + new Unzipper().unzipFile(recPath, recording.getName() + ".zip"); + File jsonSyncFile = new File(recPath + recording.getName() + ".json"); + JsonReader reader = new JsonReader(new FileReader(jsonSyncFile)); + JsonObject jsonMetadata = new Gson().fromJson(reader, JsonObject.class); + JsonArray syncArray = jsonMetadata.get("files").getAsJsonArray(); + int count1 = 0; + int count2 = 0; + List names = Stream.of(streamId2 + ".webm", streamId2 + "-1.webm", streamId2 + "-2.webm") + .collect(Collectors.toList()); + for (JsonElement fileJson : syncArray) { + JsonObject file = fileJson.getAsJsonObject(); + String fileStreamId = file.get("streamId").getAsString(); + if (fileStreamId.equals(streamId1)) { + // Normal recorded user + Assert.assertEquals("Wrong connectionId file metadata property", connectionId1, + file.get("connectionId").getAsString()); + long msDuration = file.get("endTimeOffset").getAsLong() - file.get("startTimeOffset").getAsLong(); + Assert.assertTrue("Wrong recording duration of individual file. Difference: " + (msDuration - 4000), + msDuration - 4000 < 750); + count1++; + } else if (fileStreamId.equals(streamId2)) { + // Dynamically recorded user + Assert.assertEquals("Wrong connectionId file metadata property", connectionId2, + file.get("connectionId").getAsString()); + long msDuration = file.get("endTimeOffset").getAsLong() - file.get("startTimeOffset").getAsLong(); + Assert.assertTrue( + "Wrong recording duration of individual file. Difference: " + Math.abs(msDuration - 1000), + Math.abs(msDuration - 1000) < 100); + Assert.assertTrue("File name not found among " + names.toString(), + names.remove(file.get("name").getAsString())); + count2++; + } else { + Assert.fail("Metadata file element does not belong to a known stream (" + fileStreamId + ")"); + } + } + Assert.assertEquals("Wrong number of recording files for stream " + streamId1, 1, count1); + Assert.assertEquals("Wrong number of recording files for stream " + streamId2, 3, count2); + Assert.assertTrue("Some expected file name didn't existed: " + names.toString(), names.isEmpty()); + } + + @Test + @DisplayName("REST API PRO test") + void restApiProTest() throws Exception { + + setupBrowser("chrome"); + + log.info("REST API PRO test"); + + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + + /** + * PATCH /openvidu/api/sessions//connection/ + **/ + String body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); + body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}"; + JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); + final String token = res.get("token").getAsString(); + final String tokenConnectionId = res.get("connectionId").getAsString(); + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); + + // Set token + WebElement tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); + tokenInput.clear(); + tokenInput.sendKeys(token); + // Force publishing even SUBSCRIBER + user.getDriver().findElement(By.id("force-publishing-checkbox")).click(); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + + user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .join-btn")).sendKeys(Keys.ENTER); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + + try { + user.getWaiter().until(ExpectedConditions.alertIsPresent()); + Alert alert = user.getDriver().switchTo().alert(); + Assert.assertTrue("Alert does not contain expected text", + alert.getText().equals("OPENVIDU_PERMISSION_DENIED: You don't have permissions to publish")); + alert.accept(); + } catch (Exception e) { + Assert.fail("Alert exception"); + } + Thread.sleep(500); + + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':false}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'record':123}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'PUBLISHER',record:'WRONG'}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'SUBSCRIBER','record':true}", HttpStatus.SC_NO_CONTENT); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'PUBLISHER'}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'PUBLISHER'}", HttpStatus.SC_NO_CONTENT); + + user.getEventManager().resetEventThread(); + + user.getWaiter().until(ExpectedConditions.elementToBeClickable(By.cssSelector(".republish-error-btn"))); + user.getDriver().findElement(By.cssSelector(".republish-error-btn")).click(); + + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 1); + + // connectionId should be equal to the one brought by the token + Assert.assertEquals("Wrong connectionId", tokenConnectionId, + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK) + .get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject() + .get("connectionId").getAsString()); + + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); + + // GET /openvidu/api/sessions should return empty again + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, + ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); + + /** GET /openvidu/api/config **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, + "{'VERSION':'STR','DOMAIN_OR_PUBLIC_IP':'STR','HTTPS_PORT':0,'OPENVIDU_PUBLICURL':'STR','OPENVIDU_CDR':false,'OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH':0," + + "'OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH':0,'OPENVIDU_SESSIONS_GARBAGE_INTERVAL':0,'OPENVIDU_SESSIONS_GARBAGE_THRESHOLD':0," + + "'OPENVIDU_RECORDING':false,'OPENVIDU_RECORDING_VERSION':'STR','OPENVIDU_RECORDING_PATH':'STR','OPENVIDU_RECORDING_PUBLIC_ACCESS':false,'OPENVIDU_RECORDING_NOTIFICATION':'STR'," + + "'OPENVIDU_RECORDING_CUSTOM_LAYOUT':'STR','OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT':0,'OPENVIDU_WEBHOOK':false,'OPENVIDU_WEBHOOK_ENDPOINT':'STR','OPENVIDU_WEBHOOK_HEADERS':[]," + + "'OPENVIDU_WEBHOOK_EVENTS':[],'OPENVIDU_SERVER_DEPENDENCY_VERSION':'STR','KMS_URIS':[],'OPENVIDU_PRO_STATS_MONITORING_INTERVAL':0,'OPENVIDU_PRO_STATS_WEBRTC_INTERVAL':0,'OPENVIDU_PRO_CLUSTER_ID':'STR'," + + "'OPENVIDU_PRO_CLUSTER_ENVIRONMENT':'STR','OPENVIDU_PRO_CLUSTER_MEDIA_NODES':0,'OPENVIDU_PRO_CLUSTER_PATH':'STR','OPENVIDU_PRO_CLUSTER_AUTOSCALING':false,'OPENVIDU_PRO_NETWORK_STAT':false," + + "'OPENVIDU_PRO_ELASTICSEARCH':false,'OPENVIDU_PRO_KIBANA':false,'OPENVIDU_PRO_RECORDING_STORAGE':'STR'}"); + + /** GET /openvidu/api/health **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/health", null, HttpStatus.SC_OK, true, + ImmutableMap.of("status", "UP")); + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index f90eaa56..665e1d44 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -18,23 +18,11 @@ package io.openvidu.test.e2e; import static org.junit.Assert.fail; -import static org.openqa.selenium.OutputType.BASE64; -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.math.RoundingMode; -import java.nio.file.Path; import java.nio.file.Paths; -import java.text.DecimalFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; -import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -42,21 +30,9 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.imageio.ImageIO; - -import org.apache.commons.io.FileUtils; import org.apache.http.HttpStatus; -import org.jcodec.api.FrameGrab; -import org.jcodec.api.JCodecException; -import org.jcodec.common.model.Picture; -import org.jcodec.scale.AWTUtil; import org.junit.Assert; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -65,30 +41,21 @@ import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.Keys; -import org.openqa.selenium.TakesScreenshot; -import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.google.common.collect.ImmutableMap; -import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import com.google.gson.stream.JsonReader; import com.mashape.unirest.http.HttpMethod; -import io.github.bonigarcia.wdm.WebDriverManager; import io.openvidu.java.client.Connection; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.OpenVidu; import io.openvidu.java.client.OpenViduHttpException; -import io.openvidu.java.client.OpenViduJavaClientException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Publisher; import io.openvidu.java.client.Recording; @@ -99,15 +66,8 @@ import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.Session; import io.openvidu.java.client.SessionProperties; import io.openvidu.java.client.TokenOptions; -import io.openvidu.test.browsers.BrowserUser; -import io.openvidu.test.browsers.ChromeAndroidUser; -import io.openvidu.test.browsers.ChromeUser; import io.openvidu.test.browsers.FirefoxUser; -import io.openvidu.test.browsers.OperaUser; -import io.openvidu.test.browsers.utils.CommandLineExecutor; import io.openvidu.test.browsers.utils.CustomHttpClient; -import io.openvidu.test.browsers.utils.MultimediaFileMetadata; -import io.openvidu.test.browsers.utils.Unzipper; import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler; import io.openvidu.test.browsers.utils.webhook.CustomWebhook; @@ -120,195 +80,7 @@ import io.openvidu.test.browsers.utils.webhook.CustomWebhook; @Tag("e2e") @DisplayName("E2E tests for OpenVidu TestApp") @ExtendWith(SpringExtension.class) -public class OpenViduTestAppE2eTest { - - static String OPENVIDU_SECRET = "MY_SECRET"; - static String OPENVIDU_URL = "https://localhost:4443/"; - static String APP_URL = "http://localhost:4200/"; - static String EXTERNAL_CUSTOM_LAYOUT_URL = "http://localhost:5555"; - static String EXTERNAL_CUSTOM_LAYOUT_PARAMS = "sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET"; - static Exception ex = null; - private final Object lock = new Object(); - - private static final Logger log = LoggerFactory.getLogger(OpenViduTestAppE2eTest.class); - private static final CommandLineExecutor commandLine = new CommandLineExecutor(); - private static final String RECORDING_IMAGE = "openvidu/openvidu-recording"; - - MyUser user; - Collection otherUsers = new ArrayList<>(); - volatile static boolean isRecordingTest; - volatile static boolean isKurentoRestartTest; - private static OpenVidu OV; - - @BeforeAll() - static void setupAll() { - - String ffmpegOutput = commandLine.executeCommand("which ffmpeg"); - if (ffmpegOutput == null || ffmpegOutput.isEmpty()) { - log.error("ffmpeg package is not installed in the host machine"); - Assert.fail(); - return; - } else { - log.info("ffmpeg is installed and accesible"); - } - - WebDriverManager.chromedriver().setup(); - WebDriverManager.firefoxdriver().setup(); - - String appUrl = System.getProperty("APP_URL"); - if (appUrl != null) { - APP_URL = appUrl; - } - log.info("Using URL {} to connect to openvidu-testapp", APP_URL); - - String externalCustomLayoutUrl = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_URL"); - if (externalCustomLayoutUrl != null) { - EXTERNAL_CUSTOM_LAYOUT_URL = externalCustomLayoutUrl; - } - log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_URL); - - String externalCustomLayoutParams = System.getProperty("EXTERNAL_CUSTOM_LAYOUT_PARAMS"); - if (externalCustomLayoutParams != null) { - // Parse external layout parameters and build a URL formatted params string - List params = Stream.of(externalCustomLayoutParams.split(",", -1)).collect(Collectors.toList()); - if (params.size() % 2 != 0) { - log.error( - "Wrong configuration property EXTERNAL_CUSTOM_LAYOUT_PARAMS. Must be a comma separated list with an even number of elements. e.g: EXTERNAL_CUSTOM_LAYOUT_PARAMS=param1,value1,param2,value2"); - Assert.fail(); - return; - } else { - EXTERNAL_CUSTOM_LAYOUT_PARAMS = ""; - for (int i = 0; i < params.size(); i++) { - if (i % 2 == 0) { - // Param name - EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i) + "="; - } else { - // Param value - EXTERNAL_CUSTOM_LAYOUT_PARAMS += params.get(i); - if (i < params.size() - 1) { - EXTERNAL_CUSTOM_LAYOUT_PARAMS += "&"; - } - } - } - } - } - log.info("Using URL {} to connect to external custom layout", EXTERNAL_CUSTOM_LAYOUT_PARAMS); - - String openviduUrl = System.getProperty("OPENVIDU_URL"); - if (openviduUrl != null) { - OPENVIDU_URL = openviduUrl; - } - log.info("Using URL {} to connect to openvidu-server", OPENVIDU_URL); - - String openvidusecret = System.getProperty("OPENVIDU_SECRET"); - if (openvidusecret != null) { - OPENVIDU_SECRET = openvidusecret; - } - log.info("Using secret {} to connect to openvidu-server", OPENVIDU_SECRET); - - try { - log.info("Cleaning folder /opt/openvidu/recordings"); - FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); - } catch (IOException e) { - log.error(e.getMessage()); - } - OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); - } - - void setupBrowser(String browser) { - - BrowserUser browserUser; - - switch (browser) { - case "chrome": - browserUser = new ChromeUser("TestUser", 50, false); - break; - case "firefox": - browserUser = new FirefoxUser("TestUser", 50); - break; - case "opera": - browserUser = new OperaUser("TestUser", 50); - break; - case "chromeAndroid": - browserUser = new ChromeAndroidUser("TestUser", 50); - break; - case "chromeAlternateScreenShare": - browserUser = new ChromeUser("TestUser", 50, "OpenVidu TestApp", false); - break; - case "chromeAsRoot": - browserUser = new ChromeUser("TestUser", 50, true); - break; - default: - browserUser = new ChromeUser("TestUser", 50, false); - } - - this.user = new MyUser(browserUser); - - user.getDriver().get(APP_URL); - - WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); - urlInput.clear(); - urlInput.sendKeys(OPENVIDU_URL); - WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); - secretInput.clear(); - secretInput.sendKeys(OPENVIDU_SECRET); - - user.getEventManager().startPolling(); - } - - void setupChromeWithFakeVideo(Path videoFileLocation) { - this.user = new MyUser(new ChromeUser("TestUser", 50, videoFileLocation)); - user.getDriver().get(APP_URL); - WebElement urlInput = user.getDriver().findElement(By.id("openvidu-url")); - urlInput.clear(); - urlInput.sendKeys(OPENVIDU_URL); - WebElement secretInput = user.getDriver().findElement(By.id("openvidu-secret")); - secretInput.clear(); - secretInput.sendKeys(OPENVIDU_SECRET); - user.getEventManager().startPolling(); - } - - @AfterEach - void dispose() { - if (user != null) { - user.dispose(); - } - Iterator it = otherUsers.iterator(); - while (it.hasNext()) { - MyUser other = it.next(); - other.dispose(); - it.remove(); - } - try { - OV.fetch(); - } catch (OpenViduJavaClientException | OpenViduHttpException e1) { - log.error("Error fetching sessions: {}", e1.getMessage()); - } - OV.getActiveSessions().forEach(session -> { - try { - session.close(); - log.info("Session {} successfully closed", session.getSessionId()); - } catch (OpenViduJavaClientException e) { - log.error("Error closing session: {}", e.getMessage()); - } catch (OpenViduHttpException e) { - log.error("Error closing session: {}", e.getMessage()); - } - }); - if (isRecordingTest) { - removeAllRecordingContiners(); - try { - FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); - } catch (IOException e) { - log.error(e.getMessage()); - } - isRecordingTest = false; - } - if (isKurentoRestartTest) { - this.restartKms(); - isKurentoRestartTest = false; - } - OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); - } +public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("One2One Chrome [Video + Audio]") @@ -1583,46 +1355,6 @@ public class OpenViduTestAppE2eTest { gracefullyLeaveParticipants(2); } - @Test - @DisplayName("Individual dynamic record") - void individualDynamicRecordTest() throws Exception { - isRecordingTest = true; - - setupBrowser("chrome"); - - log.info("Individual dynamic record"); - - // Connect 3 users. Two of them not recorded - for (int i = 0; i < 3; i++) { - user.getDriver().findElement(By.id("add-user-btn")).click(); - if (i < 2) { - user.getDriver().findElement(By.id("session-settings-btn-" + i)).click(); - Thread.sleep(1000); - user.getDriver().findElement(By.id("record-checkbox")).click(); - user.getDriver().findElement(By.id("save-btn")).click(); - Thread.sleep(1000); - } - } - - String sessionName = "TestSession"; - - user.getDriver().findElements(By.className("join-btn")).forEach(el -> el.sendKeys(Keys.ENTER)); - user.getEventManager().waitUntilEventReaches("streamPlaying", 6); - - CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); - restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", - "{'session':'" + sessionName + "','outputMode':'INDIVIDUAL'}", HttpStatus.SC_OK); - user.getEventManager().waitUntilEventReaches("recordingStarted", 3); - Thread.sleep(2000); - restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/" + sessionName, HttpStatus.SC_OK); - user.getEventManager().waitUntilEventReaches("recordingStopped", 3); - - String recPath = "/opt/openvidu/recordings/" + sessionName + "/"; - Recording recording = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET).getRecording(sessionName); - this.checkIndividualRecording(recPath, recording, 1, "opus", "vp8", true); - - } - @Test @DisplayName("Record cross-browser audio-only and video-only") void audioOnlyVideoOnlyRecordTest() throws Exception { @@ -3062,12 +2794,11 @@ public class OpenViduTestAppE2eTest { **/ body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); - body = "{'session': 'CUSTOM_SESSION_ID'}"; + body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}"; res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String tokenAConnectionId = res.get("connectionId").getAsString(); final String tokenA = res.get("token").getAsString(); res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); - final String tokenB = res.get("token").getAsString(); final String tokenBConnectionId = res.get("connectionId").getAsString(); user.getDriver().findElement(By.id("one2one-btn")).click(); @@ -3079,15 +2810,6 @@ public class OpenViduTestAppE2eTest { tokenInput.clear(); tokenInput.sendKeys(tokenA); - user.getDriver().findElement(By.id("save-btn")).click(); - Thread.sleep(1000); - user.getDriver().findElement(By.id("session-settings-btn-1")).click(); - Thread.sleep(1000); - - // Set token 2 - tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); - tokenInput.clear(); - tokenInput.sendKeys(tokenB); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -3095,7 +2817,7 @@ public class OpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId, HttpStatus.SC_NO_CONTENT); - // First user should pop up invalid token + // User should pop up invalid token user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .join-btn")).sendKeys(Keys.ENTER); try { user.getWaiter().until(ExpectedConditions.alertIsPresent()); @@ -3694,295 +3416,4 @@ public class OpenViduTestAppE2eTest { } } - private void listEmptyRecordings() { - // List existing recordings (empty) - user.getDriver().findElement(By.id("list-recording-btn")).click(); - user.getWaiter() - .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Recording list []")); - } - - private ExpectedCondition waitForVideoDuration(WebElement element, int durationInSeconds) { - return new ExpectedCondition() { - @Override - public Boolean apply(WebDriver input) { - return element.getAttribute("duration").matches( - durationInSeconds - 1 + "\\.[5-9][0-9]{0,5}|" + durationInSeconds + "\\.[0-5][0-9]{0,5}"); - } - }; - } - - private static boolean checkVideoAverageRgbGreen(Map rgb) { - // GREEN color: {r < 15, g > 130, b <15} - return (rgb.get("r") < 15) && (rgb.get("g") > 130) && (rgb.get("b") < 15); - } - - private static boolean checkVideoAverageRgbGray(Map rgb) { - // GRAY color: {r < 50, g < 50, b < 50} and the absolute difference between them - // not greater than 2 - return (rgb.get("r") < 50) && (rgb.get("g") < 50) && (rgb.get("b") < 50) - && (Math.abs(rgb.get("r") - rgb.get("g")) <= 2) && (Math.abs(rgb.get("r") - rgb.get("b")) <= 2) - && (Math.abs(rgb.get("b") - rgb.get("g")) <= 2); - } - - private static boolean checkVideoAverageRgbRed(Map rgb) { - // RED color: {r > 240, g < 15, b <15} - return (rgb.get("r") > 240) && (rgb.get("g") < 15) && (rgb.get("b") < 15); - } - - private void gracefullyLeaveParticipants(int numberOfParticipants) throws Exception { - int accumulatedConnectionDestroyed = 0; - for (int j = 1; j <= numberOfParticipants; j++) { - user.getDriver().findElement(By.id("remove-user-btn")).sendKeys(Keys.ENTER); - user.getEventManager().waitUntilEventReaches("sessionDisconnected", j); - accumulatedConnectionDestroyed = (j != numberOfParticipants) - ? (accumulatedConnectionDestroyed + numberOfParticipants - j) - : (accumulatedConnectionDestroyed); - user.getEventManager().waitUntilEventReaches("connectionDestroyed", accumulatedConnectionDestroyed); - } - } - - private String getBase64Screenshot(MyUser user) throws Exception { - String screenshotBase64 = ((TakesScreenshot) user.getDriver()).getScreenshotAs(BASE64); - return "data:image/png;base64," + screenshotBase64; - } - - private boolean recordedFileFine(File file, Recording recording, - Function, Boolean> colorCheckFunction) throws IOException { - this.checkMultimediaFile(file, recording.hasAudio(), recording.hasVideo(), recording.getDuration(), - recording.getResolution(), "aac", "h264", true); - - boolean isFine = false; - Picture frame; - try { - // Get a frame at 75% duration and check that it has the expected color - frame = FrameGrab.getFrameAtSec(file, (double) (recording.getDuration() * 0.75)); - BufferedImage image = AWTUtil.toBufferedImage(frame); - Map colorMap = this.averageColor(image); - - String realResolution = image.getWidth() + "x" + image.getHeight(); - Assert.assertEquals( - "Resolution (" + recording.getResolution() - + ") of recording entity is not equal to real video resolution (" + realResolution + ")", - recording.getResolution(), realResolution); - - log.info("Recording map color: {}", colorMap.toString()); - log.info("Recording frame below"); - System.out.println(bufferedImageToBase64PngString(image)); - isFine = colorCheckFunction.apply(colorMap); - } catch (IOException | JCodecException e) { - log.warn("Error getting frame from video recording: {}", e.getMessage()); - isFine = false; - } - return isFine; - } - - private boolean recordedGreenFileFine(File file, Recording recording) throws IOException { - return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbGreen); - } - - private boolean recordedRedFileFine(File file, Recording recording) throws IOException { - return this.recordedFileFine(file, recording, OpenViduTestAppE2eTest::checkVideoAverageRgbRed); - } - - private String bufferedImageToBase64PngString(BufferedImage image) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - String imageString = null; - try { - ImageIO.write(image, "png", bos); - byte[] imageBytes = bos.toByteArray(); - imageString = "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes); - bos.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return imageString; - } - - private void checkIndividualRecording(String recPath, Recording recording, int numberOfVideoFiles, - String audioDecoder, String videoDecoder, boolean checkAudio) throws IOException { - - // Should be only 2 files: zip and metadata - File folder = new File(recPath); - Assert.assertEquals("There are more than 2 files (ZIP and metadata) inside individual recording folder " - + recPath + ": " + Arrays.toString(folder.listFiles()), 2, folder.listFiles().length); - - File file1 = new File(recPath + recording.getName() + ".zip"); - File file2 = new File(recPath + ".recording." + recording.getId()); - - Assert.assertTrue("File " + file1.getAbsolutePath() + " does not exist or is empty", - file1.exists() && file1.length() > 0); - Assert.assertTrue("File " + file2.getAbsolutePath() + " does not exist or is empty", - file2.exists() && file2.length() > 0); - - List unzippedWebmFiles = new Unzipper().unzipFile(recPath, recording.getName() + ".zip"); - - Assert.assertEquals("Expecting " + numberOfVideoFiles + " videos inside ZIP file but " - + unzippedWebmFiles.size() + " found: " + unzippedWebmFiles.toString(), numberOfVideoFiles, - unzippedWebmFiles.size()); - - File jsonSyncFile = new File(recPath + recording.getName() + ".json"); - Assert.assertTrue("JSON sync file " + jsonSyncFile.getAbsolutePath() + "does not exist or is empty", - jsonSyncFile.exists() && jsonSyncFile.length() > 0); - - JsonObject jsonSyncMetadata; - try { - Gson gson = new Gson(); - JsonReader reader = new JsonReader(new FileReader(jsonSyncFile)); - jsonSyncMetadata = gson.fromJson(reader, JsonObject.class); - } catch (Exception e) { - log.error("Cannot read JSON sync metadata file from {}. Error: {}", jsonSyncFile.getAbsolutePath(), - e.getMessage()); - Assert.fail("Cannot read JSON sync metadata file from " + jsonSyncFile.getAbsolutePath()); - return; - } - - long totalFileSize = 0; - JsonArray syncArray = jsonSyncMetadata.get("files").getAsJsonArray(); - for (File webmFile : unzippedWebmFiles) { - totalFileSize += webmFile.length(); - - Assert.assertTrue("WEBM file " + webmFile.getAbsolutePath() + " does not exist or is empty", - webmFile.exists() && webmFile.length() > 0); - - double durationInSeconds = 0; - boolean found = false; - for (int i = 0; i < syncArray.size(); i++) { - JsonObject j = syncArray.get(i).getAsJsonObject(); - if (webmFile.getName().contains(j.get("streamId").getAsString())) { - durationInSeconds = (double) (j.get("endTimeOffset").getAsDouble() - - j.get("startTimeOffset").getAsDouble()) / 1000; - found = true; - break; - } - } - - Assert.assertTrue("Couldn't find in JSON sync object information for webm file " + webmFile.getName(), - found); - - log.info("Duration of {} according to sync metadata json file: {} s", webmFile.getName(), - durationInSeconds); - this.checkMultimediaFile(webmFile, recording.hasAudio(), recording.hasVideo(), durationInSeconds, - recording.getResolution(), audioDecoder, videoDecoder, checkAudio); - webmFile.delete(); - } - - Assert.assertEquals("Size of recording entity (" + recording.getSessionId() - + ") is not equal to real file size (" + totalFileSize + ")", recording.getSize(), totalFileSize); - - jsonSyncFile.delete(); - } - - private void checkMultimediaFile(File file, boolean hasAudio, boolean hasVideo, double duration, String resolution, - String audioDecoder, String videoDecoder, boolean checkAudio) throws IOException { - // Check tracks, duration, resolution, framerate and decoders - MultimediaFileMetadata metadata = new MultimediaFileMetadata(file.getAbsolutePath()); - - if (hasVideo) { - if (checkAudio) { - if (hasAudio) { - Assert.assertTrue("Media file " + file.getAbsolutePath() + " should have audio", - metadata.hasAudio() && metadata.hasVideo()); - Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); - } else { - Assert.assertTrue("Media file " + file.getAbsolutePath() + " should have video", - metadata.hasVideo()); - Assert.assertFalse(metadata.hasAudio()); - } - } - if (resolution != null) { - Assert.assertEquals(resolution, metadata.getVideoWidth() + "x" + metadata.getVideoHeight()); - } - Assert.assertTrue(metadata.getVideoDecoder().toLowerCase().contains(videoDecoder)); - } else if (hasAudio && checkAudio) { - Assert.assertTrue(metadata.hasAudio()); - Assert.assertFalse(metadata.hasVideo()); - Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); - } else { - Assert.fail("Cannot check a file witho no audio and no video"); - } - // Check duration with 1 decimal precision - DecimalFormat df = new DecimalFormat("#0.0"); - df.setRoundingMode(RoundingMode.UP); - log.info("Duration of {} according to ffmpeg: {} s", file.getName(), metadata.getDuration()); - log.info("Duration of {} according to 'duration' property: {} s", file.getName(), duration); - log.info("Difference in s duration: {}", Math.abs(metadata.getDuration() - duration)); - final double difference = 10; - Assert.assertTrue( - "Difference between recording entity duration (" + duration + ") and real video duration (" - + metadata.getDuration() + ") is greater than " + difference + " in file " + file.getName(), - Math.abs((metadata.getDuration() - duration)) < difference); - } - - private boolean thumbnailIsFine(File file, Function, Boolean> colorCheckFunction) { - boolean isFine = false; - BufferedImage image = null; - try { - image = ImageIO.read(file); - } catch (IOException e) { - log.error(e.getMessage()); - return false; - } - log.info("Recording thumbnail dimensions: {}x{}", image.getWidth(), image.getHeight()); - Map colorMap = this.averageColor(image); - log.info("Thumbnail map color: {}", colorMap.toString()); - isFine = colorCheckFunction.apply(colorMap); - return isFine; - } - - private Map averageColor(BufferedImage bi) { - int x0 = 0; - int y0 = 0; - int w = bi.getWidth(); - int h = bi.getHeight(); - int x1 = x0 + w; - int y1 = y0 + h; - long sumr = 0, sumg = 0, sumb = 0; - for (int x = x0; x < x1; x++) { - for (int y = y0; y < y1; y++) { - Color pixel = new Color(bi.getRGB(x, y)); - sumr += pixel.getRed(); - sumg += pixel.getGreen(); - sumb += pixel.getBlue(); - } - } - int num = w * h; - Map colorMap = new HashMap<>(); - colorMap.put("r", (long) (sumr / num)); - colorMap.put("g", (long) (sumg / num)); - colorMap.put("b", (long) (sumb / num)); - return colorMap; - } - - private void startKms() { - log.info("Starting KMS"); - commandLine.executeCommand("/usr/bin/kurento-media-server &>> /kms.log &"); - } - - private void stopKms() { - log.info("Stopping KMS"); - commandLine.executeCommand("kill -9 $(pidof kurento-media-server)"); - } - - private void restartKms() { - this.stopKms(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - this.startKms(); - } - - private void checkDockerContainerRunning(String imageName, int amount) { - int number = Integer.parseInt(commandLine.executeCommand("docker ps | grep " + imageName + " | wc -l")); - Assert.assertEquals("Wrong number of Docker containers for image " + imageName + " running", amount, number); - } - - private void removeAllRecordingContiners() { - commandLine.executeCommand("docker ps -a | awk '{ print $1,$2 }' | grep " + RECORDING_IMAGE - + " | awk '{print $1 }' | xargs -I {} docker rm -f {}"); - } - } From b479cb2bac6a9ea57f477c16cc877c41483484ec Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 12:12:55 +0200 Subject: [PATCH 095/435] openvidu-test-browsers: fix CustomHttpClient response check --- .../io/openvidu/test/browsers/utils/CustomHttpClient.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java index 1228b190..236a3b2c 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java @@ -138,14 +138,14 @@ public class CustomHttpClient { JsonObject jsonObjActual = json.get(entry.getKey()).getAsJsonObject(); // COMPARE - } catch (JsonSyntaxException e1) { + } catch (Exception e1) { try { JsonArray jsonArrayExpected = JsonParser.parseString((String) value).getAsJsonArray(); JsonArray jsonArrayActual = json.get(entry.getKey()).getAsJsonArray(); // COMPARE - } catch (JsonSyntaxException e2) { - if (((String) value) != json.get(entry.getKey()).getAsString()) { + } catch (Exception e2) { + if (!((String) value).equals(json.get(entry.getKey()).getAsString())) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value + ". Actual: " + json.get(entry.getKey()).getAsString()); } From b1801ae33cb53bc956b1fb12cd22f30ada9139b7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 12:13:55 +0200 Subject: [PATCH 096/435] openvidu-testapp: allow force publishing independently of role --- .../session-properties-dialog.component.html | 12 ++++++++++-- .../session-properties-dialog.component.ts | 4 +++- .../openvidu-instance.component.html | 3 +++ .../openvidu-instance.component.ts | 19 ++++++++++++++++--- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index b0d1b333..98f49ec0 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -108,7 +108,8 @@
- Record + Record +
@@ -117,6 +118,13 @@
+ +
+ Force + publishing + +
+ @@ -124,6 +132,6 @@ + [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, customToken: customToken, forcePublishing: forcePublishing, tokenOptions: generateTokenOptions()}">SAVE diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts index b7427ed2..e58d9496 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts @@ -14,6 +14,7 @@ export class SessionPropertiesDialogComponent { turnConf: string; manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; + forcePublishing: boolean = false; tokenOptions: TokenOptions; filterName = 'GStreamerFilter'; @@ -29,8 +30,9 @@ export class SessionPropertiesDialogComponent { this.sessionProperties = data.sessionProperties; this.turnConf = data.turnConf; this.manualTurnConf = data.manualTurnConf; - this.tokenOptions = data.tokenOptions; this.customToken = data.customToken; + this.forcePublishing = data.forcePublishing; + this.tokenOptions = data.tokenOptions; } enumToArray(enumerator: any) { diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html index 8014c7ea..4e1e16ef 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html @@ -107,6 +107,9 @@
{{sessionName}}
+ diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 5184a4db..9eb3a466 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -127,6 +127,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { turnConf = 'auto'; manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; + forcePublishing: boolean; tokenOptions: TokenOptions = { role: OpenViduRole.PUBLISHER, record: true, @@ -141,6 +142,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { events: OpenViduEvent[] = []; + republishPossible: boolean = false; openviduError: any; constructor( @@ -234,7 +236,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { .then(() => { this.changeDetector.detectChanges(); - if (this.publishTo && this.session.capabilities.publish) { + if (this.publishTo && this.session.capabilities.publish || this.forcePublishing) { // this.asyncInitPublisher(); this.syncInitPublisher(); } @@ -493,9 +495,14 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.publisher.subscribeToRemote(); } - this.session.publish(this.publisher).catch((error: OpenViduError) => { + this.session.publish(this.publisher).then(() => { + this.republishPossible = false; + }).catch((error: OpenViduError) => { console.error(error); + alert(error.name + ": " + error.message); + this.republishPossible = true; this.session.unpublish(this.publisher); + delete this.publisher; }); } @@ -558,7 +565,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { turnConf: this.turnConf, manualTurnConf: this.manualTurnConf, customToken: this.customToken, - tokenOptions: this.tokenOptions + forcePublishing: this.forcePublishing, + tokenOptions: this.tokenOptions, }, width: '450px' }); @@ -572,6 +580,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.turnConf = result.turnConf; this.manualTurnConf = result.manualTurnConf; this.customToken = result.customToken; + this.forcePublishing = result.forcePublishing; this.tokenOptions = result.tokenOptions; } document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused'); @@ -715,4 +724,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.publisherProperties.videoSource !== 'screen'); } + republishAfterError() { + this.syncInitPublisher(); + } + } From c259880c8539737ddcb0542aa2449f7fa7fa07b4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 13:08:25 +0200 Subject: [PATCH 097/435] openvidu-test-e2e: update Pro test for openvidu-java-client --- .../test/e2e/OpenViduProTestAppE2eTest.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 00774e0f..74d594dc 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -24,8 +24,13 @@ import com.google.gson.JsonObject; import com.google.gson.stream.JsonReader; import com.mashape.unirest.http.HttpMethod; +import io.openvidu.java.client.Connection; import io.openvidu.java.client.OpenVidu; +import io.openvidu.java.client.OpenViduHttpException; +import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; +import io.openvidu.java.client.Session; +import io.openvidu.java.client.TokenOptions; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; @@ -211,6 +216,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } Thread.sleep(500); + // Test with REST API restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':false}", HttpStatus.SC_BAD_REQUEST); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, @@ -218,12 +224,36 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER',record:'WRONG'}", HttpStatus.SC_BAD_REQUEST); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'SUBSCRIBER','record':true}", HttpStatus.SC_NO_CONTENT); + "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_NO_CONTENT); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_NO_CONTENT); + // Test with openvidu-java-client + OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); + OV.fetch(); + Session session = OV.getActiveSessions().get(0); + try { + session.updateConnection("WRONG_CONNECTION_ID", new TokenOptions.Builder().build()); + Assert.fail("Expected OpenViduHttpException exception"); + } catch (OpenViduHttpException exception) { + Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); + } + Connection connection = session.updateConnection(tokenConnectionId, + new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build()); + Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); + Assert.assertTrue("Wrong record in Connection object", connection.record()); + connection = session.updateConnection(tokenConnectionId, + new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); + connection = session.updateConnection(tokenConnectionId, + new TokenOptions.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); + Assert.assertFalse("Wrong record in Connection object", connection.record()); + Assert.assertTrue("Wrong data in Connection object", connection.getServerData().isEmpty()); + user.getEventManager().resetEventThread(); user.getWaiter().until(ExpectedConditions.elementToBeClickable(By.cssSelector(".republish-error-btn"))); From 98a35ab6ecf40a119fe9a011274cf249239772a4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 7 Oct 2020 13:11:31 +0200 Subject: [PATCH 098/435] openvidu-node-client: TypeDoc update --- openvidu-browser/src/OpenVidu/OpenVidu.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 49f028e7..d889901c 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -660,6 +660,7 @@ export class OpenVidu { * - `iceServers`: set custom STUN/TURN servers to be used by OpenVidu Browser * - `screenShareChromeExtension`: url to a custom screen share extension for Chrome to be used instead of the default one, based on ours [https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension](https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension) * - `publisherSpeakingEventsOptions`: custom configuration for the [[PublisherSpeakingEvent]] feature and the [StreamManagerEvent.streamAudioVolumeChange](/en/stable/api/openvidu-browser/classes/streammanagerevent.html) feature + * - `forceMediaReconnectionAfterNetworkDrop`: always force WebRTC renegotiation of all the streams of a client after a network loss and reconnection. This can help reducing frozen videos in low quality networks. * * Call this method to override previous values at any moment. */ From 6ea52fe0615d7b8b7c57882dd47780a61caf74bc Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 7 Oct 2020 21:08:14 +0200 Subject: [PATCH 099/435] deployment-openvidu-pro: Easier configuration for s3 recordings --- ...penvidu-server-pro-no-market.yaml.template | 56 +++++++++++-------- .../docker-compose/openvidu-server-pro/.env | 12 ++-- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index f62256b5..bb527d30 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -42,16 +42,20 @@ Parameters: Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications" Type: String - RecordingStorage: - Description: "If 's3', recordings will be stored in a S3 bucket" + Recording: + Description: | + If 'disabled', recordings will not be active. + If 'local' recordings will be saved in EC2 instance locally. + If 's3', recordings will be stored in a S3 bucket" Type: String AllowedValues: + - disabled - local - s3 Default: local S3RecordingsBucketName: - Description: "If RecordingStorage is 's3', this will be the name of s3 bucket to store recordings" + Description: "S3 Bucket Name" Type: String # OpenVidu Configuration @@ -224,7 +228,10 @@ Metadata: - OpenViduLicense - OpenViduSecret - MediaNodesStartNumber - - RecordingStorage + - Label: + default: OpenVidu Recording Configuration + Parameters: + - Recording - S3RecordingsBucketName - Label: default: Elasticsearch and Kibana configuration @@ -261,8 +268,8 @@ Metadata: default: "URL to the key file (owncert)" LetsEncryptEmail: default: "Email for Let's Encrypt (letsencrypt)" - RecordingStorage: - default: "Recording storage" + Recording: + default: "OpenVidu Recording" S3RecordingsBucketName: default: "S3 Bucket where recordings will be stored" # OpenVidu configuration @@ -294,20 +301,22 @@ Metadata: default: "Deploy OpenVidu Call application" Conditions: - WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ""] ] - PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ] - RecordingStorageIsS3: !Equals [!Ref RecordingStorage, "s3" ] - S3RecordingsBucketNamePresent: !Not [ !Equals [!Ref S3RecordingsBucketName, ""] ] - CreateS3Bucket: !And [ !Equals [!Ref RecordingStorage, "s3" ], !Equals [!Ref S3RecordingsBucketName, ""] ] + WhichCertPresent: !Not [ !Equals [!Ref WhichCert, ''] ] + PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ''] ] + RecordingStorageIsS3: !Equals [ !Ref Recording, 's3' ] + CreateS3Bucket: !And + - !Equals [!Ref Recording, 's3' ] + - !Equals [!Ref S3RecordingsBucketName, ''] Rules: - ValidateParametersS3Local: + + RecordingValidation: RuleCondition: - Fn::Equals: [!Ref RecordingStorage, "local" ] + Fn::Equals: [!Ref Recording, 'disabled' ] Assertions: - - AssertDescription: If Recording Storage is 'local', you don't need to define an S3 bucket + - AssertDescription: If recording Storage is 'disabled', you don't need to specify a S3 bucket. Assert: - Fn::Equals: [!Ref S3RecordingsBucketName, ""] + Fn::Equals: [ !Ref S3RecordingsBucketName, "" ] Resources: @@ -353,9 +362,9 @@ Resources: Resource: - Fn::If: # Get bucket name depending if the user defines a bucket name or not - - S3RecordingsBucketNamePresent - - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName, '/*'] ] + - CreateS3Bucket - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings', '/*'] ] + - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName, '/*'] ] - Ref: AWS::NoValue - Fn::If: # Only apply this policy if S3 is configured @@ -366,9 +375,9 @@ Resources: Resource: - Fn::If: # Get bucket name depending if the user defines a bucket name or not - - S3RecordingsBucketNamePresent - - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName ] ] + - CreateS3Bucket - !Join [ "", [ 'arn:aws:s3:::', !Ref AWS::StackName, '-recordings' ] ] + - !Join [ "", [ 'arn:aws:s3:::', !Ref S3RecordingsBucketName ] ] - Ref: AWS::NoValue - Fn::If: # Only apply this policy if S3 is configured @@ -393,7 +402,7 @@ Resources: S3bucket: Type: 'AWS::S3::Bucket' Properties: - BucketName: !Join [ "", [ !Ref 'AWS::StackName', '-recordings' ] ] + BucketName: !Join ["" , [ !Ref AWS::StackName, '-recordings' ] ] AccessControl: Private PublicAccessBlockConfiguration: BlockPublicAcls: true @@ -486,8 +495,9 @@ Resources: fi # S3 Configuration - if [ "${RecordingStorage}" == "s3" ]; then - sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=s3/" $WORKINGDIR/.env + if [ "${Recording}" != "disabled" ]; then + sed -i "s/OPENVIDU_RECORDING=false/OPENVIDU_RECORDING=true/" $WORKINGDIR/.env + sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=${Recording}/" $WORKINGDIR/.env if [ ! -z "${S3RecordingsBucketName}" ]; then sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}/" $WORKINGDIR/.env else @@ -495,7 +505,7 @@ Resources: fi fi - kmsAmi: !FindInMap [KMSAMIMAP, !Ref 'AWS::Region', AMI] - s3BucketName: !Join [ "", [ !Ref 'AWS::StackName', '-recordings' ] ] + s3BucketName: !Join ["", [ !Ref AWS::StackName, '-recordings' ] ] mode: "000755" owner: "root" group: "root" diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 3cb782ae..912e59d2 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -132,12 +132,6 @@ OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams # For example 192.168.1.101 # OPENVIDU_PRO_PRIVATE_IP= -# Whether to enable recording module or not -OPENVIDU_RECORDING=false - -# Use recording module with debug mode. -OPENVIDU_RECORDING_DEBUG=false - # Where to store recording files. Can be “local” (local storage) or “s3” (AWS bucket). # You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it. #OPENVIDU_PRO_RECORDING_STORAGE= @@ -166,6 +160,12 @@ OPENVIDU_RECORDING_DEBUG=false # This property is only taken into account if OPENVIDU_PRO_RECORDING_STORAGE=s3 # OPENVIDU_PRO_AWS_REGION= +# Whether to enable recording module or not +OPENVIDU_RECORDING=false + +# Use recording module with debug mode. +OPENVIDU_RECORDING_DEBUG=false + # Openvidu Folder Record used for save the openvidu recording videos. Change it # with the folder you want to use from your host. OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings From 38270cc315276b980d14dc86d4c8635794beef84 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 7 Oct 2020 21:34:38 +0200 Subject: [PATCH 100/435] deployment-openvidu-pro: Show error if s3 bucket is defined and 'Recording' is 'local' or 'disabled' --- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index bb527d30..8ca07c01 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -312,7 +312,7 @@ Rules: RecordingValidation: RuleCondition: - Fn::Equals: [!Ref Recording, 'disabled' ] + Fn::Or: [ !Equals [!Ref Recording, 'disabled' ], !Equals [!Ref Recording, 'local' ] ] Assertions: - AssertDescription: If recording Storage is 'disabled', you don't need to specify a S3 bucket. Assert: From 08cc2aec1699efa7731bbba48a4b66738ff36f67 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 7 Oct 2020 22:02:27 +0200 Subject: [PATCH 101/435] deployment-openvidu-pro: Typos and remove repeated parameter .env --- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 2 +- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 8ca07c01..a1472420 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -494,7 +494,7 @@ Resources: rm $WORKINGDIR/docker-compose.override.yml fi - # S3 Configuration + # Recording Configuration if [ "${Recording}" != "disabled" ]; then sed -i "s/OPENVIDU_RECORDING=false/OPENVIDU_RECORDING=true/" $WORKINGDIR/.env sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=${Recording}/" $WORKINGDIR/.env diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 912e59d2..6cf0d1ae 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -141,10 +141,6 @@ OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams # if OPENVIDU_PRO_RECORDING_STORAGE=s3 #OPENVIDU_PRO_AWS_S3_BUCKET= -# AWS credentials access key. Must have read and write permissions over the bucket. -# If not provided, then the internal S3 client will try to use the default AWS credentials -# of the machine (if available). This property is only taken into account if -# OPENVIDU_PRO_RECORDING_STORAGE=s3 # If you're instance has a role which has access to read # and write into the s3 bucket, you don't need this parameter # OPENVIDU_PRO_AWS_ACCESS_KEY= From 178aae9f20e98333df1ebe6ba79150d1fa70155d Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 7 Oct 2020 22:06:24 +0200 Subject: [PATCH 102/435] deployment-openvidu-pro: Add missing rule GetBucketLocation in OpenViduManageEC2Policy --- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index a1472420..752eb10a 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -372,6 +372,7 @@ Resources: - Effect: Allow Action: - 's3:ListBucket' + - 's3:GetBucketLocation' Resource: - Fn::If: # Get bucket name depending if the user defines a bucket name or not From 3499b973013381ff669095406274233583fe2b77 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 7 Oct 2020 23:07:27 +0200 Subject: [PATCH 103/435] deployment-openvidu-pro: Only replace OPENVIDU_PRO_AWS_S3_BUCKET with created s3 bucket name if Recording is s3 --- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 752eb10a..9b913da4 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -314,7 +314,7 @@ Rules: RuleCondition: Fn::Or: [ !Equals [!Ref Recording, 'disabled' ], !Equals [!Ref Recording, 'local' ] ] Assertions: - - AssertDescription: If recording Storage is 'disabled', you don't need to specify a S3 bucket. + - AssertDescription: If recording Storage is 'disabled' or 'local', you don't need to specify a S3 bucket. Assert: Fn::Equals: [ !Ref S3RecordingsBucketName, "" ] @@ -501,7 +501,7 @@ Resources: sed -i "s/#OPENVIDU_PRO_RECORDING_STORAGE=/OPENVIDU_PRO_RECORDING_STORAGE=${Recording}/" $WORKINGDIR/.env if [ ! -z "${S3RecordingsBucketName}" ]; then sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${S3RecordingsBucketName}/" $WORKINGDIR/.env - else + elif [ "${Recording}" == "s3" ]; then sed -i "s/#OPENVIDU_PRO_AWS_S3_BUCKET=/OPENVIDU_PRO_AWS_S3_BUCKET=${s3BucketName}/" $WORKINGDIR/.env fi fi From c24606aca719a42b6a132c98dabe40ec7a85109c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 14:33:14 +0200 Subject: [PATCH 104/435] openvidu-server: Session and Token objects REST API --- .../io/openvidu/server/core/Participant.java | 1 + .../java/io/openvidu/server/core/Session.java | 3 +- .../openvidu/server/core/SessionManager.java | 5 ++- .../java/io/openvidu/server/core/Token.java | 23 +++++++++- .../openvidu/server/core/TokenGenerator.java | 2 +- .../kurento/core/KurentoTokenOptions.java | 25 +++++++++++ .../server/rest/SessionRestController.java | 45 ++----------------- ...essionGarbageCollectorIntegrationTest.java | 2 +- .../test/e2e/OpenViduTestAppE2eTest.java | 29 +++++++----- 9 files changed, 75 insertions(+), 60 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index b8906a5c..a71eaedd 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -232,6 +232,7 @@ public class Participant { public JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("connectionId", this.participantPublicId); + json.addProperty("session", this.sessionId); json.addProperty("createdAt", this.createdAt); json.addProperty("location", this.location != null ? this.location.toString() : "unknown"); json.addProperty("platform", this.platform); 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 6feb9736..c521686e 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 @@ -175,7 +175,7 @@ public class Session implements SessionInterface { Iterator> iterator = this.tokens.entrySet().iterator(); while (iterator.hasNext() && !deleted) { Entry entry = iterator.next(); - if (connectionId.equals(entry.getValue().getConnetionId())) { + if (connectionId.equals(entry.getValue().getConnectionId())) { iterator.remove(); deleted = true; } @@ -225,6 +225,7 @@ public class Session implements SessionInterface { private JsonObject sharedJson(Function toJsonFunction) { JsonObject json = new JsonObject(); json.addProperty("sessionId", this.sessionId); + json.addProperty("id", this.sessionId); // TODO: deprecated. Better use only "sessionId" json.addProperty("createdAt", this.startTime); json.addProperty("mediaMode", this.sessionProperties.mediaMode().name()); json.addProperty("recordingMode", this.sessionProperties.recordingMode().name()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 6ce7c2c3..df58dd20 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -308,7 +308,8 @@ public abstract class SessionManager { } public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception { - Token tokenObj = new Token(token, OpenViduRole.PUBLISHER, serverMetadata != null ? serverMetadata : "", true, + Token tokenObj = new Token(token, session.getSessionId(), OpenViduRole.PUBLISHER, + serverMetadata != null ? serverMetadata : "", true, this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null); session.storeToken(tokenObj); session.showTokens("Token created for insecure user"); @@ -357,7 +358,7 @@ public abstract class SessionManager { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnetionId(), sessionId, + Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnectionId(), sessionId, token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index d5ed9ca6..5e707316 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -19,6 +19,8 @@ package io.openvidu.server.core; import org.apache.commons.lang3.RandomStringUtils; +import com.google.gson.JsonObject; + import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.coturn.TurnCredentials; import io.openvidu.server.kurento.core.KurentoTokenOptions; @@ -26,6 +28,7 @@ import io.openvidu.server.kurento.core.KurentoTokenOptions; public class Token { private String token; + private String sessionId; private OpenViduRole role; private String serverMetadata = ""; private boolean record; @@ -35,9 +38,10 @@ public class Token { private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); - public Token(String token, OpenViduRole role, String serverMetadata, boolean record, + public Token(String token, String sessionId, OpenViduRole role, String serverMetadata, boolean record, TurnCredentials turnCredentials, KurentoTokenOptions kurentoTokenOptions) { this.token = token; + this.sessionId = sessionId; this.role = role; this.serverMetadata = serverMetadata; this.record = record; @@ -73,7 +77,7 @@ public class Token { return kurentoTokenOptions; } - public String getConnetionId() { + public String getConnectionId() { return connectionId; } @@ -85,6 +89,21 @@ public class Token { this.record = record; } + public JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("token", this.getToken()); + json.addProperty("id", this.getToken()); + json.addProperty("connectionId", this.getConnectionId()); + json.addProperty("session", this.sessionId); + json.addProperty("role", this.getRole().toString()); + json.addProperty("data", this.getServerMetadata()); + json.addProperty("record", this.record()); + if (this.getKurentoTokenOptions() != null) { + json.add("kurentoOptions", this.getKurentoTokenOptions().toJson()); + } + return json; + } + @Override public String toString() { if (this.role != null) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 540f8e94..0c5f9b84 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -56,6 +56,6 @@ public class TokenGenerator { token += "&turnCredential=" + turnCredentials.getCredential(); } } - return new Token(token, role, serverMetadata, record, turnCredentials, kurentoTokenOptions); + return new Token(token, sessionId, role, serverMetadata, record, turnCredentials, kurentoTokenOptions); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java index cc785116..a7b21da8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java @@ -79,4 +79,29 @@ public class KurentoTokenOptions { return this.allowedFilters.containsKey(filterType); } + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (this.getVideoMaxRecvBandwidth() != null) { + json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth()); + } + if (this.getVideoMinRecvBandwidth() != null) { + json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth()); + } + if (this.getVideoMaxSendBandwidth() != null) { + json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth()); + } + if (this.getVideoMinSendBandwidth() != null) { + json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth()); + } + if (this.getAllowedFilters().length > 0) { + JsonArray filtersJson = new JsonArray(); + String[] filters = this.getAllowedFilters(); + for (String filter : filters) { + filtersJson.add(filter); + } + json.add("allowedFilters", filtersJson); + } + return json; + } + } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 7cc2bac3..75539422 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -176,11 +176,9 @@ public class SessionRestController { Session sessionNotActive = sessionManager.storeSessionNotActive(sessionId, sessionProperties); log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream() .map(Session::getSessionId).collect(Collectors.toList()).toString()); - JsonObject responseJson = new JsonObject(); - responseJson.addProperty("id", sessionNotActive.getSessionId()); - responseJson.addProperty("createdAt", sessionNotActive.getStartTime()); - return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + return new ResponseEntity<>(sessionNotActive.toJson().toString(), RestUtils.getResponseHeaders(), + HttpStatus.OK); } @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET) @@ -396,44 +394,7 @@ public class SessionRestController { if (session.closingLock.readLock().tryLock()) { try { Token token = sessionManager.newToken(session, role, metadata, record, kurentoTokenOptions); - - JsonObject responseJson = new JsonObject(); - responseJson.addProperty("id", token.getToken()); - responseJson.addProperty("connectionId", token.getConnetionId()); - responseJson.addProperty("session", sessionId); - responseJson.addProperty("role", role.toString()); - responseJson.addProperty("data", metadata); - responseJson.addProperty("record", record); - responseJson.addProperty("token", token.getToken()); - - if (kurentoOptions != null) { - JsonObject kurentoOptsResponse = new JsonObject(); - if (kurentoTokenOptions.getVideoMaxRecvBandwidth() != null) { - kurentoOptsResponse.addProperty("videoMaxRecvBandwidth", - kurentoTokenOptions.getVideoMaxRecvBandwidth()); - } - if (kurentoTokenOptions.getVideoMinRecvBandwidth() != null) { - kurentoOptsResponse.addProperty("videoMinRecvBandwidth", - kurentoTokenOptions.getVideoMinRecvBandwidth()); - } - if (kurentoTokenOptions.getVideoMaxSendBandwidth() != null) { - kurentoOptsResponse.addProperty("videoMaxSendBandwidth", - kurentoTokenOptions.getVideoMaxSendBandwidth()); - } - if (kurentoTokenOptions.getVideoMinSendBandwidth() != null) { - kurentoOptsResponse.addProperty("videoMinSendBandwidth", - kurentoTokenOptions.getVideoMinSendBandwidth()); - } - if (kurentoTokenOptions.getAllowedFilters().length > 0) { - JsonArray filters = new JsonArray(); - for (String filter : kurentoTokenOptions.getAllowedFilters()) { - filters.add(filter); - } - kurentoOptsResponse.add("allowedFilters", filters); - } - responseJson.add("kurentoOptions", kurentoOptsResponse); - } - return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + return new ResponseEntity<>(token.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (Exception e) { return this.generateErrorResponse( "Error generating token for session " + sessionId + ": " + e.getMessage(), "/tokens", diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 5e36c975..7e267ee6 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -115,7 +115,7 @@ public class SessionGarbageCollectorIntegrationTest { } private void joinParticipant(String sessionId, String token) { - Token t = new Token(token, OpenViduRole.PUBLISHER, "SERVER_METADATA", true, null, null); + Token t = new Token(token, sessionId, OpenViduRole.PUBLISHER, "SERVER_METADATA", true, null, null); String uuid = UUID.randomUUID().toString(); String participantPrivateId = "PARTICIPANT_PRIVATE_ID_" + uuid; String finalUserId = "FINAL_USER_ID_" + uuid; diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 665e1d44..87dd2a61 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -2520,6 +2520,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { log.info("REST API test"); + final String DEFAULT_JSON_SESSION = "{'sessionId':'STR','id':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); // 401 @@ -2550,11 +2552,10 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 200 body = "{'mediaMode': 'ROUTED', 'recordingMode': 'MANUAL', 'customSessionId': 'CUSTOM_SESSION_ID', 'defaultOutputMode': 'COMPOSED', 'defaultRecordingLayout': 'BEST_FIT'}"; - restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK, true, - "{'id': 'STR', 'createdAt': 0}"); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK, true, DEFAULT_JSON_SESSION); // Default values JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{}", HttpStatus.SC_OK, true, - "{'id': 'STR', 'createdAt': 0}"); + DEFAULT_JSON_SESSION); restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), HttpStatus.SC_NO_CONTENT); @@ -2564,7 +2565,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { /** GET /openvidu/api/sessions (after session created) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, - "{'sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':true}"); + DEFAULT_JSON_SESSION); restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, ImmutableMap.of("numberOfElements", new Integer(1), "content", new JsonArray())); @@ -2643,7 +2644,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 409 (RELAYED media mode) res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'mediaMode':'RELAYED'}", HttpStatus.SC_OK, - true, "{'id': 'STR', 'createdAt': 0}"); + true, DEFAULT_JSON_SESSION); body = "{'session':'" + res.get("id").getAsString() + "'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_CONFLICT); restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), @@ -2737,7 +2738,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/stream/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, - "{'sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':2,'content'" + "{'sessionId':'STR','id':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':2,'content'" + ":[{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','token':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[" + "{'createdAt':0,'streamId':'STR','mediaOptions':{'hasAudio':false,'audioActive':false,'hasVideo':false,'videoActive':false,'typeOfVideo':'STR','frameRate':0," + "'videoDimensions':'STR','filter':{}}}],'subscribers':[{'createdAt':0,'streamId':'STR','publisher':'STR'}]},{'connectionId':'STR','createdAt':0,'location':'STR'," @@ -2800,16 +2801,25 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final String tokenA = res.get("token").getAsString(); res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String tokenBConnectionId = res.get("connectionId").getAsString(); + final String tokenB = res.get("token").getAsString(); user.getDriver().findElement(By.id("one2one-btn")).click(); - user.getDriver().findElement(By.id("session-settings-btn-0")).click(); - Thread.sleep(1000); // Set token 1 + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokenInput.clear(); tokenInput.sendKeys(tokenA); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + // Set token 2 + user.getDriver().findElement(By.id("session-settings-btn-1")).click(); + Thread.sleep(1000); + tokenInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); + tokenInput.clear(); + tokenInput.sendKeys(tokenB); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2835,9 +2845,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).sendKeys(Keys.ENTER); user.getEventManager().waitUntilEventReaches("connectionCreated", 1); - user.getEventManager().waitUntilEventReaches("accessAllowed", 1); - user.getEventManager().waitUntilEventReaches("streamCreated", 1); - user.getEventManager().waitUntilEventReaches("streamPlaying", 1); // connectionId should be equal to the one brought by the token Assert.assertEquals("Wrong connectionId", tokenBConnectionId, From 417d645e45cefc69d04628189f37b887c2de22f5 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 8 Oct 2020 15:43:06 +0200 Subject: [PATCH 105/435] openvidu-server: Added Network Quality support --- .../server/config/OpenviduConfig.java | 14 -------- .../io/openvidu/server/core/Participant.java | 36 +++++++++++++++++++ .../server/core/SessionEventsHandler.java | 12 +++++++ .../openvidu/server/core/SessionManager.java | 2 ++ .../kurento/core/KurentoSessionManager.java | 5 +++ .../io/openvidu/server/rpc/RpcHandler.java | 17 +++++++++ 6 files changed, 72 insertions(+), 14 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index e48d190f..a0336722 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -773,20 +773,6 @@ public class OpenviduConfig { } } - protected Double asNonNegativeDouble(String property) { - try { - Double doubleValue = Double.parseDouble(getValue(property)); - - if (doubleValue < 0) { - addError(property, "Is not a non negative double"); - } - return doubleValue; - } catch (NumberFormatException e) { - addError(property, "Is not a non negative doubleValue"); - return 0.0; - } - } - /* * This method checks all types of Internet addresses (IPv4, IPv6 and Domains) */ diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index a71eaedd..1c4fd73f 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -38,6 +38,10 @@ public class Participant { protected GeoLocation location; // Location of the participant protected String platform; // Platform used by the participant to connect to the session protected EndpointType endpointType; // Type of participant (web participant, IP cam participant...) + protected Integer videoWidth = 0; + protected Integer videoHeight = 0; + protected Boolean videoActive = false; + protected Boolean audioActive = false; protected boolean streaming = false; protected volatile boolean closed = false; @@ -141,6 +145,38 @@ public class Participant { public EndpointType getEndpointType() { return this.endpointType; } + + public Integer getVideoWidth() { + return videoWidth; + } + + public void setVideoWidth(Integer videoWidth) { + this.videoWidth = videoWidth; + } + + public Integer getVideoHeight() { + return videoHeight; + } + + public void setVideoHeight(Integer videoHeight) { + this.videoHeight = videoHeight; + } + + public Boolean isVideoActive() { + return videoActive; + } + + public void setVideoActive(Boolean videoActive) { + this.videoActive = videoActive; + } + + public Boolean isAudioActive() { + return audioActive; + } + + public void setAudioActive(Boolean audioActive) { + this.audioActive = audioActive; + } public boolean isStreaming() { return streaming; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index bee845f2..00126d74 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -558,6 +558,18 @@ public class SessionEventsHandler { } } + public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, + Boolean videoActive, Boolean audioActive) { + participant.setVideoHeight(height); + participant.setVideoWidth(width); + participant.setVideoActive(videoActive); + participant.setAudioActive(audioActive); + log.info( + "Video data of participant {} was initialized. height:{}, width:{}, isVideoActive: {}, isAudioActive: {}", + participant.getParticipantPublicId(), height, width, videoActive, audioActive); + rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); + } + public void closeRpcSession(String participantPrivateId) { this.rpcNotificationService.closeRpcSession(participantPrivateId); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index df58dd20..b4475461 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -165,6 +165,8 @@ public abstract class SessionManager { public abstract String getParticipantPrivateIdFromStreamId(String sessionId, String streamId) throws OpenViduException; + + public abstract void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, Boolean videoActive, Boolean audioActive); /** * Returns a Session given its id diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index d689cd81..81032cfb 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -1107,6 +1107,11 @@ public class KurentoSessionManager extends SessionManager { Session session = this.getSession(sessionId); return ((KurentoSession) session).getParticipantPrivateIdFromStreamId(streamId); } + + @Override + public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, Boolean videoActive, Boolean audioActive) { + sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive); + } private void applyFilterInPublisher(KurentoParticipant kParticipant, KurentoFilter filter) throws OpenViduException { diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index 7c66e35c..05f6fdf8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -165,6 +165,9 @@ public class RpcHandler extends DefaultJsonRpcHandler { case ProtocolElements.RECONNECTSTREAM_METHOD: reconnectStream(rpcConnection, request); break; + case ProtocolElements.VIDEODATA_METHOD: + updateVideoData(rpcConnection, request); + break; default: log.error("Unrecognized request {}", request); break; @@ -633,6 +636,20 @@ public class RpcHandler extends DefaultJsonRpcHandler { new JsonObject(), e); } } + + private void updateVideoData(RpcConnection rpcConnection, Request request) { + Participant participant; + try { + participant = sanityCheckOfSession(rpcConnection, "videoData"); + int height = getIntParam(request, "height"); + int width = getIntParam(request, "width"); + boolean videoActive = getBooleanParam(request, "videoActive"); + boolean audioActive = getBooleanParam(request, "audioActive"); + sessionManager.onVideoData(participant, request.getId(), height, width, videoActive, audioActive); + } catch (OpenViduException e) { + log.error("Error getting video data: {}", e.toString()); + } + } public void leaveRoomAfterConnClosed(String participantPrivateId, EndReason reason) { try { From feb5a54b420874cf8ec3ca0c070f862458e5d7b8 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 8 Oct 2020 15:43:37 +0200 Subject: [PATCH 106/435] openvidu-client: Added Network Quality support --- .../java/io/openvidu/client/internal/ProtocolElements.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index c664e8ac..a4f43166 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -95,9 +95,7 @@ public class ProtocolElements { public static final String NETWORKQUALITYCHANGED_METHOD = "networkQualityChanged"; public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId"; - public static final String NETWORKQUALITYCHANGED_NEWVALUE_PARAM = "newValue"; - public static final String NETWORKQUALITYCHANGED_OLDVALUE_PARAM = "oldValue"; - public static final String NETWORKQUALITYCHANGED_REASON_PARAM = "reason"; + public static final String NETWORKQUALITYCHANGED_QUALITYLEVEL_PARAM = "qualityLevel"; public static final String FORCEDISCONNECT_METHOD = "forceDisconnect"; public static final String FORCEDISCONNECT_CONNECTIONID_PARAM = "connectionId"; @@ -127,6 +125,8 @@ public class ProtocolElements { public static final String RECONNECTSTREAM_METHOD = "reconnectStream"; public static final String RECONNECTSTREAM_STREAM_PARAM = "stream"; public static final String RECONNECTSTREAM_SDPOFFER_PARAM = "sdpOffer"; + + public static final String VIDEODATA_METHOD = "videoData"; // ---------------------------- SERVER RESPONSES & EVENTS ----------------- From 0a34e7f2de371e4799e62ec627b38c071dabf176 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 8 Oct 2020 15:46:03 +0200 Subject: [PATCH 107/435] openvidu-browser: Updated Network Quality Event - Added sendVideoData method --- openvidu-browser/src/OpenVidu/OpenVidu.ts | 127 ++++++++++++++---- openvidu-browser/src/OpenVidu/Publisher.ts | 4 + openvidu-browser/src/OpenVidu/Session.ts | 38 +++++- .../Events/NetworkQualityChangedEvent.ts | 22 +-- openvidu-browser/src/index.ts | 1 - 5 files changed, 142 insertions(+), 50 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index d889901c..29be9863 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -183,6 +183,7 @@ export class OpenVidu { } else { this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]); publisher.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(publisher, publisher.stream, 'videoDimensions', publisher.stream.videoDimensions, { width: oldWidth, height: oldHeight }, 'deviceRotated')]); + this.session.sendVideoData(publisher); } }); clearTimeout(repeatUntilChange); @@ -334,12 +335,9 @@ export class OpenVidu { * @returns 1 if the browser supports OpenVidu, 0 otherwise */ checkSystemRequirements(): number { - const browser = platform.name; - const family = platform.os!!.family; - const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; - if (this.isIPhoneOrIPad(userAgent)) { - if (this.isIOSWithSafari(userAgent) || platform['isIonicIos']) { + if (this.isIPhoneOrIPad()) { + if (this.isIOSWithSafari() || platform['isIonicIos']) { return 1; } return 0; @@ -347,13 +345,10 @@ export class OpenVidu { // Accept: Chrome (desktop and Android), Firefox (desktop and Android), Opera (desktop and Android), // Safari (OSX and iOS), Ionic (Android and iOS), Samsung Internet Browser (Android) - if ( - (browser === 'Safari') || - (browser === 'Chrome') || (browser === 'Chrome Mobile') || - (browser === 'Firefox') || (browser === 'Firefox Mobile') || - (browser === 'Opera') || (browser === 'Opera Mobile') || - (browser === 'Android Browser') || (browser === 'Electron') || - (browser === 'Samsung Internet Mobile') || (browser === 'Samsung Internet') + if (this.isSafariBrowser() || this.isChromeBrowser() || this.isChromeMobileBrowser() || + this.isFirefoxBrowser() || this.isFirefoxMobileBrowser() || this.isOperaBrowser() || + this.isOperaMobileBrowser() || this.isAndroidBrowser() || this.isElectron() || + this.isSamsungBrowser() ) { return 1; } @@ -877,6 +872,98 @@ export class OpenVidu { return mediaStream; } + /** + * @hidden + */ + public isChromeBrowser(): boolean { + return platform.name === 'Chrome'; + } + + /** + * @hidden + */ + public isSafariBrowser(): boolean { + return platform.name === 'Safari'; + } + + /** + * @hidden + */ + public isChromeMobileBrowser(): boolean { + return platform.name === 'Chrome Mobile'; + } + + /** + * @hidden + */ + public isFirefoxBrowser(): boolean { + return platform.name === 'Firefox'; + } + + /** + * @hidden + */ + public isFirefoxMobileBrowser(): boolean { + return platform.name === 'Firefox Mobile'; + } + + /** + * @hidden + */ + public isOperaBrowser(): boolean { + return platform.name === 'Opera'; + } + + /** + * @hidden + */ + public isOperaMobileBrowser(): boolean { + return platform.name === 'Opera Mobile'; + } + + /** + * @hidden + */ + public isAndroidBrowser(): boolean { + return platform.name === 'Android Browser'; + } + + /** + * @hidden + */ + public isElectron(): boolean { + return platform.name === 'Electron'; + } + + /** + * @hidden + */ + public isSamsungBrowser(): boolean { + return platform.name === 'Samsung Internet Mobile' || platform.name === 'Samsung Internet'; + } + + /** + * @hidden + */ + public isIPhoneOrIPad(): boolean { + const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; + + const isTouchable = 'ontouchend' in document; + const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable; + const isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) && /\b(\w*Mobile\w*)\b/.test(userAgent) && isTouchable; + + return isIPad || isIPhone; + } + + /** + * @hidden + */ + public isIOSWithSafari(): boolean { + const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; + return /\b(\w*Apple\w*)\b/.test(navigator.vendor) && /\b(\w*Safari\w*)\b/.test(userAgent) + && !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent); + } + /** * @hidden */ @@ -1066,18 +1153,4 @@ export class OpenVidu { (platform.name === 'Electron' && videoSource.startsWith('screen:')) } - private isIPhoneOrIPad(userAgent): boolean { - const isTouchable = 'ontouchend' in document; - const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable; - const isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) && /\b(\w*Mobile\w*)\b/.test(userAgent) && isTouchable; - - return isIPad || isIPhone; - } - - private isIOSWithSafari(userAgent): boolean { - return /\b(\w*Apple\w*)\b/.test(navigator.vendor) && /\b(\w*Safari\w*)\b/.test(userAgent) - && !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent); - } - - -} \ No newline at end of file + } \ No newline at end of file diff --git a/openvidu-browser/src/OpenVidu/Publisher.ts b/openvidu-browser/src/OpenVidu/Publisher.ts index 60151ca6..15aa155a 100644 --- a/openvidu-browser/src/OpenVidu/Publisher.ts +++ b/openvidu-browser/src/OpenVidu/Publisher.ts @@ -142,6 +142,7 @@ export class Publisher extends StreamManager { } else { this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'audioActive', value, !value, 'publishAudio')]); this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'audioActive', value, !value, 'publishAudio')]); + this.session.sendVideoData(this.stream.streamManager); } }); } @@ -189,6 +190,7 @@ export class Publisher extends StreamManager { } else { this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoActive', value, !value, 'publishVideo')]); this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoActive', value, !value, 'publishVideo')]); + this.session.sendVideoData(this.stream.streamManager); } }); } @@ -308,6 +310,7 @@ export class Publisher extends StreamManager { mediaStream.removeTrack(removedTrack); removedTrack.stop(); mediaStream.addTrack(track); + this.session.sendVideoData(this.stream.streamManager); } return new Promise((resolve, reject) => { @@ -481,6 +484,7 @@ export class Publisher extends StreamManager { } else { this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this.stream, 'videoDimensions', this.stream.videoDimensions, oldValue, 'screenResized')]); this.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, this.stream, 'videoDimensions', this.stream.videoDimensions, oldValue, 'screenResized')]); + this.session.sendVideoData(this.stream.streamManager); } }); } diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 09f5a38a..e3b1c55b 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -37,7 +37,7 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent'; import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent'; import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent'; -import { NetworkQualityChangedEvent, NetworkQualityChangedReason } from '../OpenViduInternal/Events/NetworkQualityChangedEvent'; +import { NetworkQualityChangedEvent } from '../OpenViduInternal/Events/NetworkQualityChangedEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; @@ -378,6 +378,7 @@ export class Session extends EventDispatcher { this.connection.addStream(publisher.stream); publisher.stream.publish() .then(() => { + this.sendVideoData(publisher, 5); resolve(); }) .catch(error => { @@ -391,6 +392,7 @@ export class Session extends EventDispatcher { publisher.reestablishStreamPlayingEvent(); publisher.stream.publish() .then(() => { + this.sendVideoData(publisher, 5); resolve(); }) .catch(error => { @@ -898,6 +900,7 @@ export class Session extends EventDispatcher { break; } this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, msg.property, msg.newValue, oldValue, msg.reason)]); + this.sendVideoData(stream.streamManager); if (!!stream.streamManager) { stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]); } @@ -926,9 +929,8 @@ export class Session extends EventDispatcher { * @hidden */ onNetworkQualityChangedChanged(msg): void { - if (msg.connectionId === this.connection.connectionId) { - this.ee.emitEvent('networkQualityChanged', [new NetworkQualityChangedEvent(this, msg.newValue, msg.oldValue, msg.reason)]); + this.ee.emitEvent('networkQualityChanged', [new NetworkQualityChangedEvent(this, msg.qualityLevel)]); } } @@ -1125,6 +1127,36 @@ export class Session extends EventDispatcher { return joinParams; } + sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1) { + if( + this.openvidu.isChromeBrowser() || this.openvidu.isChromeMobileBrowser() || this.openvidu.isOperaBrowser() || + this.openvidu.isOperaMobileBrowser() || this.openvidu.isElectron() || this.openvidu.isSafariBrowser() || + this.openvidu.isAndroidBrowser() || this.openvidu.isSamsungBrowser() || + (this.openvidu.isIPhoneOrIPad() && this.openvidu.isIOSWithSafari()) + ) { + const statsRequest = setInterval(async () => { + const statsMap = await streamManager.stream.getWebRtcPeer().pc.getStats(); + statsMap.forEach((stats) => { + + if ("frameWidth" in stats) { + this.openvidu.sendRequest('videoData', { + height: stats.frameHeight, + width: stats.frameWidth, + videoActive: streamManager.stream.videoActive, + audioActive: streamManager.stream.audioActive + }, (error, response) => { + if (error) { + logger.error("Error sending 'videoData' event", error); + } + clearInterval(statsRequest); + }); + } + }); + }, intervalSeconds * 1000); + } else { + console.error('Browser ' + platform.name + ' (version ' + platform.version + ') for ' + platform.os!!.family + ' is not supported in OpenVidu for Network Quality'); + } + } /* Private methods */ diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts index 710950e0..9aa5450b 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts @@ -24,29 +24,18 @@ import { Session } from '../../OpenVidu/Session'; */ export class NetworkQualityChangedEvent extends Event { - /** - * Cause of the change on the neteotk quality event - */ - reason: NetworkQualityChangedReason; /** * New value of the property (after change, current value) */ - newValue: Object; - - /** - * Previous value of the property (before change) - */ - oldValue: Object; + qualityLevel: Object; /** * @hidden */ - constructor(target: Session, newValue: Object, oldValue: Object, reason: NetworkQualityChangedReason) { + constructor(target: Session, qualityLevel: Object) { super(false, target, 'networkQualityChanged'); - this.newValue = newValue; - this.oldValue = oldValue; - this.reason = reason; + this.qualityLevel = qualityLevel; } /** @@ -56,8 +45,3 @@ export class NetworkQualityChangedEvent extends Event { callDefaultBehavior() { } } - -export enum NetworkQualityChangedReason { - ABOVE_MAX = "above_max", - BELOW_MIN = "below_min" -} diff --git a/openvidu-browser/src/index.ts b/openvidu-browser/src/index.ts index d9c509ae..b36d1958 100644 --- a/openvidu-browser/src/index.ts +++ b/openvidu-browser/src/index.ts @@ -24,7 +24,6 @@ export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent'; export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent'; export { FilterEvent } from './OpenViduInternal/Events/FilterEvent'; export { NetworkQualityChangedEvent } from './OpenViduInternal/Events/NetworkQualityChangedEvent'; -export { NetworkQualityChangedReason } from './OpenViduInternal/Events/NetworkQualityChangedEvent'; export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities'; export { Device } from './OpenViduInternal/Interfaces/Public/Device'; From 3c80cbfede18d9110761bac9b286347afef37ed7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 17:37:17 +0200 Subject: [PATCH 108/435] openvidu-testapp: update to support new Session.updateConnection method --- .../filter-dialog.component.html | 10 +-- .../session-api-dialog.component.css | 1 + .../session-api-dialog.component.html | 71 +++++++++++++------ .../session-api-dialog.component.ts | 26 +++++-- .../openvidu-instance.component.ts | 45 +++++++----- 5 files changed, 105 insertions(+), 48 deletions(-) diff --git a/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.html index bd7a5f8d..23fa0dcd 100644 --- a/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/filter-dialog/filter-dialog.component.html @@ -5,19 +5,19 @@ - + - + - + - + @@ -34,7 +34,7 @@

Filter events

- + diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.css b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.css index 7df97a20..5fc144c0 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.css +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.css @@ -31,6 +31,7 @@ mat-dialog-content button { .inner-text-input { margin-left: 9px; + width: 42%; } #rec-properties-btn { diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html index cc50ca9d..a7ef54ed 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html @@ -6,23 +6,44 @@ -
- - - -
- -
+ + + + + + + + +
+ Record + + + + + {{ enumerator }} + + + +
+
+ + + + +
+ -
@@ -37,7 +58,9 @@
-
+
@@ -45,17 +68,20 @@ - +
Has audio Has video - - + +
@@ -63,8 +89,10 @@
- - + +
@@ -73,6 +101,7 @@ - +
diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts index f1acab0e..2fffa7fd 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout } from 'openvidu-node-client'; +import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout, TokenOptions, OpenViduRole } from 'openvidu-node-client'; @Component({ selector: 'app-session-api-dialog', @@ -14,16 +14,23 @@ export class SessionApiDialogComponent { session: SessionAPI; sessionId: string; recordingId: string; - resourceId: string; + connectionId: string; + streamId: string; response: string; recordingProperties: RecordingProperties; recMode = Recording.OutputMode; recLayouts = RecordingLayout; + openviduRoles = OpenViduRole; customLayout = ''; recPropertiesIcon = 'add_circle'; showRecProperties = false; + tokenOptions: TokenOptions = { + record: true, + role: OpenViduRole.PUBLISHER + }; + constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data) { this.OV = data.openVidu; @@ -145,7 +152,7 @@ export class SessionApiDialogComponent { forceDisconnect() { console.log('Forcing disconnect'); - this.session.forceDisconnect(this.resourceId) + this.session.forceDisconnect(this.connectionId) .then(() => { this.response = 'User disconnected'; }) @@ -156,7 +163,7 @@ export class SessionApiDialogComponent { forceUnpublish() { console.log('Forcing unpublish'); - this.session.forceUnpublish(this.resourceId) + this.session.forceUnpublish(this.streamId) .then(() => { this.response = 'Stream unpublished'; }) @@ -165,6 +172,17 @@ export class SessionApiDialogComponent { }); } + updateConnection() { + console.log('Updating connection'); + this.session.updateConnection(this.connectionId, this.tokenOptions) + .then(modifiedConnection => { + this.response = 'Connection updated: ' + JSON.stringify({ role: modifiedConnection.role, record: modifiedConnection.record }); + }) + .catch(error => { + this.response = 'Error [' + error.message + ']'; + }); + } + enumToArray(enumerator: any) { return Object.keys(enumerator); } diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 9eb3a466..daea942c 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -4,7 +4,7 @@ import { } from '@angular/core'; import { - OpenVidu, Session, Subscriber, Publisher, Event, VideoInsertMode, StreamEvent, ConnectionEvent, + OpenVidu, Session, Subscriber, Publisher, Event, StreamEvent, ConnectionEvent, SessionDisconnectedEvent, SignalEvent, RecordingEvent, PublisherSpeakingEvent, PublisherProperties, StreamPropertyChangedEvent, OpenViduError } from 'openvidu-browser'; @@ -18,7 +18,8 @@ import { TokenOptions, OpenViduRole, RecordingProperties, - Recording + Recording, + Token } from 'openvidu-node-client'; import { MatDialog, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; import { ExtensionDialogComponent } from '../dialogs/extension-dialog/extension-dialog.component'; @@ -189,22 +190,21 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.clientData = 'TestClient'; } - joinSession(): void { - + async joinSession(): Promise { if (this.session) { this.leaveSession(); } - + const sessionId = !!this.customToken ? this.getSessionIdFromToken(this.customToken) : this.sessionName; + await this.initializeNodeClient(sessionId); if (!!this.customToken) { this.joinSessionShared(this.customToken); } else { - this.getToken().then(token => { - this.joinSessionShared(token); - }); + const token: Token = await this.getToken(); + this.joinSessionShared(token.token); } } - private joinSessionShared(token): void { + private joinSessionShared(token: string): void { this.OV = new OpenVidu(); @@ -686,16 +686,14 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { }); } - getToken(): Promise { + async initializeNodeClient(sessionId: string): Promise { this.OV_NodeClient = new OpenViduAPI(this.openviduUrl, this.openviduSecret); - if (!this.sessionProperties.customSessionId) { - this.sessionProperties.customSessionId = this.sessionName; - } - return this.OV_NodeClient.createSession(this.sessionProperties) - .then(session_NodeClient => { - this.sessionAPI = session_NodeClient; - return session_NodeClient.generateToken(this.tokenOptions); - }); + this.sessionProperties.customSessionId = sessionId; + this.sessionAPI = await this.OV_NodeClient.createSession(this.sessionProperties); + } + + async getToken(): Promise { + return this.sessionAPI.createToken(); } updateEventFromChild(event: OpenViduEvent) { @@ -728,4 +726,15 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.syncInitPublisher(); } + private getSessionIdFromToken(token: string): string { + const queryParams = decodeURI(token.split('?')[1]) + .split('&') + .map(param => param.split('=')) + .reduce((values, [key, value]) => { + values[key] = value + return values + }, {}); + return queryParams['sessionId']; + } + } From 52d4ba3f7ee82478513a2d77a1d73009936a8069 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 17:39:14 +0200 Subject: [PATCH 109/435] openvidu-test-e2e: update to test openvidu-node-client --- .../test/e2e/OpenViduProTestAppE2eTest.java | 33 ++++++++++++++++--- .../test/e2e/OpenViduTestAppE2eTest.java | 16 ++++----- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 74d594dc..be6db09a 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -222,13 +222,34 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':123}", HttpStatus.SC_BAD_REQUEST); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER',record:'WRONG'}", HttpStatus.SC_BAD_REQUEST); + "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/WRONG/connection/" + tokenConnectionId, + "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/WRONG", + "{'role':'PUBLISHER','record':true}", HttpStatus.SC_NOT_FOUND); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_NO_CONTENT); + "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER'}", HttpStatus.SC_NO_CONTENT); + + // Test with openvidu-node-client + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("connection-id-field")).clear(); + user.getDriver().findElement(By.id("connection-id-field")).sendKeys(tokenConnectionId); + user.getDriver().findElement(By.id("update-connection-api-btn")).click(); + user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", + "Connection updated: {\"role\":\"PUBLISHER\",\"record\":true}")); + user.getDriver().findElement(By.id("record-checkbox")).click(); + user.getDriver().findElement(By.id("token-role-select")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("option-SUBSCRIBER")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("update-connection-api-btn")).click(); + user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", + "Connection updated: {\"role\":\"SUBSCRIBER\",\"record\":false}")); + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); // Test with openvidu-java-client OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); @@ -240,16 +261,20 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } catch (OpenViduHttpException exception) { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } + Assert.assertFalse("Session object should not have changed", session.fetch()); Connection connection = session.updateConnection(tokenConnectionId, new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build()); + Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertTrue("Wrong record in Connection object", connection.record()); connection = session.updateConnection(tokenConnectionId, new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Session object should not have changed", session.fetch()); connection = session.updateConnection(tokenConnectionId, new TokenOptions.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); Assert.assertTrue("Wrong data in Connection object", connection.getServerData().isEmpty()); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 87dd2a61..247af151 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -1779,15 +1779,15 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { "Number: 1. Changes: false")); // Force unpublish wrong - user.getDriver().findElement(By.id("resource-id-field")).clear(); - user.getDriver().findElement(By.id("resource-id-field")).sendKeys("FAIL"); + user.getDriver().findElement(By.id("stream-id-field")).clear(); + user.getDriver().findElement(By.id("stream-id-field")).sendKeys("FAIL"); user.getDriver().findElement(By.id("force-unpublish-api-btn")).click(); user.getWaiter() .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Error [404]")); // Force unpublish right - user.getDriver().findElement(By.id("resource-id-field")).clear(); - user.getDriver().findElement(By.id("resource-id-field")).sendKeys(streamId); + user.getDriver().findElement(By.id("stream-id-field")).clear(); + user.getDriver().findElement(By.id("stream-id-field")).sendKeys(streamId); user.getDriver().findElement(By.id("force-unpublish-api-btn")).click(); user.getWaiter().until( ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Stream unpublished")); @@ -1797,15 +1797,15 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Expected 3 videos but found " + numberOfVideos, 3, numberOfVideos); // Force disconnect wrong - user.getDriver().findElement(By.id("resource-id-field")).clear(); - user.getDriver().findElement(By.id("resource-id-field")).sendKeys("FAIL"); + user.getDriver().findElement(By.id("connection-id-field")).clear(); + user.getDriver().findElement(By.id("connection-id-field")).sendKeys("FAIL"); user.getDriver().findElement(By.id("force-disconnect-api-btn")).click(); user.getWaiter() .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Error [404]")); // Force disconnect right - user.getDriver().findElement(By.id("resource-id-field")).clear(); - user.getDriver().findElement(By.id("resource-id-field")).sendKeys(connectionId); + user.getDriver().findElement(By.id("connection-id-field")).clear(); + user.getDriver().findElement(By.id("connection-id-field")).sendKeys(connectionId); user.getDriver().findElement(By.id("force-disconnect-api-btn")).click(); user.getWaiter() .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "User disconnected")); From c3be4453d8b7585cb7fdd17f70b6184fa233f324 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 8 Oct 2020 18:10:39 +0200 Subject: [PATCH 110/435] openvidu-browser: Replaced setInterval by setTimeout --- openvidu-browser/src/OpenVidu/Session.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index e3b1c55b..b6b7494d 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -1134,7 +1134,7 @@ export class Session extends EventDispatcher { this.openvidu.isAndroidBrowser() || this.openvidu.isSamsungBrowser() || (this.openvidu.isIPhoneOrIPad() && this.openvidu.isIOSWithSafari()) ) { - const statsRequest = setInterval(async () => { + setTimeout(async () => { const statsMap = await streamManager.stream.getWebRtcPeer().pc.getStats(); statsMap.forEach((stats) => { @@ -1148,7 +1148,6 @@ export class Session extends EventDispatcher { if (error) { logger.error("Error sending 'videoData' event", error); } - clearInterval(statsRequest); }); } }); From 117366a57f51e3fe660f556557769ea4bb442a7e Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 8 Oct 2020 18:26:30 +0200 Subject: [PATCH 111/435] openvidu-browser: Removed sendVideoData call for remote event --- openvidu-browser/src/OpenVidu/Session.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index b6b7494d..d979c459 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -900,7 +900,6 @@ export class Session extends EventDispatcher { break; } this.ee.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this, stream, msg.property, msg.newValue, oldValue, msg.reason)]); - this.sendVideoData(stream.streamManager); if (!!stream.streamManager) { stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(stream.streamManager, stream, msg.property, msg.newValue, oldValue, msg.reason)]); } From f2c37f29a5d901aa0488f93220c13d2901b9d11b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 18:38:53 +0200 Subject: [PATCH 112/435] openvidu-server: TODO comment in Participant class --- .../main/java/io/openvidu/server/core/Participant.java | 8 ++++++-- .../src/main/java/io/openvidu/server/rpc/RpcHandler.java | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 1c4fd73f..5184c684 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -38,6 +38,10 @@ public class Participant { protected GeoLocation location; // Location of the participant protected String platform; // Platform used by the participant to connect to the session protected EndpointType endpointType; // Type of participant (web participant, IP cam participant...) + + // TODO + // Unify with "PublisherEndpoint.MediaOptions" + // Also unify "streamPropertyChanged" and "videoData" RPCs when possible protected Integer videoWidth = 0; protected Integer videoHeight = 0; protected Boolean videoActive = false; @@ -145,7 +149,7 @@ public class Participant { public EndpointType getEndpointType() { return this.endpointType; } - + public Integer getVideoWidth() { return videoWidth; } @@ -161,7 +165,7 @@ public class Participant { public void setVideoHeight(Integer videoHeight) { this.videoHeight = videoHeight; } - + public Boolean isVideoActive() { return videoActive; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index 05f6fdf8..3d627340 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -636,7 +636,7 @@ public class RpcHandler extends DefaultJsonRpcHandler { new JsonObject(), e); } } - + private void updateVideoData(RpcConnection rpcConnection, Request request) { Participant participant; try { @@ -648,7 +648,7 @@ public class RpcHandler extends DefaultJsonRpcHandler { sessionManager.onVideoData(participant, request.getId(), height, width, videoActive, audioActive); } catch (OpenViduException e) { log.error("Error getting video data: {}", e.toString()); - } + } } public void leaveRoomAfterConnClosed(String participantPrivateId, EndReason reason) { From 08fcdbdb1523e1c3633c56fb426de79ca8db31a9 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 19:31:47 +0200 Subject: [PATCH 113/435] openvidu SDKs: support for updateConnection --- .../io/openvidu/java/client/Connection.java | 122 +++++-- .../java/io/openvidu/java/client/Session.java | 345 ++++++++++++------ .../java/io/openvidu/java/client/Token.java | 127 +++++++ .../io/openvidu/java/client/TokenOptions.java | 107 ++++-- openvidu-node-client/src/Connection.ts | 67 +++- openvidu-node-client/src/Session.ts | 246 +++++++------ openvidu-node-client/src/Token.ts | 81 ++++ openvidu-node-client/src/TokenOptions.ts | 1 - openvidu-node-client/src/index.ts | 1 + 9 files changed, 809 insertions(+), 288 deletions(-) create mode 100644 openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java create mode 100644 openvidu-node-client/src/Token.ts diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index c962c03a..c8a7159b 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -20,6 +20,10 @@ package io.openvidu.java.client; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; /** * See {@link io.openvidu.java.client.Session#getActiveConnections()} @@ -28,35 +32,52 @@ public class Connection { private String connectionId; private long createdAt; - private OpenViduRole role; - private String token; private String location; private String platform; - private String serverData; private String clientData; + private Token token; - protected Map publishers; - protected List subscribers; + protected Map publishers = new ConcurrentHashMap<>(); + protected List subscribers = new ArrayList<>(); - protected Connection(String connectionId, long createdAt, OpenViduRole role, String token, String location, - String platform, String serverData, String clientData, Map publishers, - List subscribers) { - this.connectionId = connectionId; - this.createdAt = createdAt; - this.role = role; - this.token = token; - this.location = location; - this.platform = platform; - this.serverData = serverData; - this.clientData = clientData; - this.publishers = publishers; - this.subscribers = subscribers; + protected Connection(JsonObject json) { + JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); + jsonArrayPublishers.forEach(publisher -> { + JsonObject pubJson = publisher.getAsJsonObject(); + JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject(); + Publisher pub = new Publisher(pubJson.get("streamId").getAsString(), pubJson.get("createdAt").getAsLong(), + mediaOptions.get("hasAudio").getAsBoolean(), mediaOptions.get("hasVideo").getAsBoolean(), + mediaOptions.get("audioActive"), mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), + mediaOptions.get("typeOfVideo"), mediaOptions.get("videoDimensions")); + this.publishers.put(pub.getStreamId(), pub); + }); + + JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray(); + jsonArraySubscribers.forEach(subscriber -> { + this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString()); + }); + + this.connectionId = json.get("connectionId").getAsString(); + this.createdAt = json.get("createdAt").getAsLong(); + + this.location = json.get("location").getAsString(); + this.platform = json.get("platform").getAsString(); + this.clientData = json.get("clientData").getAsString(); + + String token = json.has("token") ? json.get("token").getAsString() : null; + OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); + String data = json.get("serverData").getAsString(); + Boolean record = json.get("record").getAsBoolean(); + + TokenOptions tokenOptions = new TokenOptions(role, data, record, null); + this.token = new Token(token, this.connectionId, tokenOptions); } /** - * Returns the identifier of the connection. You can call - * {@link io.openvidu.java.client.Session#forceDisconnect(String)} passing this - * property as parameter + * Returns the identifier of the connection. You can call methods + * {@link io.openvidu.java.client.Session#forceDisconnect(String)} or + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} + * passing this property as parameter */ public String getConnectionId() { return connectionId; @@ -74,21 +95,41 @@ public class Connection { * Returns the role of the connection */ public OpenViduRole getRole() { - return role; + return this.token.getRole(); } /** - * Returns the token associated to the connection + * Returns the data associated to the connection on the server-side. This value + * is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)} + * when calling {@link io.openvidu.java.client.Session#generateToken()} + */ + public String getServerData() { + return this.token.getData(); + } + + /** + * Whether the streams published by this Connection will be recorded or not. + * This only affects INDIVIDUAL recording. + */ + public boolean record() { + return this.token.record(); + } + + /** + * Returns the token string associated to the connection */ public String getToken() { - return token; + return this.token.getToken(); } /** - * PRO + * PRO * * Returns the geo location of the connection, with the following format: * "CITY, COUNTRY" ("unknown" if it wasn't possible to @@ -106,20 +147,11 @@ public class Connection { return platform; } - /** - * Returns the data associated to the connection on the server-side. This value - * is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)} - * when calling {@link io.openvidu.java.client.Session#generateToken()} - */ - public String getServerData() { - return serverData; - } - /** * Returns the data associated to the connection on the client-side. This value - * is set with second parameter of method - * Session.connect in OpenVidu Browser + * is set with second parameter of method Session.connect in OpenVidu Browser */ public String getClientData() { return clientData; @@ -147,6 +179,16 @@ public class Connection { return this.subscribers; } + /** + * For now only properties data, role and record can be updated + */ + protected void overrideTokenOptions(TokenOptions tokenOptions) { + TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(tokenOptions.getRole()) + .record(tokenOptions.record()); + modifiableTokenOptions.data(this.token.getData()); + this.token.overrideTokenOptions(modifiableTokenOptions.build()); + } + protected void setSubscribers(List subscribers) { this.subscribers = subscribers; } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index c2e3bcc4..dc39bc28 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -29,6 +29,7 @@ import org.apache.http.HttpHeaders; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPatch; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; @@ -70,7 +71,7 @@ public class Session { } /** - * Gets the unique identifier of the Session + * Gets the unique identifier of the Session. * * @return The sessionId */ @@ -80,78 +81,112 @@ public class Session { /** * Timestamp when this session was created, in UTC milliseconds (ms since Jan 1, - * 1970, 00:00:00 UTC) + * 1970, 00:00:00 UTC). */ public long createdAt() { return this.createdAt; } /** - * Gets a new token associated to Session object with default values for - * {@link io.openvidu.java.client.TokenOptions}. This always translates into a - * new request to OpenVidu Server + * @deprecated Use {@link Session#createToken() Session.createToken()} instead + * to get a {@link io.openvidu.java.client.Token} object. * - * @return The generated token + * @return The generated token String * * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ + @Deprecated public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException { - return this.generateToken(new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build()); + return createToken().getToken(); } /** - * Gets a new token associated to Session object configured with - * tokenOptions. This always translates into a new request to - * OpenVidu Server + * @deprecated Use + * {@link Session#createToken(io.openvidu.java.client.TokenOptions) + * Session.createToken(TokenOptions)} instead to get a + * {@link io.openvidu.java.client.Token} object. * - * @return The generated token + * @return The generated token String * * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ + @Deprecated public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException { + return createToken(tokenOptions).getToken(); + } + /** + * Gets a new token object associated to Session object with default values for + * {@link io.openvidu.java.client.TokenOptions}. The token string value to send + * to the client side can be retrieved with + * {@link io.openvidu.java.client.Token#getToken() Token.getToken()}.
+ *
+ * You can use method {@link io.openvidu.java.client.Token#getConnectionId() + * Token.getConnectionId()} to get the connection identifier that will be given + * to the user consuming the token. With connectionId you can call + * the following methods without having to fetch and search for the actual + * {@link io.openvidu.java.client.Connection Connection} object: + *
    + *
  • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) + * Session.forceDisconnect()} to invalidate the token if no client has used it + * yet or force the connected client to leave the session if it has.
  • + *
  • Call + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) + * Session.updateConnection()} to update the + * {@link io.openvidu.java.client.Connection Connection} options. And this is + * valid for unused tokens, but also for already used tokens, so you can + * dynamically change the connection options on the fly.
  • + *
+ * + * @return The generated {@link io.openvidu.java.client.Token Token} object. + * + * @throws OpenViduJavaClientException + * @throws OpenViduHttpException + */ + public Token createToken() throws OpenViduJavaClientException, OpenViduHttpException { + return createToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); + } + + /** + * Gets a new token object associated to Session object configured with + * tokenOptions. The token string value to send to the client side + * can be retrieved with {@link io.openvidu.java.client.Token#getToken() + * Token.getToken()}.
+ *
+ * You can use method {@link io.openvidu.java.client.Token#getConnectionId() + * Token.getConnectionId()} to get the connection identifier that will be given + * to the user consuming the token. With connectionId you can call + * the following methods without having to fetch and search for the actual + * {@link io.openvidu.java.client.Connection Connection} object: + *
    + *
  • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) + * Session.forceDisconnect()} to invalidate the token if no client has used it + * yet or force the connected client to leave the session if it has.
  • + *
  • Call + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) + * Session.updateConnection()} to update the + * {@link io.openvidu.java.client.Connection Connection} options. And this is + * valid for unused tokens, but also for already used tokens, so you can + * dynamically change the user connection options on the fly.
  • + *
+ * + * @return The generated {@link io.openvidu.java.client.Token Token} object. + * + * @throws OpenViduJavaClientException + * @throws OpenViduHttpException + */ + public Token createToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException { if (!this.hasSessionId()) { this.getSessionId(); } HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_TOKENS); - JsonObject json = new JsonObject(); - json.addProperty("session", this.sessionId); - json.addProperty("role", tokenOptions.getRole().name()); - json.addProperty("data", tokenOptions.getData()); - if (tokenOptions.getKurentoOptions() != null) { - JsonObject kurentoOptions = new JsonObject(); - if (tokenOptions.getKurentoOptions().getVideoMaxRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMaxRecvBandwidth", - tokenOptions.getKurentoOptions().getVideoMaxRecvBandwidth()); - } - if (tokenOptions.getKurentoOptions().getVideoMinRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMinRecvBandwidth", - tokenOptions.getKurentoOptions().getVideoMinRecvBandwidth()); - } - if (tokenOptions.getKurentoOptions().getVideoMaxSendBandwidth() != null) { - kurentoOptions.addProperty("videoMaxSendBandwidth", - tokenOptions.getKurentoOptions().getVideoMaxSendBandwidth()); - } - if (tokenOptions.getKurentoOptions().getVideoMinSendBandwidth() != null) { - kurentoOptions.addProperty("videoMinSendBandwidth", - tokenOptions.getKurentoOptions().getVideoMinSendBandwidth()); - } - if (tokenOptions.getKurentoOptions().getAllowedFilters().length > 0) { - JsonArray allowedFilters = new JsonArray(); - for (String filter : tokenOptions.getKurentoOptions().getAllowedFilters()) { - allowedFilters.add(filter); - } - kurentoOptions.add("allowedFilters", allowedFilters); - } - json.add("kurentoOptions", kurentoOptions); - } StringEntity params; try { - params = new StringEntity(json.toString()); + params = new StringEntity(tokenOptions.toJsonObject(sessionId).toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } @@ -169,8 +204,8 @@ public class Session { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { - String token = httpResponseToJson(response).get("id").getAsString(); - log.info("Returning a TOKEN: {}", token); + Token token = new Token(httpResponseToJson(response)); + log.info("Returning a TOKEN: {}", token.getToken()); return token; } else { throw new OpenViduHttpException(statusCode); @@ -182,7 +217,7 @@ public class Session { /** * Gracefully closes the Session: unpublishes all streams and evicts every - * participant + * participant. * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -217,15 +252,17 @@ public class Session { * connections to the Session * ({@link io.openvidu.java.client.Session#getActiveConnections()}) and use * those values to call - * {@link io.openvidu.java.client.Session#forceDisconnect(Connection)} or - * {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)}.
+ * {@link io.openvidu.java.client.Session#forceDisconnect(Connection)}, + * {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)}.
+ *
* - * To update every Session object owned by OpenVidu object, call - * {@link io.openvidu.java.client.OpenVidu#fetch()} + * To update all Session objects owned by OpenVidu object at once, call + * {@link io.openvidu.java.client.OpenVidu#fetch()}. * * @return true if the Session status has changed with respect to the server, * false if not. This applies to any property or sub-property of the - * object + * object. * * @throws OpenViduHttpException * @throws OpenViduJavaClientException @@ -263,11 +300,19 @@ public class Session { * OpenVidu Browser will trigger the proper events on the client-side * (streamDestroyed, connectionDestroyed, * sessionDisconnected) with reason set to - * "forceDisconnectByServer"
+ * "forceDisconnectByServer".
+ *
* * You can get connection parameter with * {@link io.openvidu.java.client.Session#fetch()} and then - * {@link io.openvidu.java.client.Session#getActiveConnections()} + * {@link io.openvidu.java.client.Session#getActiveConnections()}.
+ *
+ * + * This method automatically updates the properties of the local affected + * objects. This means that there is no need to call + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * changes consequence of the execution of this method applied in the local + * objects. * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -278,15 +323,34 @@ public class Session { /** * Forces the user with Connection connectionId to leave the - * session. OpenVidu Browser will trigger the proper events on the client-side + * session, or invalidates the {@link Token} associated with that + * connectionId if no user has used it yet.
+ *
+ * + * In the first case you can get connectionId parameter from + * {@link io.openvidu.java.client.Connection#getConnectionId() + * Connection.getConnectionId()}. Connection objects can be listed with + * {@link io.openvidu.java.client.Session#getActiveConnections() + * Session.getActiveConnections()} (remember to use first + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to fetch the + * current active connections from OpenVidu Server). As a result, OpenVidu + * Browser will trigger the proper events on the client-side * (streamDestroyed, connectionDestroyed, * sessionDisconnected) with reason set to - * "forceDisconnectByServer"
+ * "forceDisconnectByServer".
+ *
* - * You can get connectionId parameter with - * {@link io.openvidu.java.client.Session#fetch()} (use - * {@link io.openvidu.java.client.Connection#getConnectionId()} to get the - * `connectionId` you want) + * In the second case you can get connectionId parameter from a + * {@link Token} with {@link Token#getConnectionId()}. As a result, the token + * will be invalidated and no user will be able to connect to the session with + * it.
+ *
+ * + * This method automatically updates the properties of the local affected + * objects. This means that there is no need to call + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * changes consequence of the execution of this method applied in the local + * objects. * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -336,14 +400,22 @@ public class Session { /** * Forces some user to unpublish a Stream. OpenVidu Browser will trigger the * proper events on the client-side (streamDestroyed) with reason - * set to "forceUnpublishByServer".
+ * set to "forceUnpublishByServer".
+ *
* * You can get publisher parameter with * {@link io.openvidu.java.client.Session#getActiveConnections()} and then for * each Connection you can call * {@link io.openvidu.java.client.Connection#getPublishers()}. Remember to call * {@link io.openvidu.java.client.Session#fetch()} before to fetch the current - * actual properties of the Session from OpenVidu Server + * actual properties of the Session from OpenVidu Server.
+ *
+ * + * This method automatically updates the properties of the local affected + * objects. This means that there is no need to call + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * changes consequence of the execution of this method applied in the local + * objects. * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -355,7 +427,8 @@ public class Session { /** * Forces some user to unpublish a Stream. OpenVidu Browser will trigger the * proper events on the client-side (streamDestroyed) with reason - * set to "forceUnpublishByServer".
+ * set to "forceUnpublishByServer".
+ *
* * You can get streamId parameter with * {@link io.openvidu.java.client.Session#getActiveConnections()} and then for @@ -364,7 +437,14 @@ public class Session { * {@link io.openvidu.java.client.Publisher#getStreamId()}) will give you the * streamId. Remember to call * {@link io.openvidu.java.client.Session#fetch()} before to fetch the current - * actual properties of the Session from OpenVidu Server + * actual properties of the Session from OpenVidu Server.
+ *
+ * + * This method automatically updates the properties of the local affected + * objects. This means that there is no need to call + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * changes consequence of the execution of this method applied in the local + * objects. * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -401,6 +481,94 @@ public class Session { } } + /** + * Updates the properties of a Connection. These properties are the ones defined + * by the {@link io.openvidu.java.client.TokenOptions} parameter when generating + * the token used to create the Connection. These are the properties that can be + * updated: + *
    + *
  • {@link io.openvidu.java.client.TokenOptions.Builder#role(OpenViduRole) + * TokenOptions.Builder.role(OpenViduRole)}
  • + *
  • {@link io.openvidu.java.client.TokenOptions.Builder#record(boolean) + * TokenOptions.Builder.record(boolean)}
  • + *
+ *
+ * + * The connectionId parameter can be obtained from a Connection + * object with {@link io.openvidu.java.client.Connection#getConnectionId() + * Connection.getConnectionId()}, in which case the updated properties will + * modify an active Connection. But connectionId can also be + * obtained from a Token with {@link Token#getConnectionId()}, which allows + * modifying a still not used token.
+ *
+ * + * This method automatically updates the properties of the local affected + * objects. This means that there is no need to call + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * changes consequence of the execution of this method applied in the local + * objects. + * + * @param connectionId The Connection (or a still not used Token) to modify + * @param tokenOptions A new TokenOptions object with the updated values to + * apply + * + * @return The updated {@link io.openvidu.java.client.Connection Connection} + * object + * + * @throws OpenViduJavaClientException + * @throws OpenViduHttpException + */ + public Connection updateConnection(String connectionId, TokenOptions tokenOptions) + throws OpenViduJavaClientException, OpenViduHttpException { + + HttpPatch request = new HttpPatch( + this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId); + + StringEntity params; + try { + params = new StringEntity(tokenOptions.toJsonObject(this.sessionId).toString()); + } catch (UnsupportedEncodingException e1) { + throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); + } + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + request.setEntity(params); + + HttpResponse response; + try { + response = this.openVidu.httpClient.execute(request); + } catch (IOException e) { + throw new OpenViduJavaClientException(e.getMessage(), e.getCause()); + } + + try { + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + log.info("Connection {} updated", connectionId); + } else if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { + log.info("Properties of Connection {} remain the same", connectionId); + } else { + throw new OpenViduHttpException(statusCode); + } + + // Update the actual Connection object with the new options + Connection existingConnection = this.activeConnections.get(connectionId); + + if (existingConnection == null) { + // The updated Connection is not available in local map + Connection newConnection = new Connection(httpResponseToJson(response)); + this.activeConnections.put(connectionId, newConnection); + return newConnection; + } else { + // The updated Connection was available in local map + existingConnection.overrideTokenOptions(tokenOptions); + return existingConnection; + } + + } finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + /** * Returns the list of active connections to the session. This value * will remain unchanged since the last time method @@ -408,38 +576,37 @@ public class Session { * Exceptions to this rule are: *
    *
  • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} - * updates each affected Connection status
  • + * automatically updates each affected local Connection object. *
  • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} - * updates each affected Connection status
  • + * automatically updates each affected local Connection object. + *
  • Calling + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} + * automatically updates the attributes of the affected local Connection + * object.
  • *
*
* To get the list of active connections with their current actual value, you * must call first {@link io.openvidu.java.client.Session#fetch()} and then - * {@link io.openvidu.java.client.Session#getActiveConnections()} + * {@link io.openvidu.java.client.Session#getActiveConnections()}. */ public List getActiveConnections() { return new ArrayList<>(this.activeConnections.values()); } /** - * Returns whether the session is being recorded or not + * Returns whether the session is being recorded or not. */ public boolean isBeingRecorded() { return this.recording; } /** - * Returns the properties defining the session + * Returns the properties defining the session. */ public SessionProperties getProperties() { return this.properties; } - @Override - public String toString() { - return this.sessionId; - } - private boolean hasSessionId() { return (this.sessionId != null && !this.sessionId.isEmpty()); } @@ -528,35 +695,9 @@ public class Session { this.properties = builder.build(); JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray(); this.activeConnections.clear(); - jsonArrayConnections.forEach(connection -> { - JsonObject con = connection.getAsJsonObject(); - - Map publishers = new ConcurrentHashMap<>(); - JsonArray jsonArrayPublishers = con.get("publishers").getAsJsonArray(); - jsonArrayPublishers.forEach(publisher -> { - JsonObject pubJson = publisher.getAsJsonObject(); - JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject(); - Publisher pub = new Publisher(pubJson.get("streamId").getAsString(), - pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(), - mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"), - mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"), - mediaOptions.get("videoDimensions")); - publishers.put(pub.getStreamId(), pub); - }); - - List subscribers = new ArrayList<>(); - JsonArray jsonArraySubscribers = con.get("subscribers").getAsJsonArray(); - jsonArraySubscribers.forEach(subscriber -> { - subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString()); - }); - - Connection c = new Connection(con.get("connectionId").getAsString(), con.get("createdAt").getAsLong(), - OpenViduRole.valueOf(con.get("role").getAsString()), - (con.has("token") ? con.get("token").getAsString() : null), con.get("location").getAsString(), - con.get("platform").getAsString(), con.get("serverData").getAsString(), - con.get("clientData").getAsString(), publishers, subscribers); - - this.activeConnections.put(con.get("connectionId").getAsString(), c); + jsonArrayConnections.forEach(connectionJsonElement -> { + Connection connectionObj = new Connection(connectionJsonElement.getAsJsonObject()); + this.activeConnections.put(connectionObj.getConnectionId(), connectionObj); }); return this; } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java new file mode 100644 index 00000000..b629d323 --- /dev/null +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java @@ -0,0 +1,127 @@ +package io.openvidu.java.client; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +public class Token { + + private String token; + private String connectionId; + private TokenOptions tokenOptions; + + protected Token(String token, String connectionId, TokenOptions tokenOptions) { + this.token = token; + this.connectionId = connectionId; + this.tokenOptions = tokenOptions; + } + + protected Token(JsonObject json) { + + this.token = json.get("token").getAsString(); + this.connectionId = json.get("connectionId").getAsString(); + + OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); + String data = json.get("data").getAsString(); + Boolean record = json.get("record").getAsBoolean(); + + KurentoOptions kurentoOptions = null; + if (json.has("kurentoOptions")) { + JsonObject kurentoOptionsJson = json.get("kurentoOptions").getAsJsonObject(); + + Integer videoMaxRecvBandwidth = null; + Integer videoMinRecvBandwidth = null; + Integer videoMaxSendBandwidth = null; + Integer videoMinSendBandwidth = null; + String[] allowedFilters = null; + + if (kurentoOptionsJson.has("videoMaxRecvBandwidth")) { + videoMaxRecvBandwidth = kurentoOptionsJson.get("videoMaxRecvBandwidth").getAsInt(); + } + if (kurentoOptionsJson.has("videoMinRecvBandwidth")) { + videoMinRecvBandwidth = kurentoOptionsJson.get("videoMinRecvBandwidth").getAsInt(); + } + if (kurentoOptionsJson.has("videoMaxSendBandwidth")) { + videoMaxSendBandwidth = kurentoOptionsJson.get("videoMaxSendBandwidth").getAsInt(); + } + if (kurentoOptionsJson.has("videoMinSendBandwidth")) { + videoMinSendBandwidth = kurentoOptionsJson.get("videoMinSendBandwidth").getAsInt(); + } + if (kurentoOptionsJson.has("allowedFilters")) { + JsonArray filters = kurentoOptionsJson.get("allowedFilters").getAsJsonArray(); + allowedFilters = new String[filters.size()]; + for (int i = 0; i < filters.size(); i++) { + allowedFilters[i] = filters.get(i).getAsString(); + } + } + kurentoOptions = new KurentoOptions(videoMaxRecvBandwidth, videoMinRecvBandwidth, videoMaxSendBandwidth, + videoMinSendBandwidth, allowedFilters); + } + + this.tokenOptions = new TokenOptions(role, data, record, kurentoOptions); + } + + /** + * Returns the token string value that must be sent to clients. They need to use + * it to connect to the session. + */ + public String getToken() { + return this.token; + } + + /** + * Returns the connection identifier that will be associated to the user + * consuming this token. This means that the future + * {@link io.openvidu.java.client.Connection Connection} object created with + * this token will have as connectionId this string. In other + * words, method {@link io.openvidu.java.client.Connection#getConnectionId() + * Connection.getConnectionId()} will return this same value. + * + * With connectionId you can call the following methods without + * having to fetch and search for the actual + * {@link io.openvidu.java.client.Connection Connection} object: + *
    + *
  • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) + * Session.forceDisconnect()} to invalidate the token if no client has used it + * yet or force the connected client to leave the session if it has.
  • + *
  • Call + * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) + * Session.updateConnection()} to update the + * {@link io.openvidu.java.client.Connection Connection} options. And this is + * valid for unused tokens, but also for already used tokens, so you can + * dynamically change the connection options on the fly.
  • + *
+ * + */ + public String getConnectionId() { + return this.connectionId; + } + + /** + * Returns the role assigned to this token. + */ + public OpenViduRole getRole() { + return this.tokenOptions.getRole(); + } + + /** + * Returns the secure (server-side) metadata assigned to this token. + */ + public String getData() { + return this.tokenOptions.getData(); + } + + /** + * Whether the streams published by the participant owning this token will be + * recorded or not. This only affects INDIVIDUAL recording. + */ + public Boolean record() { + return this.tokenOptions.record(); + } + + protected void overrideTokenOptions(TokenOptions tokenOptions) { + this.tokenOptions = tokenOptions; + } + +} diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java index 96c39fd6..f9338064 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java @@ -17,13 +17,18 @@ package io.openvidu.java.client; +import com.google.gson.JsonArray; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; + /** * See {@link io.openvidu.java.client.Session#generateToken(TokenOptions)} */ public class TokenOptions { - private String data; private OpenViduRole role; + private String data; + private Boolean record; private KurentoOptions kurentoOptions; /** @@ -33,15 +38,24 @@ public class TokenOptions { */ public static class Builder { - private String data = ""; private OpenViduRole role = OpenViduRole.PUBLISHER; + private String data; + private Boolean record = true; private KurentoOptions kurentoOptions; /** - * Builder for {@link io.openvidu.java.client.TokenOptions} + * Builder for {@link io.openvidu.java.client.TokenOptions}. */ public TokenOptions build() { - return new TokenOptions(this.data, this.role, this.kurentoOptions); + return new TokenOptions(this.role, this.data, this.record, this.kurentoOptions); + } + + /** + * Call this method to set the role assigned to this token. + */ + public Builder role(OpenViduRole role) { + this.role = role; + return this; } /** @@ -72,16 +86,19 @@ public class TokenOptions { } /** - * Call this method to set the role assigned to this token + * Call this method to flag the streams published by the participant owning this + * token to be recorded or not. This only affects INDIVIDUAL recording. If not set by default will be true. */ - public Builder role(OpenViduRole role) { - this.role = role; + public Builder record(boolean record) { + this.record = record; return this; } /** * Call this method to set a {@link io.openvidu.java.client.KurentoOptions} - * object for this token + * object for this token. */ public Builder kurentoOptions(KurentoOptions kurentoOptions) { this.kurentoOptions = kurentoOptions; @@ -90,31 +107,79 @@ public class TokenOptions { } - private TokenOptions(String data, OpenViduRole role, KurentoOptions kurentoOptions) { - this.data = data; + TokenOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) { this.role = role; + this.data = data; + this.record = record; this.kurentoOptions = kurentoOptions; } /** - * Returns the secure (server-side) metadata assigned to this token - */ - public String getData() { - return this.data; - } - - /** - * Returns the role assigned to this token + * Returns the role assigned to this token. */ public OpenViduRole getRole() { return this.role; } /** - * Returns the Kurento options assigned to this token + * Returns the secure (server-side) metadata assigned to this token. */ - public KurentoOptions getKurentoOptions() { - return this.kurentoOptions; + public String getData() { + return this.data; + } + + /** + * Whether the streams published by the participant owning this token will be + * recorded or not. This only affects INDIVIDUAL recording. + */ + public Boolean record() { + return this.record; + } + + protected JsonObject toJsonObject(String sessionId) { + JsonObject json = new JsonObject(); + json.addProperty("session", sessionId); + if (getRole() != null) { + json.addProperty("role", getRole().name()); + } else { + json.add("role", JsonNull.INSTANCE); + } + if (getData() != null) { + json.addProperty("data", getData()); + } else { + json.add("data", JsonNull.INSTANCE); + } + if (record() != null) { + json.addProperty("record", record()); + } else { + json.add("record", JsonNull.INSTANCE); + } + if (this.kurentoOptions != null) { + JsonObject kurentoOptions = new JsonObject(); + if (this.kurentoOptions.getVideoMaxRecvBandwidth() != null) { + kurentoOptions.addProperty("videoMaxRecvBandwidth", this.kurentoOptions.getVideoMaxRecvBandwidth()); + } + if (this.kurentoOptions.getVideoMinRecvBandwidth() != null) { + kurentoOptions.addProperty("videoMinRecvBandwidth", this.kurentoOptions.getVideoMinRecvBandwidth()); + } + if (this.kurentoOptions.getVideoMaxSendBandwidth() != null) { + kurentoOptions.addProperty("videoMaxSendBandwidth", this.kurentoOptions.getVideoMaxSendBandwidth()); + } + if (this.kurentoOptions.getVideoMinSendBandwidth() != null) { + kurentoOptions.addProperty("videoMinSendBandwidth", this.kurentoOptions.getVideoMinSendBandwidth()); + } + if (this.kurentoOptions.getAllowedFilters().length > 0) { + JsonArray allowedFilters = new JsonArray(); + for (String filter : this.kurentoOptions.getAllowedFilters()) { + allowedFilters.add(filter); + } + kurentoOptions.add("allowedFilters", allowedFilters); + } + json.add("kurentoOptions", kurentoOptions); + } + return json; } } diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 836eaa81..9bb08874 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -17,6 +17,7 @@ import { OpenViduRole } from './OpenViduRole'; import { Publisher } from './Publisher'; +import { TokenOptions } from './TokenOptions'; /** * See [[Session.activeConnections]] @@ -24,7 +25,8 @@ import { Publisher } from './Publisher'; export class Connection { /** - * Identifier of the connection. You can call [[Session.forceDisconnect]] passing this property as parameter + * Identifier of the connection. You can call methods [[Session.forceDisconnect]] + * or [[Session.updateConnection]] passing this property as parameter */ connectionId: string; @@ -38,6 +40,16 @@ export class Connection { */ role: OpenViduRole; + /** + * Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]] + */ + serverData: string; + + /** + * Whether to record the streams published by the participant owning this token or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) + */ + record: boolean; + /** * Token associated to the connection */ @@ -54,11 +66,6 @@ export class Connection { */ platform: string; - /** - * Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]] - */ - serverData: string; - /** * Data associated to the connection on the client-side. This value is set with second parameter of method * [Session.connect](/en/stable/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser @@ -80,18 +87,26 @@ export class Connection { /** * @hidden */ - constructor(connectionId: string, createdAt: number, role: OpenViduRole, token: string, location: string, platform: string, serverData: string, clientData: string, - publishers: Publisher[], subscribers: string[]) { - this.connectionId = connectionId; - this.createdAt = createdAt; - this.role = role; - this.token = token; - this.location = location; - this.platform = platform; - this.serverData = serverData; - this.clientData = clientData; - this.publishers = publishers; - this.subscribers = subscribers; + constructor(json) { + if (json.publishers != null) { + json.publishers.forEach(publisher => { + this.publishers.push(new Publisher(publisher)); + }); + } + if (json.subscribers != null) { + json.subscribers.forEach(subscriber => { + this.subscribers.push(subscriber.streamId); + }); + } + this.connectionId = json.connectionId; + this.createdAt = json.createdAt; + this.role = json.role; + this.serverData = json.serverData; + this.record = json.record; + this.token = json.token; + this.location = json.location; + this.platform = json.platform; + this.clientData = json.clientData; } /** @@ -102,10 +117,11 @@ export class Connection { this.connectionId === other.connectionId && this.createdAt === other.createdAt && this.role === other.role && + this.serverData === other.serverData && + this.record === other.record && this.token === other.token && this.location === other.location && this.platform === other.platform && - this.serverData === other.serverData && this.clientData === other.clientData && this.subscribers.length === other.subscribers.length && this.publishers.length === other.publishers.length); @@ -125,4 +141,17 @@ export class Connection { return false; } } + + /** + * @hidden + */ + overrideTokenOptions(tokenOptions: TokenOptions): void { + if (tokenOptions.role != null) { + this.role = tokenOptions.role; + } + if (tokenOptions.record != null) { + this.record = tokenOptions.record + } + } + } \ No newline at end of file diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 09cde2ee..cdb115be 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -15,16 +15,16 @@ * */ -import axios from 'axios'; +import axios, { AxiosError } from 'axios'; import { Connection } from './Connection'; import { MediaMode } from './MediaMode'; import { OpenVidu } from './OpenVidu'; -import { OpenViduRole } from './OpenViduRole'; import { Publisher } from './Publisher'; import { Recording } from './Recording'; import { RecordingLayout } from './RecordingLayout'; import { RecordingMode } from './RecordingMode'; import { SessionProperties } from './SessionProperties'; +import { Token } from './Token'; import { TokenOptions } from './TokenOptions'; @@ -49,8 +49,9 @@ export class Session { * Array of active connections to the session. This property always initialize as an empty array and * **will remain unchanged since the last time method [[Session.fetch]] was called**. Exceptions to this rule are: * - * - Calling [[Session.forceUnpublish]] also automatically updates each affected Connection status - * - Calling [[Session.forceDisconnect]] automatically updates each affected Connection status + * - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object. + * - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object. + * - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object. * * To get the array of active connections with their current actual value, you must call [[Session.fetch]] before consulting * property [[activeConnections]] @@ -93,12 +94,36 @@ export class Session { } /** - * Gets a new token associated to Session object - * - * @returns A Promise that is resolved to the _token_ if success and rejected with an Error object if not + * @deprecated Use [[Session.createToken]] instead to get a [[Token]] object. + * + * @returns A Promise that is resolved to the generated _token_ string if success and rejected with an Error object if not */ public generateToken(tokenOptions?: TokenOptions): Promise { return new Promise((resolve, reject) => { + this.createToken(tokenOptions).then(token => resolve(token.token)).catch(error => reject(error)); + }); + } + + /** + * Gets a new token object associated to Session object configured with + * `tokenOptions`. The token string value to send to the client side + * is available at [[Token.token]] property. + * + * Property [[Token.connectionId]] provides the connection identifier that will be given + * to the user consuming the token. With `connectionId` you can call + * the following methods without having to fetch and search for the actual + * [[Connection]] object: + * + * - Call [[Session.forceDisconnect]] to invalidate the token if no client has used it + * yet or force the connected client to leave the session if it has. + * - Call [[Session.updateConnection]] to update the [[Connection]] options. And this is + * valid for unused tokens, but also for already used tokens, so you can + * dynamically change the user connection options on the fly. + * + * @returns A Promise that is resolved to the generated [[Token]] object if success and rejected with an Error object if not + */ + public createToken(tokenOptions?: TokenOptions): Promise { + return new Promise((resolve, reject) => { const data = JSON.stringify({ session: this.sessionId, @@ -120,26 +145,13 @@ export class Session { .then(res => { if (res.status === 200) { // SUCCESS response from openvidu-server. Resolve token - resolve(res.data.id); + resolve(new Token(res.data)); } else { // ERROR response from openvidu-server. Resolve HTTP status reject(new Error(res.status.toString())); } }).catch(error => { - if (error.response) { - // The request was made and the server responded with a status code (not 2xx) - reject(new Error(error.response.status.toString())); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.error(error.request); - reject(new Error(error.request)); - } else { - // Something happened in setting up the request that triggered an Error - console.error('Error', error.message); - reject(new Error(error.message)); - } + this.handleError(error, reject); }); }); } @@ -171,29 +183,17 @@ export class Session { reject(new Error(res.status.toString())); } }).catch(error => { - if (error.response) { - // The request was made and the server responded with a status code (not 2xx) - reject(new Error(error.response.status.toString())); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.error(error.request); - reject(new Error(error.request)); - } else { - // Something happened in setting up the request that triggered an Error - console.error('Error', error.message); - reject(new Error(error.message)); - } + this.handleError(error, reject); }); }); } /** * Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of active - * connections of the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]] or [[Session.forceUnpublish]]. + * connections of the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]], [[Session.forceUnpublish]] or + * [[Session.updateConnection]]. * - * To update every Session object owned by OpenVidu object, call [[OpenVidu.fetch]] + * To update all Session objects owned by OpenVidu object at once, call [[OpenVidu.fetch]] * * @returns A promise resolved to true if the Session status has changed with respect to the server, or to false if not. * This applies to any property or sub-property of the Session object @@ -223,31 +223,27 @@ export class Session { reject(new Error(res.status.toString())); } }).catch(error => { - if (error.response) { - // The request was made and the server responded with a status code (not 2xx) - reject(new Error(error.response.status.toString())); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.error(error.request); - reject(new Error(error.request)); - } else { - // Something happened in setting up the request that triggered an Error - console.error('Error', error.message); - reject(new Error(error.message)); - } + this.handleError(error, reject); }); }); } /** - * Forces the user with Connection `connectionId` to leave the session. OpenVidu Browser will trigger the proper events on the client-side - * (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"` + * Forces the user with Connection `connectionId` to leave the session, or invalidates the [[Token]] associated with that + * `connectionId` if no user has used it yet. * - * You can get `connection` parameter from [[Session.activeConnections]] array ([[Connection.connectionId]] for getting each `connectionId` property). - * Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server + * In the first case you can get `connection` parameter from [[Session.activeConnections]] array (remember to call [[Session.fetch]] before + * to fetch the current actual properties of the Session from OpenVidu Server). As a result, OpenVidu Browser will trigger the proper + * events on the client-side (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`. + * + * In the second case you can get `connectionId` parameter with [[Token.connectionId]]. As a result, the token will be invalidated + * and no user will be able to connect to the session with it. + * + * This method automatically updates the properties of the local affected objects. This means that there is no need to call + * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * + * @param connection The Connection object to disconnect from the session, or its `connectionId` property + * * @returns A Promise that is resolved if the user was successfully disconnected and rejected with an Error object if not */ public forceDisconnect(connection: string | Connection): Promise { @@ -302,20 +298,7 @@ export class Session { } }) .catch(error => { - if (error.response) { - // The request was made and the server responded with a status code (not 2xx) - reject(new Error(error.response.status.toString())); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.error(error.request); - reject(new Error(error.request)); - } else { - // Something happened in setting up the request that triggered an Error - console.error('Error', error.message); - reject(new Error(error.message)); - } + this.handleError(error, reject); }); }); } @@ -327,6 +310,9 @@ export class Session { * You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property). * Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server * + * This method automatically updates the properties of the local affected objects. This means that there is no need to call + * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * * @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not */ public forceUnpublish(publisher: string | Publisher): Promise { @@ -367,20 +353,70 @@ export class Session { reject(new Error(res.status.toString())); } }).catch(error => { - if (error.response) { - // The request was made and the server responded with a status code (not 2xx) - reject(new Error(error.response.status.toString())); - } else if (error.request) { - // The request was made but no response was received - // `error.request` is an instance of XMLHttpRequest in the browser and an instance of - // http.ClientRequest in node.js - console.error(error.request); - reject(new Error(error.request)); - } else { - // Something happened in setting up the request that triggered an Error - console.error('Error', error.message); - reject(new Error(error.message)); + this.handleError(error, reject); + }); + }); + } + + /** + * Updates the properties of a Connection. These properties are the ones defined + * by the [[TokenOptions]] parameter when generating the token used to create the Connection. + * These are the properties that can be updated: + * + * - [[TokenOptions.role]] + * - [[TokenOptions.record]] + * + * The `connectionId` parameter can be obtained from a Connection object with + * [[Connection.connectionId]], in which case the updated properties will + * modify an active Connection. But `connectionId` can also be obtained from a + * Token with [[Token.connectionId]], which allows modifying a still not used token. + * + * This method automatically updates the properties of the local affected objects. This means that there is no need to call + * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * + * @param connectionId The [[Connection.connectionId]] property of the Connection object to modify, + * or the [[Token.connectionId]] property of a still not used token to modify + * @param tokenOptions A new [[TokenOptions]] object with the updated values to apply + * + * @returns A Promise that is resolved to the updated [[Connection]] object if the operation was + * successful and rejected with an Error object if not + */ + public updateConnection(connectionId: string, tokenOptions: TokenOptions): Promise { + return new Promise((resolve, reject) => { + axios.patch( + this.ov.host + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId, + tokenOptions, + { + headers: { + 'Authorization': this.ov.basicAuth, + 'Content-Type': 'application/json' } + } + ) + .then(res => { + if (res.status === 200) { + console.log('Connection ' + connectionId + ' updated'); + } else if (res.status === 204) { + console.log('Properties of Connection ' + connectionId + ' remain the same'); + } else { + // ERROR response from openvidu-server. Resolve HTTP status + reject(new Error(res.status.toString())); + return; + } + // Update the actual Connection object with the new options + const existingConnection: Connection = this.activeConnections.find(con => con.connectionId === connectionId); + if (!existingConnection) { + // The updated Connection is not available in local map + const newConnection: Connection = new Connection(res.data); + this.activeConnections.push(newConnection); + resolve(newConnection); + } else { + // The updated Connection was available in local map + existingConnection.overrideTokenOptions(tokenOptions); + resolve(existingConnection); + } + }).catch(error => { + this.handleError(error, reject); }); }); } @@ -478,28 +514,8 @@ export class Session { } this.activeConnections = []; - json.connections.content.forEach(connection => { - const publishers: Publisher[] = []; - connection.publishers.forEach(publisher => { - publishers.push(new Publisher(publisher)); - }); - const subscribers: string[] = []; - connection.subscribers.forEach(subscriber => { - subscribers.push(subscriber.streamId); - }); - this.activeConnections.push( - new Connection( - connection.connectionId, - connection.createdAt, - connection.role, - connection.token, - connection.location, - connection.platform, - connection.serverData, - connection.clientData, - publishers, - subscribers)); - }); + json.connections.content.forEach(jsonConnection => this.activeConnections.push(new Connection(jsonConnection))); + // Order connections by time of creation this.activeConnections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); return this; @@ -539,4 +555,24 @@ export class Session { } } + /** + * @hidden + */ + private handleError(error: AxiosError, reject: (reason?: any) => void) { + if (error.response) { + // The request was made and the server responded with a status code (not 2xx) + reject(new Error(error.response.status.toString())); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.error(error.request); + reject(new Error(error.request)); + } else { + // Something happened in setting up the request that triggered an Error + console.error('Error', error.message); + reject(new Error(error.message)); + } + } + } \ No newline at end of file diff --git a/openvidu-node-client/src/Token.ts b/openvidu-node-client/src/Token.ts new file mode 100644 index 00000000..bd9119d1 --- /dev/null +++ b/openvidu-node-client/src/Token.ts @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { TokenOptions } from './TokenOptions'; + +export class Token { + + /** + * The token string value that must be sent to clients. They need to use it to connect to the session. + */ + token: string; + + /** + * The connection identifier that will be associated to the user + * consuming this token. This means that the future [[Connection]] object created with + * this token will have as [[Connection.connectionId]] this same value. + * + * With `connectionId` you can call the following methods without + * having to fetch and search for the actual [[Connection]] object: + * + * - Call [[Session.forceDisconnect]] to invalidate the token if no client has used it + * yet or force the connected client to leave the session if it has. + * - Call [[Session.updateConnection]] to update the [[Connection]] options. And this is + * valid for unused tokens, but also for already used tokens, so you can + * dynamically change the connection options on the fly. + */ + connectionId: string; + + /** + * The [[TokenOptions]] assigned to this token. + */ + tokenOptions: TokenOptions; + + /** + * @hidden + */ + constructor(json) { + this.token = json.token; + this.connectionId = json.connectionId; + let possibleKurentoOptions; + if (!!json.kurentoOptions) { + possibleKurentoOptions = {}; + if (json.kurentoOptions.videoMaxRecvBandwidth != null) { + possibleKurentoOptions['videoMaxRecvBandwidth'] = json.kurentoOptions.videoMaxRecvBandwidth; + } + if (json.kurentoOptions.videoMinRecvBandwidth != null) { + possibleKurentoOptions['videoMinRecvBandwidth'] = json.kurentoOptions.videoMinRecvBandwidth; + } + if (json.kurentoOptions.videoMaxSendBandwidth != null) { + possibleKurentoOptions['videoMaxSendBandwidth'] = json.kurentoOptions.videoMaxSendBandwidth; + } + if (json.kurentoOptions.videoMinSendBandwidth != null) { + possibleKurentoOptions['videoMinSendBandwidth'] = json.kurentoOptions.videoMinSendBandwidth; + } + if (json.kurentoOptions.allowedFilters != null) { + possibleKurentoOptions['allowedFilters'] = json.kurentoOptions.allowedFilters; + } + } + this.tokenOptions = { + role: json.role, + data: json.data, + record: json.record, + kurentoOptions: possibleKurentoOptions + }; + } + +} \ No newline at end of file diff --git a/openvidu-node-client/src/TokenOptions.ts b/openvidu-node-client/src/TokenOptions.ts index 51fa4d0d..0dacc6ed 100644 --- a/openvidu-node-client/src/TokenOptions.ts +++ b/openvidu-node-client/src/TokenOptions.ts @@ -44,7 +44,6 @@ export interface TokenOptions { */ record?: boolean; - /** * **WARNING**: experimental option. This interface may change in the near future * diff --git a/openvidu-node-client/src/index.ts b/openvidu-node-client/src/index.ts index 50ce477a..f08dbba0 100644 --- a/openvidu-node-client/src/index.ts +++ b/openvidu-node-client/src/index.ts @@ -3,6 +3,7 @@ export * from './OpenViduRole'; export * from './Session'; export * from './SessionProperties'; export * from './TokenOptions'; +export * from './Token'; export * from './MediaMode'; export * from './RecordingLayout'; export * from './RecordingMode'; From de2cbe48369d1b8468fed36f5fc4384d755d3b7a Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 8 Oct 2020 19:58:18 +0200 Subject: [PATCH 114/435] deployment-openvidu-ce: Fixed infinite logs in coturn and add new execution mode --- .../docker/openvidu-coturn/Dockerfile | 2 +- .../docker/openvidu-coturn/README.md | 8 ++++++- .../openvidu-coturn/configuration-files.sh | 13 ++++++++--- .../docker/openvidu-coturn/entrypoint.sh | 23 +------------------ 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/openvidu-server/docker/openvidu-coturn/Dockerfile b/openvidu-server/docker/openvidu-coturn/Dockerfile index eac2ee94..dbd24bc5 100644 --- a/openvidu-server/docker/openvidu-coturn/Dockerfile +++ b/openvidu-server/docker/openvidu-coturn/Dockerfile @@ -11,4 +11,4 @@ RUN chmod +x /tmp/configuration-files.sh \ && chmod +x /usr/local/bin/entrypoint.sh \ && chmod +x /usr/local/bin/discover_my_public_ip.sh -CMD /usr/local/bin/entrypoint.sh \ No newline at end of file +ENTRYPOINT [ "/usr/local/bin/entrypoint.sh" ] \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-coturn/README.md b/openvidu-server/docker/openvidu-coturn/README.md index df542138..fb8a93d6 100644 --- a/openvidu-server/docker/openvidu-coturn/README.md +++ b/openvidu-server/docker/openvidu-coturn/README.md @@ -28,9 +28,15 @@ docker run --rm --name some-redis -d -p 6379:6379 redis Get the ip of the container and after that, run coturn, you can use url as ip too, in this example I am running coturn with nip.io: ``` -docker run -it -e REDIS_IP=172.17.0.2 -e DB_NAME=0 -e DB_PASSWORD=turn -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host coturn-openvidu +docker run -it -e REDIS_IP=172.17.0.2 -e DB_NAME=0 -e DB_PASSWORD=turn -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn ``` +## Execute turn locally with fixed username and password +``` +docker run -it -e TURN_USERNAME_PASSWORD=: -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn +``` + + # Kubernetes TODO diff --git a/openvidu-server/docker/openvidu-coturn/configuration-files.sh b/openvidu-server/docker/openvidu-coturn/configuration-files.sh index 3d94420c..18a7b779 100644 --- a/openvidu-server/docker/openvidu-coturn/configuration-files.sh +++ b/openvidu-server/docker/openvidu-coturn/configuration-files.sh @@ -13,9 +13,16 @@ fingerprint lt-cred-mech max-port=${MAX_PORT:-65535} min-port=${MIN_PORT:-40000} +simple-log pidfile="/var/run/turnserver.pid" realm=openvidu -simple-log -redis-userdb="ip=${REDIS_IP} dbname=${DB_NAME} password=${DB_PASSWORD} connect_timeout=30" verbose -EOF \ No newline at end of file +EOF + +if [[ ! -z "${REDIS_IP}" ]] && [[ ! -z "${DB_NAME}" ]] && [[ ! -z "${DB_PASSWORD}" ]]; then + echo "redis-userdb=\"ip=${REDIS_IP} dbname=${DB_NAME} password=${DB_PASSWORD} connect_timeout=30\"" >> /etc/turnserver.conf +fi + +if [[ ! -z "${TURN_USERNAME_PASSWORD}" ]]; then + echo "user=${TURN_USERNAME_PASSWORD}" >> /etc/turnserver.conf +fi \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-coturn/entrypoint.sh b/openvidu-server/docker/openvidu-coturn/entrypoint.sh index 8a87a719..f935fcf0 100644 --- a/openvidu-server/docker/openvidu-coturn/entrypoint.sh +++ b/openvidu-server/docker/openvidu-coturn/entrypoint.sh @@ -12,12 +12,6 @@ echo "TURN public IP: ${TURN_PUBLIC_IP}" [[ ! -z "${TURN_LISTEN_PORT}" ]] && echo "TURN listening port: ${TURN_LISTEN_PORT}" || { echo "TURN_LISTEN_PORT environment variable is not defined"; exit 1; } -[[ ! -z "${REDIS_IP}" ]] && echo "REDIS IP: ${REDIS_IP}" || { echo "REDIS_IP environment variable is not defined"; exit 1; } - -[[ ! -z "${DB_NAME}" ]] || { echo "DB_NAME environment variable is not defined"; exit 1; } - -[[ ! -z "${DB_PASSWORD}" ]] || { echo "DB_PASSWORD environment variable is not defined"; exit 1; } - [[ ! -z "${MIN_PORT}" ]] && echo "Defined min port coturn: ${MIN_PORT}" || echo "Min port coturn: 40000" [[ ! -z "${MAX_PORT}" ]] && echo "Defined max port coturn: ${MAX_PORT}" || echo "Max port coturn: 65535" @@ -28,19 +22,4 @@ source /tmp/configuration-files.sh # Remove temp file with configuration parameters rm /tmp/configuration-files.sh -# Save coturn External IP for other services - - -# Execute turn daemon -/usr/bin/turnserver -c /etc/turnserver.conf -v & - - -MAX_SECONDS=30 -# K8s only show turn server log in this way -while [ -z $(ls /var/log/ | grep turn_) ] && [ $SECONDS -lt $MAX_SECONDS ] -do - echo "Waiting turnserver to be running" - sleep 2 -done - -tail -f /var/log/turn_*.log +/usr/bin/turnserver -c /etc/turnserver.conf -v --log-file /dev/null \ No newline at end of file From 44525276c2fe2685c501f76de227aa2926a134d9 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 8 Oct 2020 20:02:29 +0200 Subject: [PATCH 115/435] openvidu-openvidu-ce-pro: Update coturn image version --- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 299b62d2..5ddce2df 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -62,7 +62,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:1.0.0 + image: openvidu/openvidu-coturn:2.0.0-dev1 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index c0d4a03b..7dadbac4 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -55,7 +55,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:1.0.0 + image: openvidu/openvidu-coturn:2.0.0-dev1 restart: on-failure network_mode: host environment: From 7919caeb232d7ab52ffae87072ad2cf4bd9134f4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 8 Oct 2020 20:41:55 +0200 Subject: [PATCH 116/435] Jenkinsfile updated --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index ee62eac9..b715e462 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -104,7 +104,7 @@ node('container') { } stage ('OpenVidu E2E tests') { try { - sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test' + sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test' } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' From a40eca6e3b7a8028c0b38c02c91ca055b9a4c712 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 9 Oct 2020 10:46:17 +0200 Subject: [PATCH 117/435] openvidu-testapp: fix get token --- .../components/openvidu-instance/openvidu-instance.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index daea942c..74c9aea9 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -693,7 +693,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { } async getToken(): Promise { - return this.sessionAPI.createToken(); + return this.sessionAPI.createToken(this.tokenOptions); } updateEventFromChild(event: OpenViduEvent) { From 564cab9038267f935e76b46597fe2fe690fdaf84 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 9 Oct 2020 10:47:20 +0200 Subject: [PATCH 118/435] openvidu-test-browsers: update CustomHttpClient to support longer body objects --- .../test/browsers/utils/CustomHttpClient.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java index 236a3b2c..fd5f65fd 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java @@ -121,7 +121,7 @@ public class CustomHttpClient { } public JsonObject rest(HttpMethod method, String path, String body, int status, boolean exactReturnedFields, - Map jsonResponse) throws Exception { + Map jsonResponse) throws Exception { JsonObject json = this.commonRest(method, path, body, status); if (exactReturnedFields) { @@ -129,47 +129,48 @@ public class CustomHttpClient { throw new Exception("Error in number of keys in JSON response to POST " + path); } - for (Map.Entry entry : jsonResponse.entrySet()) { + for (Map.Entry entry : jsonResponse.entrySet()) { + String key = entry.getKey().toString(); Object value = entry.getValue(); if (value instanceof String) { try { JsonObject jsonObjExpected = JsonParser.parseString((String) value).getAsJsonObject(); - JsonObject jsonObjActual = json.get(entry.getKey()).getAsJsonObject(); + JsonObject jsonObjActual = json.get(key).getAsJsonObject(); // COMPARE } catch (Exception e1) { try { JsonArray jsonArrayExpected = JsonParser.parseString((String) value).getAsJsonArray(); - JsonArray jsonArrayActual = json.get(entry.getKey()).getAsJsonArray(); + JsonArray jsonArrayActual = json.get(key).getAsJsonArray(); // COMPARE } catch (Exception e2) { - if (!((String) value).equals(json.get(entry.getKey()).getAsString())) { + if (!((String) value).equals(json.get(key).getAsString())) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " - + value + ". Actual: " + json.get(entry.getKey()).getAsString()); + + value + ". Actual: " + json.get(key).getAsString()); } } } } else if (value instanceof Integer) { - if (((int) value) != json.get(entry.getKey()).getAsInt()) { + if (((int) value) != json.get(key).getAsInt()) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(entry.getKey()).getAsInt()); + + ". Actual: " + json.get(key).getAsInt()); } } else if (value instanceof Long) { - if (((long) value) != json.get(entry.getKey()).getAsLong()) { + if (((long) value) != json.get(key).getAsLong()) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(entry.getKey()).getAsLong()); + + ". Actual: " + json.get(key).getAsLong()); } } else if (value instanceof Double) { - if (((double) value) != json.get(entry.getKey()).getAsDouble()) { + if (((double) value) != json.get(key).getAsDouble()) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(entry.getKey()).getAsDouble()); + + ". Actual: " + json.get(key).getAsDouble()); } } else if (value instanceof Boolean) { - if (((boolean) value) != json.get(entry.getKey()).getAsBoolean()) { + if (((boolean) value) != json.get(key).getAsBoolean()) { throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(entry.getKey()).getAsBoolean()); + + ". Actual: " + json.get(key).getAsBoolean()); } } else if (value instanceof JSONArray || value instanceof JsonArray) { JsonParser.parseString(entry.getValue().toString()).getAsJsonArray(); From fff755237ccbccba3c4c7517d33000398b7c4c3a Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Fri, 9 Oct 2020 10:52:01 +0200 Subject: [PATCH 119/435] openvidu-browser: Renamed networkQualityChanged --- openvidu-browser/src/OpenVidu/OpenVidu.ts | 2 +- openvidu-browser/src/OpenVidu/Session.ts | 12 ++++++------ ...edEvent.ts => NetworkQualityLevelChangedEvent.ts} | 6 +++--- openvidu-browser/src/index.ts | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) rename openvidu-browser/src/OpenViduInternal/Events/{NetworkQualityChangedEvent.ts => NetworkQualityLevelChangedEvent.ts} (85%) diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 29be9863..1e9213f0 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -774,7 +774,7 @@ export class OpenVidu { recordingStopped: this.session.onRecordingStopped.bind(this.session), sendMessage: this.session.onNewMessage.bind(this.session), streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session), - networkQualityChanged: this.session.onNetworkQualityChangedChanged.bind(this.session), + networkQualityLevelChanged: this.session.onNetworkQualityLevelChangedChanged.bind(this.session), filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session), iceCandidate: this.session.recvIceCandidate.bind(this.session), mediaError: this.session.onMediaError.bind(this.session) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index d979c459..97642a07 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -37,7 +37,7 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent'; import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent'; import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent'; -import { NetworkQualityChangedEvent } from '../OpenViduInternal/Events/NetworkQualityChangedEvent'; +import { NetworkQualityLevelChangedEvent } from '../OpenViduInternal/Events/NetworkQualityLevelChangedEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; @@ -594,7 +594,7 @@ export class Session extends EventDispatcher { /** * See [[EventDispatcher.on]] */ - on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): EventDispatcher { + on(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): EventDispatcher { super.onAux(type, "Event '" + type + "' triggered by 'Session'", handler); @@ -626,7 +626,7 @@ export class Session extends EventDispatcher { /** * See [[EventDispatcher.once]] */ - once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): Session { + once(type: string, handler: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): Session { super.onceAux(type, "Event '" + type + "' triggered once by 'Session'", handler); @@ -658,7 +658,7 @@ export class Session extends EventDispatcher { /** * See [[EventDispatcher.off]] */ - off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityChangedEvent) => void): Session { + off(type: string, handler?: (event: SessionDisconnectedEvent | SignalEvent | StreamEvent | ConnectionEvent | PublisherSpeakingEvent | RecordingEvent | NetworkQualityLevelChangedEvent) => void): Session { super.off(type, handler); @@ -927,9 +927,9 @@ export class Session extends EventDispatcher { /** * @hidden */ - onNetworkQualityChangedChanged(msg): void { + onNetworkQualityLevelChangedChanged(msg): void { if (msg.connectionId === this.connection.connectionId) { - this.ee.emitEvent('networkQualityChanged', [new NetworkQualityChangedEvent(this, msg.qualityLevel)]); + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel)]); } } diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts similarity index 85% rename from openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts rename to openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts index 9aa5450b..3636c866 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts @@ -19,10 +19,10 @@ import { Event } from './Event'; import { Session } from '../../OpenVidu/Session'; /** - * Defines event `networkQualityChangedEvent` dispatched by [[Session]]. + * Defines event `networkQualityLevelChangedEvent` dispatched by [[Session]]. * This event is fired when the network quality of the local connection changes */ -export class NetworkQualityChangedEvent extends Event { +export class NetworkQualityLevelChangedEvent extends Event { /** @@ -34,7 +34,7 @@ export class NetworkQualityChangedEvent extends Event { * @hidden */ constructor(target: Session, qualityLevel: Object) { - super(false, target, 'networkQualityChanged'); + super(false, target, 'networkQualityLevelChanged'); this.qualityLevel = qualityLevel; } diff --git a/openvidu-browser/src/index.ts b/openvidu-browser/src/index.ts index b36d1958..a2d82dda 100644 --- a/openvidu-browser/src/index.ts +++ b/openvidu-browser/src/index.ts @@ -23,7 +23,7 @@ export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent'; export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent'; export { FilterEvent } from './OpenViduInternal/Events/FilterEvent'; -export { NetworkQualityChangedEvent } from './OpenViduInternal/Events/NetworkQualityChangedEvent'; +export { NetworkQualityLevelChangedEvent } from './OpenViduInternal/Events/NetworkQualityLevelChangedEvent'; export { Capabilities } from './OpenViduInternal/Interfaces/Public/Capabilities'; export { Device } from './OpenViduInternal/Interfaces/Public/Device'; From 68f68f62e93fea19f5f43bd4635e7790729b8647 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Fri, 9 Oct 2020 10:52:24 +0200 Subject: [PATCH 120/435] openvidu-client: Renamed networkQualityChanged --- .../main/java/io/openvidu/client/internal/ProtocolElements.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index a4f43166..2d5afd0d 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -93,7 +93,7 @@ public class ProtocolElements { public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue"; public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason"; - public static final String NETWORKQUALITYCHANGED_METHOD = "networkQualityChanged"; + public static final String NETWORKQUALITYLEVELCHANGED_METHOD = "networkQualityLevelChanged"; public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId"; public static final String NETWORKQUALITYCHANGED_QUALITYLEVEL_PARAM = "qualityLevel"; From a3ef133b93eee3cc820c13008685da6bb583859e Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Fri, 9 Oct 2020 10:52:39 +0200 Subject: [PATCH 121/435] openvidu-server: Renamed networkQualityChanged --- .../java/io/openvidu/server/core/SessionEventsHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 00126d74..21effd3d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -302,9 +302,9 @@ public class SessionEventsHandler { rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); } - public void onNetworkQualityChanged(Participant participant, JsonObject params) { + public void onNetworkQualityLevelChanged(Participant participant, JsonObject params) { rpcNotificationService.sendNotification(participant.getParticipantPrivateId(), - ProtocolElements.NETWORKQUALITYCHANGED_METHOD, params); + ProtocolElements.NETWORKQUALITYLEVELCHANGED_METHOD, params); } public void onSendMessage(Participant participant, JsonObject message, Set participants, From acdfcd65593c91ff9d563e90a897b9f28972006b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 9 Oct 2020 12:21:52 +0200 Subject: [PATCH 122/435] openvidu-server: Participant object property "session" to "sessionId" --- .../src/main/java/io/openvidu/server/core/Participant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 5184c684..0da4aa25 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -272,7 +272,7 @@ public class Participant { public JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("connectionId", this.participantPublicId); - json.addProperty("session", this.sessionId); + json.addProperty("sessionId", this.sessionId); json.addProperty("createdAt", this.createdAt); json.addProperty("location", this.location != null ? this.location.toString() : "unknown"); json.addProperty("platform", this.platform); From 482d03d8e977c0dec2f3f4f949523e6fce4a595c Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Fri, 9 Oct 2020 12:35:49 +0200 Subject: [PATCH 123/435] openvidu-server: send network quality event to every participant --- .../io/openvidu/server/core/SessionEventsHandler.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 21effd3d..32798581 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -302,9 +302,12 @@ public class SessionEventsHandler { rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); } - public void onNetworkQualityLevelChanged(Participant participant, JsonObject params) { - rpcNotificationService.sendNotification(participant.getParticipantPrivateId(), - ProtocolElements.NETWORKQUALITYLEVELCHANGED_METHOD, params); + public void onNetworkQualityLevelChanged(Session session, JsonObject params) { + + session.getParticipants().forEach(p -> { + rpcNotificationService.sendNotification(p.getParticipantPrivateId(), + ProtocolElements.NETWORKQUALITYLEVELCHANGED_METHOD, params); + }); } public void onSendMessage(Participant participant, JsonObject message, Set participants, From 67c50862bb5be8462a8905dc8b171e26c86a0d57 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Fri, 9 Oct 2020 12:46:33 +0200 Subject: [PATCH 124/435] openvidu-browser: Added connection object to network quality event --- openvidu-browser/src/OpenVidu/Session.ts | 6 +++++- .../Events/NetworkQualityLevelChangedEvent.ts | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 97642a07..8ea22dfb 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -929,7 +929,11 @@ export class Session extends EventDispatcher { */ onNetworkQualityLevelChangedChanged(msg): void { if (msg.connectionId === this.connection.connectionId) { - this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel)]); + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, this.connection)]); + } else { + this.getConnection(msg.connectionId, 'Connection not found for connectionId ' + msg.connectionId).then((connection: Connection) => { + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, connection)]); + }); } } diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts index 3636c866..0eb423b2 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts @@ -17,6 +17,7 @@ import { Event } from './Event'; import { Session } from '../../OpenVidu/Session'; +import { Connection } from '../../OpenVidu/Connection'; /** * Defines event `networkQualityLevelChangedEvent` dispatched by [[Session]]. @@ -29,13 +30,15 @@ export class NetworkQualityLevelChangedEvent extends Event { * New value of the property (after change, current value) */ qualityLevel: Object; + connection: Connection /** * @hidden */ - constructor(target: Session, qualityLevel: Object) { + constructor(target: Session, qualityLevel: Object, connection: Connection) { super(false, target, 'networkQualityLevelChanged'); this.qualityLevel = qualityLevel; + this.connection = connection; } /** From 9e957eddf5c497d5628373f6a20d16affbe484be Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 12:21:14 +0200 Subject: [PATCH 125/435] openvidu-server: add new "object" and "id" properties to REST entities --- .../io/openvidu/server/core/Participant.java | 4 +++- .../java/io/openvidu/server/core/Session.java | 5 +++-- .../java/io/openvidu/server/core/Token.java | 22 ++++++++++++++++++- .../io/openvidu/server/kurento/kms/Kms.java | 2 +- .../openvidu/server/recording/Recording.java | 1 + 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 0da4aa25..0b1a5a56 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -271,7 +271,9 @@ public class Participant { public JsonObject toJson() { JsonObject json = new JsonObject(); - json.addProperty("connectionId", this.participantPublicId); + json.addProperty("id", this.participantPublicId); + json.addProperty("object", "connection"); + json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id" json.addProperty("sessionId", this.sessionId); json.addProperty("createdAt", this.createdAt); json.addProperty("location", this.location != null ? this.location.toString() : "unknown"); 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 c521686e..1b6e88b5 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 @@ -224,8 +224,9 @@ public class Session implements SessionInterface { private JsonObject sharedJson(Function toJsonFunction) { JsonObject json = new JsonObject(); - json.addProperty("sessionId", this.sessionId); - json.addProperty("id", this.sessionId); // TODO: deprecated. Better use only "sessionId" + json.addProperty("id", this.sessionId); + json.addProperty("object", "session"); + json.addProperty("sessionId", this.sessionId); // TODO: deprecated. Better use only "id" json.addProperty("createdAt", this.startTime); json.addProperty("mediaMode", this.sessionProperties.mediaMode().name()); json.addProperty("recordingMode", this.sessionProperties.recordingMode().name()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 5e707316..220d19f8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -91,8 +91,9 @@ public class Token { public JsonObject toJson() { JsonObject json = new JsonObject(); - json.addProperty("token", this.getToken()); json.addProperty("id", this.getToken()); + json.addProperty("object", "token"); + json.addProperty("token", this.getToken()); json.addProperty("connectionId", this.getConnectionId()); json.addProperty("session", this.sessionId); json.addProperty("role", this.getRole().toString()); @@ -104,6 +105,25 @@ public class Token { return json; } + public JsonObject toJsonAsParticipant() { + JsonObject json = new JsonObject(); + json.addProperty("id", this.getConnectionId()); + json.addProperty("object", "connection"); + json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id + json.addProperty("sessionId", this.sessionId); + json.add("createdAt", null); + json.add("location", null); + json.add("platform", null); + json.addProperty("token", this.getToken()); + json.addProperty("role", this.getRole().toString()); + json.addProperty("serverData", this.getServerMetadata()); + json.addProperty("record", this.record()); + json.add("clientData", null); + json.add("publishers", null); + json.add("subscribers", null); + return json; + } + @Override public String toString() { if (this.role != null) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java index 72b3cca4..31d74da9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java @@ -152,9 +152,9 @@ public class Kms { public JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("id", this.id); + json.addProperty("object", "mediaNode"); json.addProperty("ip", this.ip); json.addProperty("uri", this.uri); - final boolean connected = this.isKurentoClientConnected(); json.addProperty("connected", connected); json.addProperty("connectionTime", this.getTimeOfKurentoClientConnection()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java b/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java index bcaf216a..326f468a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/Recording.java @@ -191,6 +191,7 @@ public class Recording { public JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("id", this.id); + json.addProperty("object", "recording"); json.addProperty("name", this.recordingProperties.name()); json.addProperty("outputMode", this.getOutputMode().name()); if (RecordingUtils.IS_COMPOSED(this.recordingProperties.outputMode()) && this.hasVideo) { From 5575bf60cf04a2e8b117d2a9fa2b4d947afd71f0 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 12:23:35 +0200 Subject: [PATCH 126/435] openvidu-test-e2e: update tests with new CustomHttpClient --- openvidu-test-browsers/pom.xml | 6 + .../test/browsers/utils/CustomHttpClient.java | 222 ++++++++++-------- .../test/browsers/CustomHttpClientTest.java | 124 ++++++++++ .../e2e/AbstractOpenViduTestAppE2eTest.java | 27 ++- .../test/e2e/OpenViduTestAppE2eTest.java | 101 ++++---- 5 files changed, 331 insertions(+), 149 deletions(-) create mode 100644 openvidu-test-browsers/src/test/java/io/openvidu/test/browsers/CustomHttpClientTest.java diff --git a/openvidu-test-browsers/pom.xml b/openvidu-test-browsers/pom.xml index 25519eba..f3dc1b1a 100644 --- a/openvidu-test-browsers/pom.xml +++ b/openvidu-test-browsers/pom.xml @@ -97,6 +97,12 @@ unirest-java ${version.unirest} + + junit + junit + 4.13.1 + test + diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java index fd5f65fd..4c09af54 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java @@ -24,7 +24,7 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Base64; -import java.util.Map; +import java.util.Map.Entry; import javax.net.ssl.SSLContext; @@ -33,14 +33,14 @@ import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContextBuilder; -import org.json.JSONArray; -import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import com.mashape.unirest.http.HttpMethod; import com.mashape.unirest.http.HttpResponse; @@ -89,98 +89,143 @@ public class CustomHttpClient { return this.commonRest(method, path, body, status); } - public JsonObject rest(HttpMethod method, String path, String body, int status, boolean exactReturnedFields, - String jsonReturnedValue) throws Exception { - JsonObject json = this.commonRest(method, path, body, status); - JsonObject jsonObjExpected = null; + /** + * "matchKeys" to true for the returned JSON to have the exact same keys as the + * expected JSON (same number, position and name). If false, then any key + * existing in the expected JSON must exist in the returned JSON, but the + * returned JSON may have extra keys not available in expected JSON. + * + * "matchValues" to true for the returned JSON to have the exact same value in + * all the key-value pairs declared in the expected JSON. If the returned JSON + * does not have any of the keys of the expected JSON, an Error is thrown. The + * value comparison applies to NULL, JSON arrays, JSON objects or primitive + * values, at all nested levels. + * + * "matchArrays" to true for the returned JSON to have the exact same JSON array + * as value that any array property of the expected JSON. That includes value + * and order. To false to check only that JSON array is the type of the returned + * value, but not to check its content. If "matchValues" is false, then this + * property will not have effect and shall be considered false. + */ + public JsonObject rest(HttpMethod method, String path, String body, int status, boolean matchKeys, + boolean matchValues, boolean matchArrays, String jsonReturnedValue) throws Exception { + JsonObject jsonExpected = null; jsonReturnedValue.replaceAll("'", "\""); try { - jsonObjExpected = JsonParser.parseString(jsonReturnedValue).getAsJsonObject(); + jsonExpected = JsonParser.parseString(jsonReturnedValue).getAsJsonObject(); } catch (JsonSyntaxException e1) { - throw new Exception("Expected json element is a string without a JSON format: " + jsonReturnedValue); + throw new Exception("Expected JSON element is a string without a JSON format: " + jsonReturnedValue); } + JsonObject jsonActual = this.commonRest(method, path, body, status); + check(jsonExpected, jsonActual, matchKeys, matchValues, matchArrays); + return jsonActual; - if (exactReturnedFields) { - if (jsonObjExpected.size() != json.size()) { - throw new Exception( - "Error in number of keys in JSON response to POST (" + json.toString() + ")" + path); - } - } - for (String key : jsonObjExpected.keySet()) { - Class c1 = jsonObjExpected.get(key).getClass(); - Class c2 = json.get(key).getClass(); - - c1 = unifyNumberType(c1); - c2 = unifyNumberType(c2); - - if (!c1.equals(c2)) { - throw new Exception("Wrong class of property " + key); - } - } - return json; } - public JsonObject rest(HttpMethod method, String path, String body, int status, boolean exactReturnedFields, - Map jsonResponse) throws Exception { - JsonObject json = this.commonRest(method, path, body, status); - - if (exactReturnedFields) { - if (jsonResponse.size() != json.size()) - throw new Exception("Error in number of keys in JSON response to POST " + path); - } - - for (Map.Entry entry : jsonResponse.entrySet()) { - String key = entry.getKey().toString(); - Object value = entry.getValue(); - - if (value instanceof String) { - try { - JsonObject jsonObjExpected = JsonParser.parseString((String) value).getAsJsonObject(); - JsonObject jsonObjActual = json.get(key).getAsJsonObject(); - // COMPARE - - } catch (Exception e1) { - try { - JsonArray jsonArrayExpected = JsonParser.parseString((String) value).getAsJsonArray(); - JsonArray jsonArrayActual = json.get(key).getAsJsonArray(); - // COMPARE - - } catch (Exception e2) { - if (!((String) value).equals(json.get(key).getAsString())) { - throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " - + value + ". Actual: " + json.get(key).getAsString()); - } - } + public static void check(JsonObject jsonExpected, JsonObject jsonActual, boolean matchKeys, boolean matchValues, + boolean matchArrays) throws Exception { + if (matchKeys) { + checkSameKeys(jsonExpected, jsonActual, null, matchValues, matchArrays); + } else { + for (String key : jsonExpected.keySet()) { + JsonElement elExpected = jsonExpected.get(key); + JsonElement elActual = jsonActual.get(key); + if (elActual == null) { + throw new Exception( + "Expected property \"" + key + "\" did not exist in actual JSON " + jsonActual.toString()); + } + checkSameType(elExpected, elActual, key, matchValues); + } + } + } + + public static void checkSameKeys(JsonElement expected, JsonElement actual, String parent, boolean matchValues, + boolean matchArrays) throws Exception { + if (!expected.isJsonObject()) { + if (expected.isJsonArray()) { + JsonArray expectedArray = expected.getAsJsonArray(); + JsonArray actualArray = actual.getAsJsonArray(); + if (matchArrays) { + checkSameType(expectedArray, actualArray, parent, matchValues); + } + } else { + checkSameType(expected, actual, parent, matchValues); + } + } else { + JsonObject exp = expected.getAsJsonObject(); + JsonObject act = actual.getAsJsonObject(); + if (exp.size() != act.size()) { + throw new Exception("Error in number of keys in JSON object. Expected " + exp.size() + ". Actual: " + + act.size() + ". Actual object: " + act.toString()); + } + for (Entry entry : exp.entrySet()) { + String key = entry.getKey(); + if (!act.has(key)) { + throw new Exception("Property \"" + key + "\" is missing in actual object " + act.toString()); + } + checkSameKeys(entry.getValue(), act.get(key), key, matchValues, matchArrays); + } + } + } + + public static void checkSameType(JsonElement expected, JsonElement actual, String key, boolean checkAlsoSameValue) + throws Exception { + if (!expected.getClass().equals(actual.getClass())) { + throw new Exception("Expected JSON element has not the same class as the actual JSON element. Expected: " + + expected.getClass().getSimpleName() + ". Actual: " + actual.getClass().getSimpleName()); + } + if (expected.isJsonNull()) { + if (!actual.isJsonNull()) { + throw new Exception("Actual JSON element should be null"); + } + } + if (expected.isJsonArray()) { + if (!actual.isJsonArray()) { + throw new Exception("Actual JSON element should be a JSON array"); + } + JsonArray arrayExpected = expected.getAsJsonArray(); + JsonArray arrayActual = actual.getAsJsonArray(); + if (checkAlsoSameValue && !arrayExpected.equals(arrayActual)) { + throw new Exception("Property \"" + key + "\" expected an array " + arrayExpected.toString() + + " but found " + arrayActual.toString()); + } + } + if (expected.isJsonObject()) { + if (!actual.isJsonObject()) { + throw new Exception("Actual JSON element should be a JSON object"); + } + JsonObject objectExpected = expected.getAsJsonObject(); + JsonObject objectActual = actual.getAsJsonObject(); + if (checkAlsoSameValue && !objectExpected.equals(objectActual)) { + throw new Exception("Property \"" + key + "\" expected a JSON object " + objectExpected.toString() + + " but found " + objectActual.toString()); + } + } + if (expected.isJsonPrimitive()) { + JsonPrimitive primitive1 = expected.getAsJsonPrimitive(); + JsonPrimitive primitive2 = actual.getAsJsonPrimitive(); + if (primitive1.isString()) { + String string1 = primitive1.getAsString(); + String string2 = primitive2.getAsString(); + if (checkAlsoSameValue && !string1.equals(string2)) { + throw new Exception("Property \"" + key + "\" expected " + string1 + " but was " + string2); + } + } + if (primitive1.isBoolean()) { + boolean boolean1 = primitive1.getAsBoolean(); + boolean boolean2 = primitive2.getAsBoolean(); + if (checkAlsoSameValue && !boolean1 == boolean2) { + throw new Exception("Property \"" + key + "\" expected " + boolean1 + " but was " + boolean2); + } + } + if (primitive1.isNumber()) { + Number number1 = primitive1.getAsNumber(); + Number number2 = primitive2.getAsNumber(); + if (checkAlsoSameValue && !number1.equals(number2)) { + throw new Exception("Property \"" + key + "\" expected " + number1 + " but was " + number2); } - } else if (value instanceof Integer) { - if (((int) value) != json.get(key).getAsInt()) { - throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(key).getAsInt()); - } - } else if (value instanceof Long) { - if (((long) value) != json.get(key).getAsLong()) { - throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(key).getAsLong()); - } - } else if (value instanceof Double) { - if (((double) value) != json.get(key).getAsDouble()) { - throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(key).getAsDouble()); - } - } else if (value instanceof Boolean) { - if (((boolean) value) != json.get(key).getAsBoolean()) { - throw new Exception("JSON field " + entry.getKey() + " has not expected value. Expected: " + value - + ". Actual: " + json.get(key).getAsBoolean()); - } - } else if (value instanceof JSONArray || value instanceof JsonArray) { - JsonParser.parseString(entry.getValue().toString()).getAsJsonArray(); - } else if (value instanceof JSONObject || value instanceof JsonObject) { - JsonParser.parseString(entry.getValue().toString()).getAsJsonObject(); - } else { - throw new Exception("JSON response field cannot be parsed: " + entry.toString()); } } - return json; } public void shutdown() throws IOException { @@ -263,11 +308,4 @@ public class CustomHttpClient { return json; } - private Class unifyNumberType(Class myClass) { - if (Number.class.isAssignableFrom(myClass)) { - return Number.class; - } - return myClass; - } - } diff --git a/openvidu-test-browsers/src/test/java/io/openvidu/test/browsers/CustomHttpClientTest.java b/openvidu-test-browsers/src/test/java/io/openvidu/test/browsers/CustomHttpClientTest.java new file mode 100644 index 00000000..3fd27cbc --- /dev/null +++ b/openvidu-test-browsers/src/test/java/io/openvidu/test/browsers/CustomHttpClientTest.java @@ -0,0 +1,124 @@ +package io.openvidu.test.browsers; + +import org.junit.Assert; +import org.junit.Test; + +import com.google.gson.JsonParser; +import com.google.gson.JsonSyntaxException; + +import io.openvidu.test.browsers.utils.CustomHttpClient; + +public class CustomHttpClientTest { + + @Test + public void testOneLevel() throws Exception { + String expected = "{}"; + String actual = "{}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1'}"; + actual = "{'prop1':'val1'}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1','prop2':'val2'}"; + actual = "{'prop1':'val1','prop2':'val2'}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1'}"; + actual = "{'prop1':'val1','prop2':'val2'}"; + executeCheck(expected, actual, false, true, true); + expected = "{'prop1':'val1','prop2':'val2'}"; + actual = "{'prop1':'WRONG','prop2':'WRONG'}"; + executeCheck(expected, actual, true, false, true); + expected = "{'prop1':'val1','prop2':[{},{}]}"; + actual = "{'prop1':'WRONG','prop2':[{}]}"; + executeCheck(expected, actual, true, false, true); + } + + @Test + public void testMultipleLevels() throws Exception { + String expected = "{'prop1':{'prop2':'val2'}}"; + String actual = "{'prop1':{'prop2':'val2'}}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1','prop2':{'prop3':'val3'}}"; + actual = "{'prop1':'val1','prop2':{'prop3':'val3'}}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1','prop2':{'prop3':'val3'}}"; + actual = "{'prop1':'WRONG','prop2':{'prop3':'WRONG'}}"; + executeCheck(expected, actual, true, false, true); + Assert.assertThrows(IllegalStateException.class, () -> { + String expected2 = "{'prop1':'val1','prop2':{'prop3':'val3'}}"; + String actual2 = "{'prop1':'WRONG','prop2':'WRONG'}"; + executeCheck(expected2, actual2, true, false, true); + }); + Assert.assertThrows(IllegalStateException.class, () -> { + String expected2 = "{'prop1':'val1','prop2':{'prop3':'val3'}}"; + String actual2 = "{'prop1':'WRONG','prop2':[12,34]}"; + executeCheck(expected2, actual2, true, false, true); + }); + expected = "{'prop1':'val1','prop1':{'prop3':'val3'}}"; + actual = "{'prop1':'val1','prop1':{'prop3':'val3'},'WRONG':'val1'}"; + executeCheck(expected, actual, false, true, true); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':'val1','prop2':[12,34]}"; + String actual2 = "{'prop1':'val1','prop2':[12,35]}"; + executeCheck(expected2, actual2, false, true, true); + }); + Assert.assertThrows(IllegalStateException.class, () -> { + String expected2 = "{'prop1':'val1','prop2':[12,34]}"; + String actual2 = "{'prop1':'val1','prop2':{'WRONG':true}}"; + executeCheck(expected2, actual2, true, false, true); + }); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':'val1','prop1':{'prop3':null}}"; + String actual2 = "{'prop1':'val1','prop1':{'prop3':12.4},'WRONG':'val1'}"; + executeCheck(expected2, actual2, false, true, true); + }); + expected = "{'prop1':'val1','prop2':{'prop3':null}}"; + actual = "{'prop1':'val1','prop2':{'prop3':null},'WRONG':'val1'}"; + executeCheck(expected, actual, false, true, true); + expected = "{'prop1':'val1','prop2':{'prop3':12}}"; + actual = "{'prop1':'val1','prop2':{'prop3':12}}"; + executeCheck(expected, actual, true, true, true); + expected = "{'prop1':'val1','prop2':[true,false]}"; + actual = "{'prop1':'val1','prop2':[true,false]}"; + executeCheck(expected, actual, true, true, true); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':'val1','prop2':[false,true]}"; + String actual2 = "{'prop1':'val1','prop2':[true,false]}"; + executeCheck(expected2, actual2, true, true, true); + }); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':'val1','prop2':[false,true]}"; + String actual2 = "{'prop1':'val1','prop2':[true,false]}"; + executeCheck(expected2, actual2, true, true, true); + }); + expected = "{'prop1':'val1','prop2':[false,true]}"; + actual = "{'prop1':'val1','prop2':[]}"; + executeCheck(expected, actual, true, false, true); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':'val1','prop2':[false,true]}"; + String actual2 = "{'prop1':'val1','prop2':[],'prop3':false}"; + executeCheck(expected2, actual2, false, true, true); + }); + expected = "{'prop1':1,'prop2':[]}"; + actual = "{'prop1':1,'prop2':[{'prop2':'val2'}]}"; + executeCheck(expected, actual, true, true, false); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':1,'prop2':[]}"; + String actual2 = "{'prop1':0,'prop2':[{'prop2':'val2'}]}"; + executeCheck(expected2, actual2, true, true, false); + }); + Assert.assertThrows(Exception.class, () -> { + String expected2 = "{'prop1':1,'prop2':[]}"; + String actual2 = "{'prop1':1,'prop2':[{'prop2':'val2'}]}"; + executeCheck(expected2, actual2, true, true, true); + }); + } + + private void executeCheck(String expected, String actual, boolean matchKeys, boolean matchValues, + boolean matchArrays) throws JsonSyntaxException, Exception { + expected = expected.replaceAll("'", "\""); + actual = actual.replaceAll("'", "\""); + CustomHttpClient.check(JsonParser.parseString(expected).getAsJsonObject(), + JsonParser.parseString(actual).getAsJsonObject(), matchKeys, matchValues, matchArrays); + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java index 3634ad71..028209be 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java @@ -32,7 +32,6 @@ import org.jcodec.common.model.Picture; import org.jcodec.scale.AWTUtil; import org.junit.Assert; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.TakesScreenshot; @@ -82,9 +81,7 @@ public class AbstractOpenViduTestAppE2eTest { protected volatile static boolean isKurentoRestartTest; protected static OpenVidu OV; - @BeforeAll() - protected static void setupAll() { - + protected static void checkFfmpegInstallation() { String ffmpegOutput = commandLine.executeCommand("which ffmpeg"); if (ffmpegOutput == null || ffmpegOutput.isEmpty()) { log.error("ffmpeg package is not installed in the host machine"); @@ -93,10 +90,24 @@ public class AbstractOpenViduTestAppE2eTest { } else { log.info("ffmpeg is installed and accesible"); } + } + protected static void setupBrowserDrivers() { WebDriverManager.chromedriver().setup(); WebDriverManager.firefoxdriver().setup(); + } + protected static void cleanFoldersAndSetUpOpenViduJavaClient() { + try { + log.info("Cleaning folder /opt/openvidu/recordings"); + FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); + } catch (IOException e) { + log.error(e.getMessage()); + } + OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); + } + + protected static void loadEnvironmentVariables() { String appUrl = System.getProperty("APP_URL"); if (appUrl != null) { APP_URL = appUrl; @@ -147,14 +158,6 @@ public class AbstractOpenViduTestAppE2eTest { OPENVIDU_SECRET = openvidusecret; } log.info("Using secret {} to connect to openvidu-server", OPENVIDU_SECRET); - - try { - log.info("Cleaning folder /opt/openvidu/recordings"); - FileUtils.cleanDirectory(new File("/opt/openvidu/recordings")); - } catch (IOException e) { - log.error(e.getMessage()); - } - OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET); } protected void setupBrowser(String browser) { diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 247af151..96c6e2b5 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -33,6 +33,7 @@ import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.Assert; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -45,8 +46,6 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.springframework.test.context.junit.jupiter.SpringExtension; -import com.google.common.collect.ImmutableMap; -import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mashape.unirest.http.HttpMethod; @@ -82,6 +81,18 @@ import io.openvidu.test.browsers.utils.webhook.CustomWebhook; @ExtendWith(SpringExtension.class) public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; + final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','role':'STR','data':'STR','record':true}"; + final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; + + @BeforeAll() + protected static void setupAll() { + checkFfmpegInstallation(); + loadEnvironmentVariables(); + setupBrowserDrivers(); + cleanFoldersAndSetUpOpenViduJavaClient(); + } + @Test @DisplayName("One2One Chrome [Video + Audio]") void oneToOneVideoAudioSessionChrome() throws Exception { @@ -2520,8 +2531,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { log.info("REST API test"); - final String DEFAULT_JSON_SESSION = "{'sessionId':'STR','id':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; - CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); // 401 @@ -2532,8 +2541,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { /** GET /openvidu/api/sessions (before session created) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, - ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, true, + "{'numberOfElements': 0, 'content': []}"); /** POST /openvidu/api/sessions **/ // 400 @@ -2552,10 +2561,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 200 body = "{'mediaMode': 'ROUTED', 'recordingMode': 'MANUAL', 'customSessionId': 'CUSTOM_SESSION_ID', 'defaultOutputMode': 'COMPOSED', 'defaultRecordingLayout': 'BEST_FIT'}"; - restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK, true, DEFAULT_JSON_SESSION); - // Default values - JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{}", HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_SESSION); + // Default values + JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{}", HttpStatus.SC_OK, true, false, + true, DEFAULT_JSON_SESSION); restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), HttpStatus.SC_NO_CONTENT); @@ -2564,10 +2574,10 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_CONFLICT); /** GET /openvidu/api/sessions (after session created) **/ - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, - DEFAULT_JSON_SESSION); - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, - ImmutableMap.of("numberOfElements", new Integer(1), "content", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, false, + true, DEFAULT_JSON_SESSION); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, false, + "{'numberOfElements': 1, 'content': []}"); /** POST /openvidu/api/tokens **/ // 400 @@ -2585,9 +2595,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_BAD_REQUEST); // 200 - body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'allowedFilters': ['GStreamerFilter']}}"; - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, - "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'allowedFilters':['STR']}}"); + body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'videoMaxSendBandwidth':777,'allowedFilters': ['GStreamerFilter']}}"; + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, + "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); @@ -2595,8 +2605,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Default values body = "{'session': 'CUSTOM_SESSION_ID'}"; - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, - "{'id':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR'}"); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, + DEFAULT_JSON_TOKEN); final String token2 = res.get("id").getAsString(); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ @@ -2644,7 +2654,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 409 (RELAYED media mode) res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'mediaMode':'RELAYED'}", HttpStatus.SC_OK, - true, DEFAULT_JSON_SESSION); + true, false, false, DEFAULT_JSON_SESSION); body = "{'session':'" + res.get("id").getAsString() + "'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_CONFLICT); restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/" + res.get("id").getAsString(), @@ -2687,14 +2697,14 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { /** GET /openvidu/api/recordings (before recording started) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, - ImmutableMap.of("count", new Integer(0), "items", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true, + "{'count':0,'items':[]}"); /** POST /openvidu/api/recordings/start (ACTIVE SESSION) **/ // 200 body = "{'session':'CUSTOM_SESSION_ID'}"; - restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_OK, true, - "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':null,'status':'STR'}"); + restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/start", body, HttpStatus.SC_OK, true, false, true, + "{'id':'STR','object':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':null,'status':'STR'}"); user.getEventManager().waitUntilEventReaches("recordingStarted", 2); @@ -2713,13 +2723,14 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 200 restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_CONFLICT); restClient.rest(HttpMethod.POST, "/openvidu/api/recordings/stop/CUSTOM_SESSION_ID", body, HttpStatus.SC_OK, - true, - "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); + true, false, true, + "{'id':'STR','object':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); /** GET /openvidu/api/recordings (after recording created) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, - "{'id':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); - restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, - ImmutableMap.of("count", new Integer(1), "items", new JsonArray())); + false, true, + "{'id':'STR','object':'STR','sessionId':'STR','name':'STR','outputMode':'STR','recordingLayout':'STR','hasAudio':false,'hasVideo':false,'resolution':'STR','createdAt':0,'size':0,'duration':0,'url':'STR','status':'STR'}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, false, + "{'count':1,'items':[]}"); user.getEventManager().waitUntilEventReaches("recordingStopped", 2); @@ -2729,8 +2740,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/recordings/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); // GET /openvidu/api/recordings should return empty again - restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, - ImmutableMap.of("count", new Integer(0), "items", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true, + "{'count':0,'items':[]}"); /** DELETE /openvidu/api/sessions//stream/ **/ restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/NOT_EXISTS/stream/NOT_EXISTS", @@ -2738,7 +2749,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/stream/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, - "{'sessionId':'STR','id':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':2,'content'" + false, true, + "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':2,'content'" + ":[{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','token':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[" + "{'createdAt':0,'streamId':'STR','mediaOptions':{'hasAudio':false,'audioActive':false,'hasVideo':false,'videoActive':false,'typeOfVideo':'STR','frameRate':0," + "'videoDimensions':'STR','filter':{}}}],'subscribers':[{'createdAt':0,'streamId':'STR','publisher':'STR'}]},{'connectionId':'STR','createdAt':0,'location':'STR'," @@ -2786,8 +2798,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); // GET /openvidu/api/sessions should return empty again - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, - ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, true, + "{'numberOfElements':0,'content':[]}"); /** * DELETE /openvidu/api/sessions//connection/ (unused @@ -2796,10 +2808,12 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}"; - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, + DEFAULT_JSON_TOKEN); final String tokenAConnectionId = res.get("connectionId").getAsString(); final String tokenA = res.get("token").getAsString(); - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, + DEFAULT_JSON_TOKEN); final String tokenBConnectionId = res.get("connectionId").getAsString(); final String tokenB = res.get("token").getAsString(); @@ -2855,11 +2869,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); // GET /openvidu/api/sessions should return empty again - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, - ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, true, + "{'numberOfElements':0,'content':[]}"); /** GET /openvidu/api/config **/ - restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, false, true, "{'VERSION':'STR','DOMAIN_OR_PUBLIC_IP':'STR','HTTPS_PORT':0,'OPENVIDU_PUBLICURL':'STR','OPENVIDU_CDR':false,'OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH':0," + "'OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH':0,'OPENVIDU_SESSIONS_GARBAGE_INTERVAL':0,'OPENVIDU_SESSIONS_GARBAGE_THRESHOLD':0," + "'OPENVIDU_RECORDING':false,'OPENVIDU_RECORDING_VERSION':'STR','OPENVIDU_RECORDING_PATH':'STR','OPENVIDU_RECORDING_PUBLIC_ACCESS':false,'OPENVIDU_RECORDING_NOTIFICATION':'STR'," @@ -3198,7 +3212,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Init a session and publish IP camera AS FIRST PARTICIPANT restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'IP_CAM_SESSION'}", - HttpStatus.SC_OK, true, "{'id': 'STR', 'createdAt': 0}"); + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_SESSION); // No rtspUri [400] restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", "{}", @@ -3211,8 +3225,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Publish IP camera. Dummy URL because no user will subscribe to it [200] String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; JsonObject response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", - ipCamBody, HttpStatus.SC_OK, true, - "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); + ipCamBody, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); CustomWebhook.waitForEvent("sessionCreated", 1); CustomWebhook.waitForEvent("participantJoined", 1); @@ -3309,8 +3322,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, - HttpStatus.SC_OK, true, - "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); user.getEventManager().waitUntilEventReaches("connectionCreated", 2); user.getEventManager().waitUntilEventReaches("streamCreated", 2); @@ -3337,8 +3349,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Publish again the IPCAM response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, - HttpStatus.SC_OK, true, - "{'connectionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"); + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); user.getEventManager().waitUntilEventReaches("connectionCreated", 3); user.getEventManager().waitUntilEventReaches("streamCreated", 3); user.getEventManager().waitUntilEventReaches("streamPlaying", 3); From ef9d494a700d51d21996cb8b6a57b9e7651880b1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 12:28:06 +0200 Subject: [PATCH 127/435] OpenVidu SDKs: new ConnectionOptions object --- .../io/openvidu/java/client/Connection.java | 83 ++++++--- .../java/client/ConnectionOptions.java | 165 ++++++++++++++++++ .../java/io/openvidu/java/client/Session.java | 52 ++---- openvidu-node-client/src/Connection.ts | 25 +-- openvidu-node-client/src/ConnectionOptions.ts | 72 ++++++++ openvidu-node-client/src/Session.ts | 22 +-- openvidu-node-client/src/index.ts | 1 + 7 files changed, 341 insertions(+), 79 deletions(-) create mode 100644 openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java create mode 100644 openvidu-node-client/src/ConnectionOptions.ts diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index c8a7159b..a6a1f20b 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -41,29 +41,42 @@ public class Connection { protected List subscribers = new ArrayList<>(); protected Connection(JsonObject json) { - JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); - jsonArrayPublishers.forEach(publisher -> { - JsonObject pubJson = publisher.getAsJsonObject(); - JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject(); - Publisher pub = new Publisher(pubJson.get("streamId").getAsString(), pubJson.get("createdAt").getAsLong(), - mediaOptions.get("hasAudio").getAsBoolean(), mediaOptions.get("hasVideo").getAsBoolean(), - mediaOptions.get("audioActive"), mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), - mediaOptions.get("typeOfVideo"), mediaOptions.get("videoDimensions")); - this.publishers.put(pub.getStreamId(), pub); - }); + // These properties may be null + if (!json.get("publishers").isJsonNull()) { + JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); + jsonArrayPublishers.forEach(publisher -> { + JsonObject pubJson = publisher.getAsJsonObject(); + JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject(); + Publisher pub = new Publisher(pubJson.get("streamId").getAsString(), + pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(), + mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"), + mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"), + mediaOptions.get("videoDimensions")); + this.publishers.put(pub.getStreamId(), pub); + }); + } - JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray(); - jsonArraySubscribers.forEach(subscriber -> { - this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString()); - }); + if (!json.get("subscribers").isJsonNull()) { + JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray(); + jsonArraySubscribers.forEach(subscriber -> { + this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString()); + }); + } + if (!json.get("createdAt").isJsonNull()) { + this.createdAt = json.get("createdAt").getAsLong(); + } + if (!json.get("location").isJsonNull()) { + this.location = json.get("location").getAsString(); + } + if (!json.get("platform").isJsonNull()) { + this.platform = json.get("platform").getAsString(); + } + if (!json.get("clientData").isJsonNull()) { + this.clientData = json.get("clientData").getAsString(); + } + // These properties won't ever be null this.connectionId = json.get("connectionId").getAsString(); - this.createdAt = json.get("createdAt").getAsLong(); - - this.location = json.get("location").getAsString(); - this.platform = json.get("platform").getAsString(); - this.clientData = json.get("clientData").getAsString(); - String token = json.has("token") ? json.get("token").getAsString() : null; OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); String data = json.get("serverData").getAsString(); @@ -179,12 +192,36 @@ public class Connection { return this.subscribers; } + protected JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("id", this.getConnectionId()); + json.addProperty("createdAt", this.createdAt()); + json.addProperty("location", this.getLocation()); + json.addProperty("platform", this.getPlatform()); + json.addProperty("token", this.getToken()); + json.addProperty("role", this.getRole().name()); + json.addProperty("serverData", this.getServerData()); + json.addProperty("record", this.record()); + json.addProperty("clientData", this.getClientData()); + JsonArray pubs = new JsonArray(); + this.getPublishers().forEach(p -> { + pubs.add(p.toJson()); + }); + JsonArray subs = new JsonArray(); + this.getSubscribers().forEach(s -> { + subs.add(s); + }); + json.add("publishers", pubs); + json.add("subscribers", subs); + return json; + } + /** * For now only properties data, role and record can be updated */ - protected void overrideTokenOptions(TokenOptions tokenOptions) { - TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(tokenOptions.getRole()) - .record(tokenOptions.record()); + protected void overrideConnectionOptions(ConnectionOptions connectionOptions) { + TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(connectionOptions.getRole()) + .record(connectionOptions.record()); modifiableTokenOptions.data(this.token.getData()); this.token.overrideTokenOptions(modifiableTokenOptions.build()); } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java new file mode 100644 index 00000000..45b32efb --- /dev/null +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java @@ -0,0 +1,165 @@ +package io.openvidu.java.client; + +import com.google.gson.JsonArray; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; + +public class ConnectionOptions { + + private OpenViduRole role; + private String data; + private Boolean record; + private KurentoOptions kurentoOptions; + + /** + * + * Builder for {@link io.openvidu.java.client.ConnectionOptions} + * + */ + public static class Builder { + + private OpenViduRole role = OpenViduRole.PUBLISHER; + private String data; + private Boolean record = true; + private KurentoOptions kurentoOptions; + + /** + * Builder for {@link io.openvidu.java.client.ConnectionOptions}. + */ + public ConnectionOptions build() { + return new ConnectionOptions(this.role, this.data, this.record, this.kurentoOptions); + } + + /** + * Call this method to set the role assigned to this Connection. + */ + public Builder role(OpenViduRole role) { + this.role = role; + return this; + } + + /** + * Call this method to set the secure (server-side) data associated to this + * Connection. Every client will receive this data in property + * Connection.data. Object Connection can be retrieved + * by subscribing to event connectionCreated of Session object in + * your clients. + *
    + *
  • If you have provided no data in your clients when calling method + * Session.connect(TOKEN, DATA) (DATA not defined), + * then Connection.data will only have this + * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)} + * property.
  • + *
  • If you have provided some data when calling + * Session.connect(TOKEN, DATA) (DATA defined), then + * Connection.data will have the following structure: + * "CLIENT_DATA%/%SERVER_DATA", being + * CLIENT_DATA the second parameter passed in OpenVidu Browser in + * method Session.connect and SERVER_DATA this + * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)} + * property.
  • + *
+ */ + public Builder data(String data) { + this.data = data; + return this; + } + + /** + * Call this method to flag the streams published by this Connection to be + * recorded or not. This only affects INDIVIDUAL recording. If not set by default will be true. + */ + public Builder record(boolean record) { + this.record = record; + return this; + } + + /** + * Call this method to set a {@link io.openvidu.java.client.KurentoOptions} + * object for this Connection. + */ + public Builder kurentoOptions(KurentoOptions kurentoOptions) { + this.kurentoOptions = kurentoOptions; + return this; + } + + } + + ConnectionOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) { + this.role = role; + this.data = data; + this.record = record; + this.kurentoOptions = kurentoOptions; + } + + /** + * Returns the role assigned to this Connection. + */ + public OpenViduRole getRole() { + return this.role; + } + + /** + * Returns the secure (server-side) metadata assigned to this Connection. + */ + public String getData() { + return this.data; + } + + /** + * Whether the streams published by this Connection will be recorded or not. + * This only affects INDIVIDUAL recording. + */ + public Boolean record() { + return this.record; + } + + protected JsonObject toJsonObject(String sessionId) { + JsonObject json = new JsonObject(); + json.addProperty("session", sessionId); + if (getRole() != null) { + json.addProperty("role", getRole().name()); + } else { + json.add("role", JsonNull.INSTANCE); + } + if (getData() != null) { + json.addProperty("data", getData()); + } else { + json.add("data", JsonNull.INSTANCE); + } + if (record() != null) { + json.addProperty("record", record()); + } else { + json.add("record", JsonNull.INSTANCE); + } + if (this.kurentoOptions != null) { + JsonObject kurentoOptions = new JsonObject(); + if (this.kurentoOptions.getVideoMaxRecvBandwidth() != null) { + kurentoOptions.addProperty("videoMaxRecvBandwidth", this.kurentoOptions.getVideoMaxRecvBandwidth()); + } + if (this.kurentoOptions.getVideoMinRecvBandwidth() != null) { + kurentoOptions.addProperty("videoMinRecvBandwidth", this.kurentoOptions.getVideoMinRecvBandwidth()); + } + if (this.kurentoOptions.getVideoMaxSendBandwidth() != null) { + kurentoOptions.addProperty("videoMaxSendBandwidth", this.kurentoOptions.getVideoMaxSendBandwidth()); + } + if (this.kurentoOptions.getVideoMinSendBandwidth() != null) { + kurentoOptions.addProperty("videoMinSendBandwidth", this.kurentoOptions.getVideoMinSendBandwidth()); + } + if (this.kurentoOptions.getAllowedFilters().length > 0) { + JsonArray allowedFilters = new JsonArray(); + for (String filter : this.kurentoOptions.getAllowedFilters()) { + allowedFilters.add(filter); + } + kurentoOptions.add("allowedFilters", allowedFilters); + } + json.add("kurentoOptions", kurentoOptions); + } + return json; + } + +} diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index dc39bc28..b8256b14 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -268,7 +268,7 @@ public class Session { * @throws OpenViduJavaClientException */ public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException { - String beforeJSON = this.toJson(); + final String beforeJSON = this.toJson(); HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId); request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"); @@ -283,7 +283,7 @@ public class Session { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { this.resetSessionWithJson(httpResponseToJson(response)); - String afterJSON = this.toJson(); + final String afterJSON = this.toJson(); boolean hasChanged = !beforeJSON.equals(afterJSON); log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged); return hasChanged; @@ -482,15 +482,14 @@ public class Session { } /** - * Updates the properties of a Connection. These properties are the ones defined - * by the {@link io.openvidu.java.client.TokenOptions} parameter when generating - * the token used to create the Connection. These are the properties that can be - * updated: + * Updates the properties of a Connection with a + * {@link io.openvidu.java.client.ConnectionOptions} object. Only these + * properties can be updated: *
    - *
  • {@link io.openvidu.java.client.TokenOptions.Builder#role(OpenViduRole) - * TokenOptions.Builder.role(OpenViduRole)}
  • - *
  • {@link io.openvidu.java.client.TokenOptions.Builder#record(boolean) - * TokenOptions.Builder.record(boolean)}
  • + *
  • {@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole) + * ConnectionOptions.Builder.role(OpenViduRole)}
  • + *
  • {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) + * ConnectionOptions.Builder.record(boolean)}
  • *
*
* @@ -508,9 +507,9 @@ public class Session { * changes consequence of the execution of this method applied in the local * objects. * - * @param connectionId The Connection (or a still not used Token) to modify - * @param tokenOptions A new TokenOptions object with the updated values to - * apply + * @param connectionId The Connection (or a still not used Token) to modify + * @param connectionOptions A ConnectionOptions object with the new values to + * apply * * @return The updated {@link io.openvidu.java.client.Connection Connection} * object @@ -518,7 +517,7 @@ public class Session { * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ - public Connection updateConnection(String connectionId, TokenOptions tokenOptions) + public Connection updateConnection(String connectionId, ConnectionOptions connectionOptions) throws OpenViduJavaClientException, OpenViduHttpException { HttpPatch request = new HttpPatch( @@ -526,7 +525,7 @@ public class Session { StringEntity params; try { - params = new StringEntity(tokenOptions.toJsonObject(this.sessionId).toString()); + params = new StringEntity(connectionOptions.toJsonObject(this.sessionId).toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } @@ -549,18 +548,19 @@ public class Session { } else { throw new OpenViduHttpException(statusCode); } + JsonObject json = httpResponseToJson(response); // Update the actual Connection object with the new options Connection existingConnection = this.activeConnections.get(connectionId); if (existingConnection == null) { // The updated Connection is not available in local map - Connection newConnection = new Connection(httpResponseToJson(response)); + Connection newConnection = new Connection(json); this.activeConnections.put(connectionId, newConnection); return newConnection; } else { // The updated Connection was available in local map - existingConnection.overrideTokenOptions(tokenOptions); + existingConnection.overrideConnectionOptions(connectionOptions); return existingConnection; } @@ -717,23 +717,7 @@ public class Session { connections.addProperty("numberOfElements", this.getActiveConnections().size()); JsonArray jsonArrayConnections = new JsonArray(); this.getActiveConnections().forEach(con -> { - JsonObject c = new JsonObject(); - c.addProperty("connectionId", con.getConnectionId()); - c.addProperty("role", con.getRole().name()); - c.addProperty("token", con.getToken()); - c.addProperty("clientData", con.getClientData()); - c.addProperty("serverData", con.getServerData()); - JsonArray pubs = new JsonArray(); - con.getPublishers().forEach(p -> { - pubs.add(p.toJson()); - }); - JsonArray subs = new JsonArray(); - con.getSubscribers().forEach(s -> { - subs.add(s); - }); - c.add("publishers", pubs); - c.add("subscribers", subs); - jsonArrayConnections.add(c); + jsonArrayConnections.add(con.toJson()); }); connections.add("content", jsonArrayConnections); json.add("connections", connections); diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 9bb08874..8919edfe 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -17,7 +17,7 @@ import { OpenViduRole } from './OpenViduRole'; import { Publisher } from './Publisher'; -import { TokenOptions } from './TokenOptions'; +import { ConnectionOptions } from './ConnectionOptions'; /** * See [[Session.activeConnections]] @@ -88,6 +88,7 @@ export class Connection { * @hidden */ constructor(json) { + // These properties may be null if (json.publishers != null) { json.publishers.forEach(publisher => { this.publishers.push(new Publisher(publisher)); @@ -98,15 +99,17 @@ export class Connection { this.subscribers.push(subscriber.streamId); }); } - this.connectionId = json.connectionId; this.createdAt = json.createdAt; - this.role = json.role; - this.serverData = json.serverData; - this.record = json.record; - this.token = json.token; this.location = json.location; this.platform = json.platform; this.clientData = json.clientData; + + // These properties won't ever be null + this.connectionId = json.connectionId; + this.token = json.token; + this.role = json.role; + this.serverData = json.serverData; + this.record = json.record; } /** @@ -145,12 +148,12 @@ export class Connection { /** * @hidden */ - overrideTokenOptions(tokenOptions: TokenOptions): void { - if (tokenOptions.role != null) { - this.role = tokenOptions.role; + overrideConnectionOptions(connectionOptions: ConnectionOptions): void { + if (connectionOptions.role != null) { + this.role = connectionOptions.role; } - if (tokenOptions.record != null) { - this.record = tokenOptions.record + if (connectionOptions.record != null) { + this.record = connectionOptions.record } } diff --git a/openvidu-node-client/src/ConnectionOptions.ts b/openvidu-node-client/src/ConnectionOptions.ts new file mode 100644 index 00000000..bd10bbaf --- /dev/null +++ b/openvidu-node-client/src/ConnectionOptions.ts @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { OpenViduRole } from './OpenViduRole'; + +export interface ConnectionOptions { + + /** + * The role assigned to this Connection + * + * @default PUBLISHER + */ + role?: OpenViduRole; + + /** + * Secure (server-side) data associated to this Connection. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object. + * - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[ConnectionOptions.data]] property. + * - If you have provided some data when calling `Session.connect(TOKEN, DATA)` (`DATA` defined), then `Connection.data` will have the following structure: `"CLIENT_DATA%/%SERVER_DATA"`, being `CLIENT_DATA` the second + * parameter passed in OpenVidu Browser in method `Session.connect` and `SERVER_DATA` this [[ConnectionOptions.data]] property. + */ + data?: string; + + /** + * Whether to record the streams published by this Connection or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) + * + * @default true + */ + record?: boolean; + + /** + * **WARNING**: experimental option. This interface may change in the near future + * + * Some advanced properties setting the configuration that the WebRTC streams of the Connection will have in Kurento Media Server. + * You can adjust: + * - `videoMaxRecvBandwidth`: maximum number of Kbps that the Connection will be able to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override + * the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/) + * (parameter `OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH`) for every incoming stream of the Connection. + * _**WARNING**: the lower value set to this property limits every other bandwidth of the WebRTC pipeline this server-to-client stream belongs to. This includes the user publishing the stream and every other user subscribed to the stream_ + * - `videoMinRecvBandwidth`: minimum number of Kbps that the cConnection will try to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override + * the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/) + * (parameter `OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH`) for every incoming stream of the Connection. + * - `videoMaxSendBandwidth`: maximum number of Kbps that the Connection will be able to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override + * the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/) + * (parameter `OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH`) for every outgoing stream of the Connection. + * _**WARNING**: this value limits every other bandwidth of the WebRTC pipeline this client-to-server stream belongs to. This includes every other user subscribed to the stream_ + * - `videoMinSendBandwidth`: minimum number of Kbps that the Connection will try to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override + * the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/) + * (parameter `OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH`) for every outgoing stream of the Connection. + * - `allowedFilters`: names of the filters the Connection will be able to apply. See [Voice and video filters](/en/stable/advanced-features/filters/) + */ + kurentoOptions?: { + videoMaxRecvBandwidth?: number, + videoMinRecvBandwidth?: number, + videoMaxSendBandwidth?: number, + videoMinSendBandwidth?: number, + allowedFilters?: string[] + }; +} \ No newline at end of file diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index cdb115be..79b8dfa9 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -17,6 +17,7 @@ import axios, { AxiosError } from 'axios'; import { Connection } from './Connection'; +import { ConnectionOptions } from './ConnectionOptions'; import { MediaMode } from './MediaMode'; import { OpenVidu } from './OpenVidu'; import { Publisher } from './Publisher'; @@ -359,12 +360,11 @@ export class Session { } /** - * Updates the properties of a Connection. These properties are the ones defined - * by the [[TokenOptions]] parameter when generating the token used to create the Connection. - * These are the properties that can be updated: + * Updates the properties of a Connection with a [[ConnectionOptions]] object. + * Only these properties can be updated: * - * - [[TokenOptions.role]] - * - [[TokenOptions.record]] + * - [[ConnectionOptions.role]] + * - [[ConnectionOptions.record]] * * The `connectionId` parameter can be obtained from a Connection object with * [[Connection.connectionId]], in which case the updated properties will @@ -375,17 +375,17 @@ export class Session { * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @param connectionId The [[Connection.connectionId]] property of the Connection object to modify, - * or the [[Token.connectionId]] property of a still not used token to modify - * @param tokenOptions A new [[TokenOptions]] object with the updated values to apply + * or the [[Token.connectionId]] property of a still not used token to modify + * @param connectionOptions A new [[ConnectionOptions]] object with the updated values to apply * * @returns A Promise that is resolved to the updated [[Connection]] object if the operation was - * successful and rejected with an Error object if not + * successful and rejected with an Error object if not */ - public updateConnection(connectionId: string, tokenOptions: TokenOptions): Promise { + public updateConnection(connectionId: string, connectionOptions: ConnectionOptions): Promise { return new Promise((resolve, reject) => { axios.patch( this.ov.host + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId, - tokenOptions, + connectionOptions, { headers: { 'Authorization': this.ov.basicAuth, @@ -412,7 +412,7 @@ export class Session { resolve(newConnection); } else { // The updated Connection was available in local map - existingConnection.overrideTokenOptions(tokenOptions); + existingConnection.overrideConnectionOptions(connectionOptions); resolve(existingConnection); } }).catch(error => { diff --git a/openvidu-node-client/src/index.ts b/openvidu-node-client/src/index.ts index f08dbba0..e3b5a359 100644 --- a/openvidu-node-client/src/index.ts +++ b/openvidu-node-client/src/index.ts @@ -3,6 +3,7 @@ export * from './OpenViduRole'; export * from './Session'; export * from './SessionProperties'; export * from './TokenOptions'; +export * from './ConnectionOptions'; export * from './Token'; export * from './MediaMode'; export * from './RecordingLayout'; From 17ec0c84515ddc77d96bd2e15a9a1b1b2183bd75 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Tue, 13 Oct 2020 12:28:50 +0200 Subject: [PATCH 128/435] openvidu-browser: Added network quality Firefox support - Added basic version for Firefox. It does not support webrtc stats approach --- openvidu-browser/src/OpenVidu/Session.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 8ea22dfb..e424ea2d 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -1140,7 +1140,6 @@ export class Session extends EventDispatcher { setTimeout(async () => { const statsMap = await streamManager.stream.getWebRtcPeer().pc.getStats(); statsMap.forEach((stats) => { - if ("frameWidth" in stats) { this.openvidu.sendRequest('videoData', { height: stats.frameHeight, @@ -1155,6 +1154,18 @@ export class Session extends EventDispatcher { } }); }, intervalSeconds * 1000); + } else if (this.openvidu.isFirefoxBrowser() || this.openvidu.isFirefoxMobileBrowser()) { + // Basic version for Firefox. It does not support stats + this.openvidu.sendRequest('videoData', { + height: streamManager.stream.videoDimensions.height, + width: streamManager.stream.videoDimensions.width, + videoActive: streamManager.stream.videoActive, + audioActive: streamManager.stream.audioActive + }, (error, response) => { + if (error) { + logger.error("Error sending 'videoData' event", error); + } + }); } else { console.error('Browser ' + platform.name + ' (version ' + platform.version + ') for ' + platform.os!!.family + ' is not supported in OpenVidu for Network Quality'); } From 5e5d886e59471cc1c779b46ba306b0db9d2641d6 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 12:44:30 +0200 Subject: [PATCH 129/435] openvidu-test-e2e: update Pro tests with new REST API --- .../test/e2e/OpenViduProTestAppE2eTest.java | 126 +++++++++++++----- 1 file changed, 95 insertions(+), 31 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index be6db09a..3ab0585b 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -8,6 +8,7 @@ import java.util.stream.Stream; import org.apache.http.HttpStatus; import org.junit.Assert; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.openqa.selenium.Alert; @@ -16,7 +17,6 @@ import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; -import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -25,17 +25,24 @@ import com.google.gson.stream.JsonReader; import com.mashape.unirest.http.HttpMethod; import io.openvidu.java.client.Connection; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.java.client.OpenVidu; import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.Session; -import io.openvidu.java.client.TokenOptions; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + @BeforeAll() + protected static void setupAll() { + loadEnvironmentVariables(); + setupBrowserDrivers(); + cleanFoldersAndSetUpOpenViduJavaClient(); + } + @Test @DisplayName("Individual dynamic record") void individualDynamicRecordTest() throws Exception { @@ -154,7 +161,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { long msDuration = file.get("endTimeOffset").getAsLong() - file.get("startTimeOffset").getAsLong(); Assert.assertTrue( "Wrong recording duration of individual file. Difference: " + Math.abs(msDuration - 1000), - Math.abs(msDuration - 1000) < 100); + Math.abs(msDuration - 1000) < 150); Assert.assertTrue("File name not found among " + names.toString(), names.remove(file.get("name").getAsString())); count2++; @@ -171,8 +178,6 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @DisplayName("REST API PRO test") void restApiProTest() throws Exception { - setupBrowser("chrome"); - log.info("REST API PRO test"); CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); @@ -182,11 +187,56 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { **/ String body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); - body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}"; + body = "{'session':'CUSTOM_SESSION_ID','role':'PUBLISHER','record':false}"; JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String token = res.get("token").getAsString(); final String tokenConnectionId = res.get("connectionId").getAsString(); + /** UPDATE TOKEN **/ + + // Test with REST API + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':false}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'record':123}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/WRONG/connection/" + tokenConnectionId, + "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/WRONG", + "{'role':'PUBLISHER','record':true}", HttpStatus.SC_NOT_FOUND); + + // Updating only role should let record value untouched + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':false,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); + // Updating only record should let role value untouched + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + "{'record':true}", HttpStatus.SC_OK, true, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); + + // Test with openvidu-java-client + OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); + Assert.assertTrue("OpenVidu object should have changed", OV.fetch()); + Session session = OV.getActiveSessions().get(0); + try { + session.updateConnection("WRONG_CONNECTION_ID", new ConnectionOptions.Builder().build()); + Assert.fail("Expected OpenViduHttpException exception"); + } catch (OpenViduHttpException exception) { + Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); + } + Assert.assertFalse("Session object should not have changed", session.fetch()); + Connection connection = session.updateConnection(tokenConnectionId, + new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); + Assert.assertEquals("Wrong role Connection property", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Wrong record Connection property", connection.record()); + + setupBrowser("chrome"); + user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.id("session-settings-btn-0")).click(); Thread.sleep(1000); @@ -205,6 +255,11 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getEventManager().waitUntilEventReaches("connectionCreated", 1); user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + Assert.assertTrue("Session object should have changed", session.fetch()); + connection = session.getActiveConnections().get(0); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Wrong record in Connection object", connection.record()); + try { user.getWaiter().until(ExpectedConditions.alertIsPresent()); Alert alert = user.getDriver().switchTo().alert(); @@ -216,21 +271,31 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } Thread.sleep(500); + /** UPDATE CONNECTION **/ + // Test with REST API + // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':false}", HttpStatus.SC_BAD_REQUEST); + "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':false,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); + // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'record':123}", HttpStatus.SC_BAD_REQUEST); + "{'record':true}", HttpStatus.SC_OK, false, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/WRONG/connection/" + tokenConnectionId, - "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_NOT_FOUND); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/WRONG", - "{'role':'PUBLISHER','record':true}", HttpStatus.SC_NOT_FOUND); + "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'SUBSCRIBER','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER'}", HttpStatus.SC_OK); + "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, + "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId + + "','role':'PUBLISHER','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); // Test with openvidu-node-client user.getDriver().findElement(By.id("session-api-btn-0")).click(); @@ -252,28 +317,26 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); // Test with openvidu-java-client - OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); - OV.fetch(); - Session session = OV.getActiveSessions().get(0); + Assert.assertFalse("Session object should not have changed", session.fetch()); try { - session.updateConnection("WRONG_CONNECTION_ID", new TokenOptions.Builder().build()); + session.updateConnection("WRONG_CONNECTION_ID", new ConnectionOptions.Builder().build()); Assert.fail("Expected OpenViduHttpException exception"); } catch (OpenViduHttpException exception) { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } Assert.assertFalse("Session object should not have changed", session.fetch()); - Connection connection = session.updateConnection(tokenConnectionId, - new TokenOptions.Builder().role(OpenViduRole.PUBLISHER).build()); + connection = session.updateConnection(tokenConnectionId, + new ConnectionOptions.Builder().role(OpenViduRole.PUBLISHER).build()); Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertTrue("Wrong record in Connection object", connection.record()); connection = session.updateConnection(tokenConnectionId, - new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); + new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Session object should not have changed", session.fetch()); connection = session.updateConnection(tokenConnectionId, - new TokenOptions.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + new ConnectionOptions.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); @@ -297,22 +360,23 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_NO_CONTENT); // GET /openvidu/api/sessions should return empty again - restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, - ImmutableMap.of("numberOfElements", new Integer(0), "content", new JsonArray())); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, true, + "{'numberOfElements':0,'content':[]}"); /** GET /openvidu/api/config **/ - restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, + restClient.rest(HttpMethod.GET, "/openvidu/api/config", null, HttpStatus.SC_OK, true, false, true, "{'VERSION':'STR','DOMAIN_OR_PUBLIC_IP':'STR','HTTPS_PORT':0,'OPENVIDU_PUBLICURL':'STR','OPENVIDU_CDR':false,'OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH':0," + "'OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH':0,'OPENVIDU_SESSIONS_GARBAGE_INTERVAL':0,'OPENVIDU_SESSIONS_GARBAGE_THRESHOLD':0," + "'OPENVIDU_RECORDING':false,'OPENVIDU_RECORDING_VERSION':'STR','OPENVIDU_RECORDING_PATH':'STR','OPENVIDU_RECORDING_PUBLIC_ACCESS':false,'OPENVIDU_RECORDING_NOTIFICATION':'STR'," + "'OPENVIDU_RECORDING_CUSTOM_LAYOUT':'STR','OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT':0,'OPENVIDU_WEBHOOK':false,'OPENVIDU_WEBHOOK_ENDPOINT':'STR','OPENVIDU_WEBHOOK_HEADERS':[]," + "'OPENVIDU_WEBHOOK_EVENTS':[],'OPENVIDU_SERVER_DEPENDENCY_VERSION':'STR','KMS_URIS':[],'OPENVIDU_PRO_STATS_MONITORING_INTERVAL':0,'OPENVIDU_PRO_STATS_WEBRTC_INTERVAL':0,'OPENVIDU_PRO_CLUSTER_ID':'STR'," - + "'OPENVIDU_PRO_CLUSTER_ENVIRONMENT':'STR','OPENVIDU_PRO_CLUSTER_MEDIA_NODES':0,'OPENVIDU_PRO_CLUSTER_PATH':'STR','OPENVIDU_PRO_CLUSTER_AUTOSCALING':false,'OPENVIDU_PRO_NETWORK_STAT':false," - + "'OPENVIDU_PRO_ELASTICSEARCH':false,'OPENVIDU_PRO_KIBANA':false,'OPENVIDU_PRO_RECORDING_STORAGE':'STR'}"); + + "'OPENVIDU_PRO_CLUSTER_ENVIRONMENT':'STR','OPENVIDU_PRO_CLUSTER_MEDIA_NODES':0,'OPENVIDU_PRO_CLUSTER_PATH':'STR','OPENVIDU_PRO_CLUSTER_AUTOSCALING':false," + + "'OPENVIDU_PRO_ELASTICSEARCH':true,'OPENVIDU_PRO_ELASTICSEARCH_VERSION':'STR','OPENVIDU_PRO_ELASTICSEARCH_HOST':'STR','OPENVIDU_PRO_KIBANA':true,'OPENVIDU_PRO_KIBANA_VERSION':'STR'," + + "'OPENVIDU_PRO_KIBANA_HOST':'STR','OPENVIDU_PRO_RECORDING_STORAGE':'STR','OPENVIDU_PRO_NETWORK_QUALITY':false}"); /** GET /openvidu/api/health **/ - restClient.rest(HttpMethod.GET, "/openvidu/api/health", null, HttpStatus.SC_OK, true, - ImmutableMap.of("status", "UP")); + restClient.rest(HttpMethod.GET, "/openvidu/api/health", null, HttpStatus.SC_OK, true, true, true, + "{'status':'UP'}"); } } From dfa12ffbb8ffa090f4eb5006171d7d28d2e4cf35 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 14:00:54 +0200 Subject: [PATCH 130/435] openvidu-test-e2e: fix Pro e2e tests --- .../test/java/io/openvidu/test/e2e/MyUser.java | 2 +- .../openvidu/test/e2e/OpenViduEventManager.java | 16 +++++++++------- .../test/e2e/OpenViduProTestAppE2eTest.java | 17 +++++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/MyUser.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/MyUser.java index 3a7952b1..8ed6a980 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/MyUser.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/MyUser.java @@ -28,7 +28,7 @@ public class MyUser { } public void dispose() { - this.eventManager.stopPolling(true); + this.eventManager.stopPolling(true, true); this.browserUser.dispose(); } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java index 4105fdab..db1a8d22 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java @@ -101,7 +101,7 @@ public class OpenViduEventManager { public void uncaughtException(Thread th, Throwable ex) { if (ex.getClass().getSimpleName().equals("UnhandledAlertException") && ex.getMessage().contains("unexpected alert open")) { - stopPolling(false); + stopPolling(false, false); System.err .println("Alert opened (" + ex.getMessage() + "). Waiting 1 second and restarting polling"); try { @@ -138,14 +138,16 @@ public class OpenViduEventManager { this.pollingThread.start(); } - public void stopPolling(boolean stopThread) { + public void stopPolling(boolean stopThread, boolean cleanExistingEvents) { if (stopThread) { this.isInterrupted.set(true); this.pollingThread.interrupt(); } - this.eventCallbacks.clear(); - this.eventCountdowns.clear(); - this.eventNumbers.clear(); + if (cleanExistingEvents) { + this.eventCallbacks.clear(); + this.eventCountdowns.clear(); + this.eventNumbers.clear(); + } } public void on(String eventName, Consumer callback) { @@ -195,12 +197,12 @@ public class OpenViduEventManager { } public void resetEventThread() throws InterruptedException { - this.stopPolling(true); + this.stopPolling(true, true); this.pollingLatch.await(); this.execService.shutdownNow(); this.execService.awaitTermination(10, TimeUnit.SECONDS); this.execService = Executors.newCachedThreadPool(); - this.stopPolling(false); + this.stopPolling(false, true); this.clearAllCurrentEvents(); this.isInterrupted.set(false); this.pollingLatch = new CountDownLatch(1); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 3ab0585b..132a0a6e 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -38,6 +38,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @BeforeAll() protected static void setupAll() { + checkFfmpegInstallation(); loadEnvironmentVariables(); setupBrowserDrivers(); cleanFoldersAndSetUpOpenViduJavaClient(); @@ -252,14 +253,6 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .join-btn")).sendKeys(Keys.ENTER); - user.getEventManager().waitUntilEventReaches("connectionCreated", 1); - user.getEventManager().waitUntilEventReaches("accessAllowed", 1); - - Assert.assertTrue("Session object should have changed", session.fetch()); - connection = session.getActiveConnections().get(0); - Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); - Assert.assertFalse("Wrong record in Connection object", connection.record()); - try { user.getWaiter().until(ExpectedConditions.alertIsPresent()); Alert alert = user.getDriver().switchTo().alert(); @@ -271,6 +264,14 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } Thread.sleep(500); + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + + Assert.assertTrue("Session object should have changed", session.fetch()); + connection = session.getActiveConnections().get(0); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Wrong record in Connection object", connection.record()); + /** UPDATE CONNECTION **/ // Test with REST API From 3daf4a2ec12d80a6b234f248f16401a71f1e052b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 14:35:41 +0200 Subject: [PATCH 131/435] openvidu-server: fix NullPointer on stop composite recording --- .../java/io/openvidu/server/recording/CompositeWrapper.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/CompositeWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/CompositeWrapper.java index 7b0b550a..4513f22d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/CompositeWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/CompositeWrapper.java @@ -86,8 +86,8 @@ public class CompositeWrapper { this.recorderEndpoint.record(); } - public synchronized void stopCompositeRecording(CountDownLatch stopLatch, Long timeOfKmsDisconnection) { - if (timeOfKmsDisconnection == 0) { + public synchronized void stopCompositeRecording(CountDownLatch stopLatch, Long kmsDisconnectionTime) { + if (kmsDisconnectionTime == null) { this.recorderEndpoint.addStoppedListener(new EventListener() { @Override public void onEvent(StoppedEvent event) { @@ -101,7 +101,7 @@ public class CompositeWrapper { }); this.recorderEndpoint.stop(); } else { - endTime = timeOfKmsDisconnection; + endTime = kmsDisconnectionTime; stopLatch.countDown(); log.warn("Forcing composed audio-only recording stop after KMS restart in session {}", this.session.getSessionId()); From e8121bf35cb33149e9dcb5b613f8c3e6c990370f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 14:46:04 +0200 Subject: [PATCH 132/435] openvidu-test-e2e: fix Pro /config expected returned value --- .../java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 132a0a6e..33247fe5 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -369,8 +369,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { "{'VERSION':'STR','DOMAIN_OR_PUBLIC_IP':'STR','HTTPS_PORT':0,'OPENVIDU_PUBLICURL':'STR','OPENVIDU_CDR':false,'OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH':0," + "'OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH':0,'OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH':0,'OPENVIDU_SESSIONS_GARBAGE_INTERVAL':0,'OPENVIDU_SESSIONS_GARBAGE_THRESHOLD':0," + "'OPENVIDU_RECORDING':false,'OPENVIDU_RECORDING_VERSION':'STR','OPENVIDU_RECORDING_PATH':'STR','OPENVIDU_RECORDING_PUBLIC_ACCESS':false,'OPENVIDU_RECORDING_NOTIFICATION':'STR'," - + "'OPENVIDU_RECORDING_CUSTOM_LAYOUT':'STR','OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT':0,'OPENVIDU_WEBHOOK':false,'OPENVIDU_WEBHOOK_ENDPOINT':'STR','OPENVIDU_WEBHOOK_HEADERS':[]," - + "'OPENVIDU_WEBHOOK_EVENTS':[],'OPENVIDU_SERVER_DEPENDENCY_VERSION':'STR','KMS_URIS':[],'OPENVIDU_PRO_STATS_MONITORING_INTERVAL':0,'OPENVIDU_PRO_STATS_WEBRTC_INTERVAL':0,'OPENVIDU_PRO_CLUSTER_ID':'STR'," + + "'OPENVIDU_RECORDING_CUSTOM_LAYOUT':'STR','OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT':0,'OPENVIDU_WEBHOOK':false,'OPENVIDU_SERVER_DEPENDENCY_VERSION':'STR','KMS_URIS':[]," + + "'OPENVIDU_PRO_STATS_MONITORING_INTERVAL':0,'OPENVIDU_PRO_STATS_WEBRTC_INTERVAL':0,'OPENVIDU_PRO_CLUSTER_ID':'STR'," + "'OPENVIDU_PRO_CLUSTER_ENVIRONMENT':'STR','OPENVIDU_PRO_CLUSTER_MEDIA_NODES':0,'OPENVIDU_PRO_CLUSTER_PATH':'STR','OPENVIDU_PRO_CLUSTER_AUTOSCALING':false," + "'OPENVIDU_PRO_ELASTICSEARCH':true,'OPENVIDU_PRO_ELASTICSEARCH_VERSION':'STR','OPENVIDU_PRO_ELASTICSEARCH_HOST':'STR','OPENVIDU_PRO_KIBANA':true,'OPENVIDU_PRO_KIBANA_VERSION':'STR'," + "'OPENVIDU_PRO_KIBANA_HOST':'STR','OPENVIDU_PRO_RECORDING_STORAGE':'STR','OPENVIDU_PRO_NETWORK_QUALITY':false}"); From 433d640a8aaf31dfdc701cadd80a60815cab5f2a Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Tue, 13 Oct 2020 16:13:37 +0200 Subject: [PATCH 133/435] openvidu-browser: Wrapped platform library --- .../src/OpenVidu/LocalRecorder.ts | 9 +- openvidu-browser/src/OpenVidu/OpenVidu.ts | 159 +++------------ openvidu-browser/src/OpenVidu/Publisher.ts | 20 +- openvidu-browser/src/OpenVidu/Session.ts | 24 ++- openvidu-browser/src/OpenVidu/Stream.ts | 13 +- .../src/OpenVidu/StreamManager.ts | 17 +- .../src/OpenViduInternal/Utils/Platform.ts | 183 ++++++++++++++++++ .../OpenViduInternal/WebRtcPeer/WebRtcPeer.ts | 11 +- .../WebRtcStats/WebRtcStats.ts | 19 +- 9 files changed, 280 insertions(+), 175 deletions(-) create mode 100644 openvidu-browser/src/OpenViduInternal/Utils/Platform.ts diff --git a/openvidu-browser/src/OpenVidu/LocalRecorder.ts b/openvidu-browser/src/OpenVidu/LocalRecorder.ts index 9a9af25f..d23085b1 100644 --- a/openvidu-browser/src/OpenVidu/LocalRecorder.ts +++ b/openvidu-browser/src/OpenVidu/LocalRecorder.ts @@ -17,8 +17,8 @@ import { Stream } from './Stream'; import { LocalRecorderState } from '../OpenViduInternal/Enums/LocalRecorderState'; -import platform = require('platform'); import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; /** @@ -30,6 +30,11 @@ declare var MediaRecorder: any; */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); + /** * Easy recording of [[Stream]] objects straightaway from the browser. Initialized with [[OpenVidu.initLocalRecorder]] method @@ -211,7 +216,7 @@ export class LocalRecorder { this.videoPreview.id = this.id; this.videoPreview.autoplay = true; - if (platform.name === 'Safari') { + if (platform.isSafariBrowser()) { this.videoPreview.setAttribute('playsinline', 'true'); } diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 1e9213f0..3b5d80c1 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -28,6 +28,7 @@ import { CustomMediaStreamConstraints } from '../OpenViduInternal/Interfaces/Pri import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; import * as screenSharingAuto from '../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto'; import * as screenSharing from '../OpenViduInternal/ScreenSharing/Screen-Capturing'; @@ -39,13 +40,6 @@ import EventEmitter = require('wolfy87-eventemitter'); * @hidden */ import RpcBuilder = require('../OpenViduInternal/KurentoUtils/kurento-jsonrpc'); -/** - * @hidden - */ -import platform = require('platform'); - -platform['isIonicIos'] = (platform.product === 'iPhone' || platform.product === 'iPad') && platform.ua!!.indexOf('Safari') === -1; -platform['isIonicAndroid'] = platform.os!!.family === 'Android' && platform.name == "Android Browser"; /** * @hidden @@ -60,6 +54,11 @@ declare var cordova: any; */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); + /** * Entrypoint of OpenVidu Browser library. * Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]] @@ -122,7 +121,7 @@ export class OpenVidu { logger.info("'OpenVidu' initialized"); logger.info("openvidu-browser version: " + this.libraryVersion); - if (platform.os!!.family === 'iOS' || platform.os!!.family === 'Android') { + if (platform.isMobileDevice()) { // Listen to orientationchange only on mobile devices (window).addEventListener('orientationchange', () => { this.publishers.forEach(publisher => { @@ -135,7 +134,7 @@ export class OpenVidu { const getNewVideoDimensions = (): Promise<{ newWidth: number, newHeight: number }> => { return new Promise((resolve, reject) => { - if (platform['isIonicIos']) { + if (platform.isIonicIos()) { // iOS Ionic. Limitation: must get new dimensions from an existing video element already inserted into DOM resolve({ newWidth: publisher.stream.streamManager.videos[0].video.videoWidth, @@ -146,8 +145,8 @@ export class OpenVidu { // New resolution got from different places for Chrome and Firefox. Chrome needs a videoWidth and videoHeight of a videoElement. // Firefox needs getSettings from the videoTrack const firefoxSettings = publisher.stream.getMediaStream().getVideoTracks()[0].getSettings(); - const newWidth = ((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.width : publisher.videoReference.videoWidth); - const newHeight = ((platform.name!!.toLowerCase().indexOf('firefox') !== -1) ? firefoxSettings.height : publisher.videoReference.videoHeight); + const newWidth = ((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.width : publisher.videoReference.videoWidth); + const newHeight = ((platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? firefoxSettings.height : publisher.videoReference.videoHeight); resolve({ newWidth, newHeight }); } }); @@ -336,8 +335,8 @@ export class OpenVidu { */ checkSystemRequirements(): number { - if (this.isIPhoneOrIPad()) { - if (this.isIOSWithSafari() || platform['isIonicIos']) { + if (platform.isIPhoneOrIPad()) { + if (platform.isIOSWithSafari() || platform.isIonicIos()) { return 1; } return 0; @@ -345,10 +344,10 @@ export class OpenVidu { // Accept: Chrome (desktop and Android), Firefox (desktop and Android), Opera (desktop and Android), // Safari (OSX and iOS), Ionic (Android and iOS), Samsung Internet Browser (Android) - if (this.isSafariBrowser() || this.isChromeBrowser() || this.isChromeMobileBrowser() || - this.isFirefoxBrowser() || this.isFirefoxMobileBrowser() || this.isOperaBrowser() || - this.isOperaMobileBrowser() || this.isAndroidBrowser() || this.isElectron() || - this.isSamsungBrowser() + if (platform.isSafariBrowser() || platform.isChromeBrowser() || platform.isChromeMobileBrowser() || + platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isOperaBrowser() || + platform.isOperaMobileBrowser() || platform.isAndroidBrowser() || platform.isElectron() || + platform.isSamsungBrowser() ) { return 1; } @@ -362,22 +361,8 @@ export class OpenVidu { * Checks if the browser supports screen-sharing. Desktop Chrome, Firefox and Opera support screen-sharing * @returns 1 if the browser supports screen-sharing, 0 otherwise */ - checkScreenSharingCapabilities(): number { - const browser = platform.name; - const version = platform?.version ? parseFloat(platform.version) : -1; - const family = platform.os!!.family; - - // Reject mobile devices - if (family === 'iOS' || family === 'Android') { - return 0; - } - - if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera') && (browser !== 'Electron') && - (browser === 'Safari' && version < 13)) { - return 0; - } else { - return 1; - } + checkScreenSharingCapabilities(): boolean { + return platform.canScreenShare(); } @@ -390,7 +375,7 @@ export class OpenVidu { const devices: Device[] = []; // Ionic Android devices - if (platform['isIonicAndroid'] && typeof cordova != "undefined" && cordova?.plugins?.EnumerateDevicesPlugin) { + if (platform.isIonicAndroid() && typeof cordova != "undefined" && cordova?.plugins?.EnumerateDevicesPlugin) { cordova.plugins.EnumerateDevicesPlugin.getEnumerateDevices().then((pluginDevices: Device[]) => { let pluginAudioDevices: Device[] = []; let videoDevices: Device[] = []; @@ -582,10 +567,10 @@ export class OpenVidu { // Video is deviceId or screen sharing if (options.videoSource === 'screen' || options.videoSource === 'window' || - (platform.name === 'Electron' && options.videoSource.startsWith('screen:'))) { + (platform.isElectron() && options.videoSource.startsWith('screen:'))) { // Video is screen sharing mustAskForAudioTrackLater = !myConstraints.audioTrack && (options.audioSource !== null && options.audioSource !== false); - if (navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') { + if (navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { // getDisplayMedia supported navigator.mediaDevices['getDisplayMedia']({ video: true }) .then(mediaStream => { @@ -872,98 +857,6 @@ export class OpenVidu { return mediaStream; } - /** - * @hidden - */ - public isChromeBrowser(): boolean { - return platform.name === 'Chrome'; - } - - /** - * @hidden - */ - public isSafariBrowser(): boolean { - return platform.name === 'Safari'; - } - - /** - * @hidden - */ - public isChromeMobileBrowser(): boolean { - return platform.name === 'Chrome Mobile'; - } - - /** - * @hidden - */ - public isFirefoxBrowser(): boolean { - return platform.name === 'Firefox'; - } - - /** - * @hidden - */ - public isFirefoxMobileBrowser(): boolean { - return platform.name === 'Firefox Mobile'; - } - - /** - * @hidden - */ - public isOperaBrowser(): boolean { - return platform.name === 'Opera'; - } - - /** - * @hidden - */ - public isOperaMobileBrowser(): boolean { - return platform.name === 'Opera Mobile'; - } - - /** - * @hidden - */ - public isAndroidBrowser(): boolean { - return platform.name === 'Android Browser'; - } - - /** - * @hidden - */ - public isElectron(): boolean { - return platform.name === 'Electron'; - } - - /** - * @hidden - */ - public isSamsungBrowser(): boolean { - return platform.name === 'Samsung Internet Mobile' || platform.name === 'Samsung Internet'; - } - - /** - * @hidden - */ - public isIPhoneOrIPad(): boolean { - const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; - - const isTouchable = 'ontouchend' in document; - const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable; - const isIPhone = /\b(\w*iPhone\w*)\b/.test(userAgent) && /\b(\w*Mobile\w*)\b/.test(userAgent) && isTouchable; - - return isIPad || isIPhone; - } - - /** - * @hidden - */ - public isIOSWithSafari(): boolean { - const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; - return /\b(\w*Apple\w*)\b/.test(navigator.vendor) && /\b(\w*Safari\w*)\b/.test(userAgent) - && !/\b(\w*CriOS\w*)\b/.test(userAgent) && !/\b(\w*FxiOS\w*)\b/.test(userAgent); - } - /** * @hidden */ @@ -984,12 +877,12 @@ export class OpenVidu { // Screen sharing if (!this.checkScreenSharingCapabilities()) { - const error = new OpenViduError(OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0) or Electron. Detected client: ' + platform.name); + const error = new OpenViduError(OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome, Firefox, Opera, Safari (>=13.0) or Electron. Detected client: ' + platform.getName()); logger.error(error); reject(error); } else { - if (platform.name === 'Electron') { + if (platform.isElectron()) { const prefix = "screen:"; const videoSourceString: string = videoSource; const electronScreenId = videoSourceString.substr(videoSourceString.indexOf(prefix) + prefix.length); @@ -1003,7 +896,7 @@ export class OpenVidu { } else { - if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.name!.indexOf('Firefox') !== -1) && !navigator.mediaDevices['getDisplayMedia']) { + if (!!this.advancedConfiguration.screenShareChromeExtension && !(platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) && !navigator.mediaDevices['getDisplayMedia']) { // Custom screen sharing extension for Chrome (and Opera) and no support for MediaDevices.getDisplayMedia() @@ -1042,7 +935,7 @@ export class OpenVidu { resolve(myConstraints); } else { // Default screen sharing extension for Chrome/Opera, or is Firefox < 66 - const firefoxString = platform.name!.indexOf('Firefox') !== -1 ? publisherProperties.videoSource : undefined; + const firefoxString = (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) ? publisherProperties.videoSource : undefined; screenSharingAuto.getScreenId(firefoxString, (error, sourceId, screenConstraints) => { if (!!error) { @@ -1150,7 +1043,7 @@ export class OpenVidu { private isScreenShare(videoSource: string) { return videoSource === 'screen' || videoSource === 'window' || - (platform.name === 'Electron' && videoSource.startsWith('screen:')) + (platform.isElectron() && videoSource.startsWith('screen:')) } } \ No newline at end of file diff --git a/openvidu-browser/src/OpenVidu/Publisher.ts b/openvidu-browser/src/OpenVidu/Publisher.ts index 15aa155a..b6fc847e 100644 --- a/openvidu-browser/src/OpenVidu/Publisher.ts +++ b/openvidu-browser/src/OpenVidu/Publisher.ts @@ -27,15 +27,19 @@ import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPro import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; - -import platform = require('platform'); import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); + /** * Packs local media streams. Participants can publish it to a session. Initialized with [[OpenVidu.initPublisher]] method * @@ -400,7 +404,7 @@ export class Publisher extends StreamManager { if (this.stream.isSendVideo()) { if (!this.stream.isSendScreen()) { - if (platform['isIonicIos'] || platform.name === 'Safari') { + if (platform.isIonicIos() || platform.isSafariBrowser()) { // iOS Ionic or Safari. Limitation: cannot set videoDimensions directly, as the videoReference is not loaded // if not added to DOM. Must add it to DOM and wait for videoWidth and videoHeight properties to be defined @@ -436,7 +440,7 @@ export class Publisher extends StreamManager { // Orientation must be checked for mobile devices (width and height are reversed) const { width, height } = this.getVideoDimensions(mediaStream); - if ((platform.os!!.family === 'iOS' || platform.os!!.family === 'Android') && (window.innerHeight > window.innerWidth)) { + if (platform.isMobileDevice() && (window.innerHeight > window.innerWidth)) { // Mobile portrait mode this.stream.videoDimensions = { width: height || 0, @@ -460,8 +464,8 @@ export class Publisher extends StreamManager { }; this.screenShareResizeInterval = setInterval(() => { const firefoxSettings = mediaStream.getVideoTracks()[0].getSettings(); - const newWidth = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoWidth : firefoxSettings.width; - const newHeight = (platform.name === 'Chrome' || platform.name === 'Opera') ? this.videoReference.videoHeight : firefoxSettings.height; + const newWidth = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoWidth : firefoxSettings.width; + const newHeight = (platform.isChromeBrowser() || platform.isOperaBrowser()) ? this.videoReference.videoHeight : firefoxSettings.height; if (this.stream.isLocalStreamPublished && (newWidth !== this.stream.videoDimensions.width || newHeight !== this.stream.videoDimensions.height)) { @@ -631,7 +635,7 @@ export class Publisher extends StreamManager { startTime = Date.now(); this.setPermissionDialogTimer(timeForDialogEvent); - if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && platform.name !== 'Electron') { + if (this.stream.isSendScreen() && navigator.mediaDevices['getDisplayMedia'] && !platform.isElectron()) { navigator.mediaDevices['getDisplayMedia']({ video: true }) .then(mediaStream => { this.openvidu.addAlreadyProvidedTracks(myConstraints, mediaStream); @@ -680,7 +684,7 @@ export class Publisher extends StreamManager { initializeVideoReference(mediaStream: MediaStream) { this.videoReference = document.createElement('video'); - if (platform.name === 'Safari') { + if (platform.isSafariBrowser()) { this.videoReference.setAttribute('playsinline', 'true'); } diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index e424ea2d..31376bc2 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -40,15 +40,19 @@ import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPro import { NetworkQualityLevelChangedEvent } from '../OpenViduInternal/Events/NetworkQualityLevelChangedEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; - -import platform = require('platform'); import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); + /** * Represents a video call. It can also be seen as a videoconference room where multiple users can connect. * Participants who publish their videos to a session can be seen by the rest of users connected to that specific session. @@ -193,7 +197,7 @@ export class Session extends EventDispatcher { reject(error); }); } else { - reject(new OpenViduError(OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.name + ' (version ' + platform.version + ') for ' + platform.os!!.family + ' is not supported in OpenVidu')); + reject(new OpenViduError(OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu')); } }); } @@ -1122,7 +1126,7 @@ export class Session extends EventDispatcher { const joinParams = { token: (!!token) ? token : '', session: this.sessionId, - platform: !!platform.description ? platform.description : 'unknown', + platform: !!platform.getDescription() ? platform.getDescription() : 'unknown', metadata: !!this.options.metadata ? this.options.metadata : '', secret: this.openvidu.getSecret(), recorder: this.openvidu.getRecorder() @@ -1132,10 +1136,10 @@ export class Session extends EventDispatcher { sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1) { if( - this.openvidu.isChromeBrowser() || this.openvidu.isChromeMobileBrowser() || this.openvidu.isOperaBrowser() || - this.openvidu.isOperaMobileBrowser() || this.openvidu.isElectron() || this.openvidu.isSafariBrowser() || - this.openvidu.isAndroidBrowser() || this.openvidu.isSamsungBrowser() || - (this.openvidu.isIPhoneOrIPad() && this.openvidu.isIOSWithSafari()) + platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || + platform.isOperaMobileBrowser() || platform.isElectron() || platform.isSafariBrowser() || + platform.isAndroidBrowser() || platform.isSamsungBrowser() || + (platform.isIPhoneOrIPad() && platform.isIOSWithSafari()) ) { setTimeout(async () => { const statsMap = await streamManager.stream.getWebRtcPeer().pc.getStats(); @@ -1154,7 +1158,7 @@ export class Session extends EventDispatcher { } }); }, intervalSeconds * 1000); - } else if (this.openvidu.isFirefoxBrowser() || this.openvidu.isFirefoxMobileBrowser()) { + } else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) { // Basic version for Firefox. It does not support stats this.openvidu.sendRequest('videoData', { height: streamManager.stream.videoDimensions.height, @@ -1167,7 +1171,7 @@ export class Session extends EventDispatcher { } }); } else { - console.error('Browser ' + platform.name + ' (version ' + platform.version + ') for ' + platform.os!!.family + ' is not supported in OpenVidu for Network Quality'); + logger.error('Browser ' + platform.getName() + ' (version ' + platform.getVersion() + ') for ' + platform.getFamily() + ' is not supported in OpenVidu for Network Quality'); } } diff --git a/openvidu-browser/src/OpenVidu/Stream.ts b/openvidu-browser/src/OpenVidu/Stream.ts index e4f3cfe5..45702ba8 100644 --- a/openvidu-browser/src/OpenVidu/Stream.ts +++ b/openvidu-browser/src/OpenVidu/Stream.ts @@ -30,19 +30,22 @@ import { PublisherSpeakingEvent } from '../OpenViduInternal/Events/PublisherSpea import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent'; import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; +import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; /** * @hidden */ import hark = require('hark'); -import platform = require('platform'); -import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); - +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); /** * Represents each one of the media streams available in OpenVidu Server for certain session. @@ -108,7 +111,7 @@ export class Stream extends EventDispatcher { * - `"SCREEN"`: when the video source comes from screen-sharing. * - `"CUSTOM"`: when [[PublisherProperties.videoSource]] has been initialized in the Publisher side with a custom MediaStreamTrack when calling [[OpenVidu.initPublisher]]). * - `"IPCAM"`: when the video source comes from an IP camera participant instead of a regular participant (see [IP cameras](/en/stable/advanced-features/ip-cameras/)). - * + * * If [[hasVideo]] is false, this property is undefined */ typeOfVideo?: string; @@ -537,7 +540,7 @@ export class Stream extends EventDispatcher { */ isSendScreen(): boolean { let screen = this.outboundStreamOpts.publisherProperties.videoSource === 'screen'; - if (platform.name === 'Electron') { + if (platform.isElectron()) { screen = typeof this.outboundStreamOpts.publisherProperties.videoSource === 'string' && this.outboundStreamOpts.publisherProperties.videoSource.startsWith('screen:'); } diff --git a/openvidu-browser/src/OpenVidu/StreamManager.ts b/openvidu-browser/src/OpenVidu/StreamManager.ts index 2025d69b..ae4dbc26 100644 --- a/openvidu-browser/src/OpenVidu/StreamManager.ts +++ b/openvidu-browser/src/OpenVidu/StreamManager.ts @@ -22,14 +22,19 @@ import { Event } from '../OpenViduInternal/Events/Event'; import { StreamManagerEvent } from '../OpenViduInternal/Events/StreamManagerEvent'; import { VideoElementEvent } from '../OpenViduInternal/Events/VideoElementEvent'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; - -import platform = require('platform'); import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; +import { PlatformUtils } from '../OpenViduInternal/Utils/Platform'; + /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); + /** * Interface in charge of displaying the media streams in the HTML DOM. This wraps any [[Publisher]] and [[Subscriber]] object. * You can insert as many video players fo the same Stream as you want by calling [[StreamManager.addVideoElement]] or @@ -121,7 +126,7 @@ export class StreamManager extends EventDispatcher { id: '', canplayListenerAdded: false }; - if (platform.name === 'Safari') { + if (platform.isSafariBrowser()) { this.firstVideoElement.video.setAttribute('playsinline', 'true'); } this.targetElement = targEl; @@ -379,7 +384,7 @@ export class StreamManager extends EventDispatcher { video.autoplay = true; video.controls = false; - if (platform.name === 'Safari') { + if (platform.isSafariBrowser()) { video.setAttribute('playsinline', 'true'); } @@ -463,7 +468,7 @@ export class StreamManager extends EventDispatcher { updateMediaStream(mediaStream: MediaStream) { this.videos.forEach(streamManagerVideo => { streamManagerVideo.video.srcObject = mediaStream; - if (platform['isIonicIos']) { + if (platform.isIonicIos()) { // iOS Ionic. LIMITATION: must reinsert the video in the DOM for // the media stream to be updated const vParent = streamManagerVideo.video.parentElement; @@ -506,7 +511,7 @@ export class StreamManager extends EventDispatcher { } private mirrorVideo(video): void { - if (!platform['isIonicIos']) { + if (!platform.isIonicIos()) { video.style.transform = 'rotateY(180deg)'; video.style.webkitTransform = 'rotateY(180deg)'; } diff --git a/openvidu-browser/src/OpenViduInternal/Utils/Platform.ts b/openvidu-browser/src/OpenViduInternal/Utils/Platform.ts new file mode 100644 index 00000000..96f429f4 --- /dev/null +++ b/openvidu-browser/src/OpenViduInternal/Utils/Platform.ts @@ -0,0 +1,183 @@ +import platform = require("platform"); + +export class PlatformUtils { + private static instance: PlatformUtils; + private constructor() {} + + static getInstance(): PlatformUtils { + if (!PlatformUtils.instance) { + PlatformUtils.instance = new PlatformUtils(); + } + return PlatformUtils.instance; + } + + public isChromeBrowser(): boolean { + return platform.name === "Chrome"; + } + + /** + * @hidden + */ + public isSafariBrowser(): boolean { + return platform.name === "Safari"; + } + + /** + * @hidden + */ + public isChromeMobileBrowser(): boolean { + return platform.name === "Chrome Mobile"; + } + + /** + * @hidden + */ + public isFirefoxBrowser(): boolean { + return platform.name === "Firefox"; + } + + /** + * @hidden + */ + public isFirefoxMobileBrowser(): boolean { + return platform.name === "Firefox Mobile"; + } + + /** + * @hidden + */ + public isOperaBrowser(): boolean { + return platform.name === "Opera"; + } + + /** + * @hidden + */ + public isOperaMobileBrowser(): boolean { + return platform.name === "Opera Mobile"; + } + + /** + * @hidden + */ + public isAndroidBrowser(): boolean { + return platform.name === "Android Browser"; + } + + /** + * @hidden + */ + public isElectron(): boolean { + return platform.name === "Electron"; + } + + /** + * @hidden + */ + public isSamsungBrowser(): boolean { + return ( + platform.name === "Samsung Internet Mobile" || + platform.name === "Samsung Internet" + ); + } + + /** + * @hidden + */ + public isIPhoneOrIPad(): boolean { + const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; + + const isTouchable = "ontouchend" in document; + const isIPad = /\b(\w*Macintosh\w*)\b/.test(userAgent) && isTouchable; + const isIPhone = + /\b(\w*iPhone\w*)\b/.test(userAgent) && + /\b(\w*Mobile\w*)\b/.test(userAgent) && + isTouchable; + + return isIPad || isIPhone; + } + + /** + * @hidden + */ + public isIOSWithSafari(): boolean { + const userAgent = !!platform.ua ? platform.ua : navigator.userAgent; + return ( + /\b(\w*Apple\w*)\b/.test(navigator.vendor) && + /\b(\w*Safari\w*)\b/.test(userAgent) && + !/\b(\w*CriOS\w*)\b/.test(userAgent) && + !/\b(\w*FxiOS\w*)\b/.test(userAgent) + ); + } + + /** + * @hidden + */ + public isIonicIos(): boolean { + return this.isIPhoneOrIPad() && platform.ua!!.indexOf("Safari") === -1; + } + + /** + * @hidden + */ + public isIonicAndroid(): boolean { + return ( + platform.os!!.family === "Android" && platform.name == "Android Browser" + ); + } + + /** + * @hidden + */ + public isMobileDevice(): boolean { + return platform.os!!.family === "iOS" || platform.os!!.family === "Android"; + } + + /** + * @hidden + */ + public canScreenShare(): boolean { + const version = platform?.version ? parseFloat(platform.version) : -1; + + // Reject mobile devices + if (this.isMobileDevice()) { + return false; + } + + return ( + this.isChromeBrowser() || + this.isFirefoxBrowser() || + this.isOperaBrowser() || + this.isElectron() || + (this.isSafariBrowser() && version >= 13) + ); + } + + /** + * @hidden + */ + public getName(): string { + return platform.name || ""; + } + + /** + * @hidden + */ + public getVersion(): string { + return platform.version || ""; + } + + /** + * @hidden + */ + public getFamily(): string { + return platform.os!!.family || ""; + } + + /** + * @hidden + */ + public getDescription(): string { + return platform.description || ""; + } +} diff --git a/openvidu-browser/src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts b/openvidu-browser/src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts index 42e161ae..cefdb392 100644 --- a/openvidu-browser/src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts +++ b/openvidu-browser/src/OpenViduInternal/WebRtcPeer/WebRtcPeer.ts @@ -17,12 +17,17 @@ import freeice = require('freeice'); import uuid = require('uuid'); -import platform = require('platform'); import { OpenViduLogger } from '../Logger/OpenViduLogger'; +import { PlatformUtils } from '../Utils/Platform'; + /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); export interface WebRtcPeerConfiguration { @@ -139,7 +144,7 @@ export class WebRtcPeer { logger.debug('RTCPeerConnection constraints: ' + JSON.stringify(constraints)); - if (platform.name === 'Safari' && platform.ua!!.indexOf('Safari') !== -1) { + if (platform.isSafariBrowser() && !platform.isIonicIos()) { // Safari (excluding Ionic), at least on iOS just seems to support unified plan, whereas in other browsers is not yet ready and considered experimental if (offerAudio) { this.pc.addTransceiver('audio', { @@ -217,7 +222,7 @@ export class WebRtcPeer { * @hidden */ setRemoteDescription(answer: RTCSessionDescriptionInit, needsTimeoutOnProcessAnswer: boolean, resolve: (value?: string | PromiseLike | undefined) => void, reject: (reason?: any) => void) { - if (platform['isIonicIos']) { + if (platform.isIonicIos()) { // Ionic iOS platform if (needsTimeoutOnProcessAnswer) { // 400 ms have not elapsed yet since first remote stream triggered Stream#initWebRtcPeerReceive diff --git a/openvidu-browser/src/OpenViduInternal/WebRtcStats/WebRtcStats.ts b/openvidu-browser/src/OpenViduInternal/WebRtcStats/WebRtcStats.ts index 502adc0e..5007192e 100644 --- a/openvidu-browser/src/OpenViduInternal/WebRtcStats/WebRtcStats.ts +++ b/openvidu-browser/src/OpenViduInternal/WebRtcStats/WebRtcStats.ts @@ -18,13 +18,16 @@ // tslint:disable:no-string-literal import { Stream } from '../../OpenVidu/Stream'; -import platform = require('platform'); import { OpenViduLogger } from '../Logger/OpenViduLogger'; +import { PlatformUtils } from '../Utils/Platform'; /** * @hidden */ const logger: OpenViduLogger = OpenViduLogger.getInstance(); - +/** + * @hidden + */ +const platform: PlatformUtils = PlatformUtils.getInstance(); export class WebRtcStats { @@ -103,7 +106,7 @@ export class WebRtcStats { return new Promise((resolve, reject) => { this.getStatsAgnostic(this.stream.getRTCPeerConnection(), (stats) => { - if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) { + if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) { let localCandidateId, remoteCandidateId, googCandidatePair; const localCandidates = {}; const remoteCandidates = {}; @@ -181,7 +184,7 @@ export class WebRtcStats { const f = (stats) => { - if (platform.name!.indexOf('Firefox') !== -1) { + if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) { stats.forEach((stat) => { let json = {}; @@ -278,7 +281,7 @@ export class WebRtcStats { sendPost(JSON.stringify(json)); } }); - } else if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) { + } else if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) { for (const key of Object.keys(stats)) { const stat = stats[key]; if (stat.type === 'ssrc') { @@ -377,7 +380,7 @@ export class WebRtcStats { logger.log(response); const standardReport = {}; - if (platform.name!.indexOf('Firefox') !== -1) { + if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) { Object.keys(response).forEach(key => { logger.log(response[key]); }); @@ -400,13 +403,13 @@ export class WebRtcStats { } private getStatsAgnostic(pc, successCb, failureCb) { - if (platform.name!.indexOf('Firefox') !== -1) { + if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) { // getStats takes args in different order in Chrome and Firefox return pc.getStats(null).then(response => { const report = this.standardizeReport(response); successCb(report); }).catch(failureCb); - } else if ((platform.name!.indexOf('Chrome') !== -1) || (platform.name!.indexOf('Opera') !== -1)) { + } else if (platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser()) { // In Chrome, the first two arguments are reversed return pc.getStats((response) => { const report = this.standardizeReport(response); From d0483f903317e34eef786baa3a3f1cd06fafbb90 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 19:03:49 +0200 Subject: [PATCH 134/435] openvidu-server: close UpdatableTimerTasks on @PreDestroy --- .../io/openvidu/server/core/SessionManager.java | 17 +++++++++++++---- .../openvidu/server/kurento/kms/KmsManager.java | 16 ++++++++++------ .../server/utils/UpdatableTimerTask.java | 2 +- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index b4475461..75e75e44 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -87,6 +87,8 @@ public abstract class SessionManager { public FormatChecker formatChecker = new FormatChecker(); + private UpdatableTimerTask sessionGarbageCollectorTimer; + final protected ConcurrentMap sessions = new ConcurrentHashMap<>(); final protected ConcurrentMap sessionsNotActive = new ConcurrentHashMap<>(); protected ConcurrentMap> sessionidParticipantpublicidParticipant = new ConcurrentHashMap<>(); @@ -165,8 +167,9 @@ public abstract class SessionManager { public abstract String getParticipantPrivateIdFromStreamId(String sessionId, String streamId) throws OpenViduException; - - public abstract void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, Boolean videoActive, Boolean audioActive); + + public abstract void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, + Boolean videoActive, Boolean audioActive); /** * Returns a Session given its id @@ -422,6 +425,9 @@ public abstract class SessionManager { log.warn("Error closing session '{}': {}", sessionId, e.getMessage()); } } + if (this.sessionGarbageCollectorTimer != null) { + this.sessionGarbageCollectorTimer.cancelTimer(); + } } @PostConstruct @@ -431,7 +437,8 @@ public abstract class SessionManager { "Garbage collector for non active sessions is disabled (property 'OPENVIDU_SESSIONS_GARBAGE_INTERVAL' is 0)"); return; } - new UpdatableTimerTask(() -> { + + this.sessionGarbageCollectorTimer = new UpdatableTimerTask(() -> { // Remove all non active sessions created more than the specified time log.info("Running non active sessions garbage collector..."); @@ -477,7 +484,9 @@ public abstract class SessionManager { log.warn("Possible ghost session {}", sessionActive.getSessionId()); } } - }, () -> new Long(openviduConfig.getSessionGarbageInterval() * 1000)).updateTimer(); + }, () -> new Long(openviduConfig.getSessionGarbageInterval() * 1000)); + + this.sessionGarbageCollectorTimer.updateTimer(); log.info( "Garbage collector for non active sessions initialized. Running every {} seconds and cleaning up non active Sessions more than {} seconds old", diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java index a77c718f..c63c3ebf 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/KmsManager.java @@ -57,6 +57,8 @@ public abstract class KmsManager { private Map kmsReconnectionLocks = new ConcurrentHashMap<>(); + private UpdatableTimerTask kurentoReconnectTimer; + public class KmsLoad implements Comparable { private Kms kms; @@ -231,10 +233,9 @@ public abstract class KmsManager { // TODO: this is a fix for the lack of reconnected event kmsReconnectionLocks.putIfAbsent(kms.getId(), new ReentrantLock()); - final UpdatableTimerTask[] TIMER = new UpdatableTimerTask[1]; final AtomicInteger ITERATION = new AtomicInteger(0); - TIMER[0] = new UpdatableTimerTask(() -> { + kurentoReconnectTimer = new UpdatableTimerTask(() -> { boolean lockAcquired = false; try { if (kmsReconnectionLocks.get(kms.getId()).tryLock(5, TimeUnit.SECONDS)) { @@ -245,7 +246,7 @@ public abstract class KmsManager { log.info( "Timer of KMS with uri {} and KurentoClient [{}] cancelled (reconnected event received during interval wait)", kms.getUri(), kms.getKurentoClient().toString()); - TIMER[0].cancelTimer(); + kurentoReconnectTimer.cancelTimer(); return; } @@ -253,14 +254,14 @@ public abstract class KmsManager { log.info( "Timer of KMS with uri {} and KurentoClient [{}] has been closed. Cancelling Timer", kms.getUri(), kms.getKurentoClient().toString()); - TIMER[0].cancelTimer(); + kurentoReconnectTimer.cancelTimer(); return; } kms.getKurentoClient().getServerManager().getInfo(); log.info("According to Timer KMS with uri {} and KurentoClient [{}] is now reconnected", kms.getUri(), kms.getKurentoClient().toString()); - TIMER[0].cancelTimer(); + kurentoReconnectTimer.cancelTimer(); kms.setKurentoClientConnected(true); kms.setTimeOfKurentoClientConnection(System.currentTimeMillis()); @@ -296,7 +297,7 @@ public abstract class KmsManager { } }, () -> new Long(dynamicReconnectLoopSeconds(ITERATION.getAndIncrement()) * 1000)); - TIMER[0].updateTimer(); + kurentoReconnectTimer.updateTimer(); } @Override @@ -365,6 +366,9 @@ public abstract class KmsManager { this.kmss.values().forEach(kms -> { kms.getKurentoClient().destroy(); }); + if (kurentoReconnectTimer != null) { + kurentoReconnectTimer.cancelTimer(); + } } public static String generateKmsId() { diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/UpdatableTimerTask.java b/openvidu-server/src/main/java/io/openvidu/server/utils/UpdatableTimerTask.java index d94122e5..6a59836b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/UpdatableTimerTask.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/UpdatableTimerTask.java @@ -67,7 +67,7 @@ public class UpdatableTimerTask extends TimerTask { try { task.run(); } catch (Exception e) { - log.error("Exception running UpdatableTimerTask: {}", e.getMessage()); + log.error("Exception running UpdatableTimerTask: {} - {}", e.getMessage(), e.getStackTrace()); } updateTimer(); } From 2ba178760bbae533b76fb53182505dad174940f7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 13 Oct 2020 19:44:55 +0200 Subject: [PATCH 135/435] openvidu-server: fix https://github.com/OpenVidu/openvidu/issues/549 --- .../main/java/io/openvidu/server/config/OpenviduConfig.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index a0336722..66906af1 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -38,6 +38,7 @@ import java.util.Map; import javax.annotation.PostConstruct; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.message.BasicHeader; import org.kurento.jsonrpc.JsonUtils; @@ -875,7 +876,7 @@ public class OpenviduConfig { public URI checkWebsocketUri(String uri) throws Exception { try { - if (!uri.startsWith("ws://") || uri.startsWith("wss://")) { + if (!StringUtils.startsWithAny(uri, "ws://", "wss://")) { throw new Exception("WebSocket protocol not found"); } String parsedUri = uri.replaceAll("^ws://", "http://").replaceAll("^wss://", "https://"); From d9127e8c560f62730af3a8552eeab00dbe4e3b63 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 14 Oct 2020 11:45:05 +0200 Subject: [PATCH 136/435] openvidu-server: RequestMapping WebSocket path /info --- .../src/main/java/io/openvidu/server/OpenViduServer.java | 4 ++-- .../java/io/openvidu/server/config/InfoSocketConfig.java | 4 +++- .../java/io/openvidu/server/core/SessionEventsHandler.java | 5 ----- .../io/openvidu/server/rest/ApiRestPathRewriteFilter.java | 2 ++ .../main/java/io/openvidu/server/rest/RequestMappings.java | 5 +++++ 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index b1e70c02..419d6e77 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -69,6 +69,7 @@ import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.recording.service.RecordingManagerUtils; import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage; import io.openvidu.server.rest.ApiRestPathRewriteFilter; +import io.openvidu.server.rest.RequestMappings; import io.openvidu.server.rpc.RpcHandler; import io.openvidu.server.rpc.RpcNotificationService; import io.openvidu.server.utils.CommandExecutor; @@ -91,7 +92,6 @@ public class OpenViduServer implements JsonRpcConfigurer { private static final Logger log = LoggerFactory.getLogger(OpenViduServer.class); - public static final String WS_PATH = "/openvidu"; public static String wsUrl; public static String httpUrl; @@ -241,7 +241,7 @@ public class OpenViduServer implements JsonRpcConfigurer { @Override public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) { registry.addHandler(rpcHandler().withPingWatchdog(true).withInterceptors(new HttpHandshakeInterceptor()), - WS_PATH); + RequestMappings.WS_RPC); } public static String getContainerIp() throws IOException, InterruptedException { diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/InfoSocketConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/InfoSocketConfig.java index 6e39357b..6620a3b5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/InfoSocketConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/InfoSocketConfig.java @@ -24,13 +24,15 @@ import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean; +import io.openvidu.server.rest.RequestMappings; + @Configuration @EnableWebSocket public class InfoSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { - registry.addHandler(infoHandler(), "/info").setAllowedOrigins("*"); + registry.addHandler(infoHandler(), RequestMappings.WS_INFO).setAllowedOrigins("*"); } @Bean diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 32798581..153e69c6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -38,7 +38,6 @@ import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.cdr.CallDetailRecord; -import io.openvidu.server.config.InfoHandler; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.kurento.core.KurentoParticipant; import io.openvidu.server.kurento.endpoint.KurentoFilter; @@ -52,9 +51,6 @@ public class SessionEventsHandler { @Autowired protected RpcNotificationService rpcNotificationService; - @Autowired - protected InfoHandler infoHandler; - @Autowired protected CallDetailRecord CDR; @@ -303,7 +299,6 @@ public class SessionEventsHandler { } public void onNetworkQualityLevelChanged(Session session, JsonObject params) { - session.getParticipants().forEach(p -> { rpcNotificationService.sendNotification(p.getParticipantPrivateId(), ProtocolElements.NETWORKQUALITYLEVELCHANGED_METHOD, params); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java index 8d7a9bcf..a837f7f4 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java @@ -24,6 +24,8 @@ public class ApiRestPathRewriteFilter implements Filter { protected Map PATH_REDIRECTIONS_MAP = new HashMap() { { + // WS + put("/info", RequestMappings.WS_INFO); // APIs put("/api/", RequestMappings.API + "/"); put("/config", RequestMappings.API + "/config"); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java index f9fc5509..f842ee85 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/RequestMappings.java @@ -2,10 +2,15 @@ package io.openvidu.server.rest; public class RequestMappings { + // WebSocket + final public static String WS_RPC = "/openvidu"; + final public static String WS_INFO = "/openvidu/info"; + // REST API final public static String API = "/openvidu/api"; final public static String CDR = "/openvidu/cdr"; final public static String API_ELK = "/openvidu/elk"; final public static String API_INSPECTOR = "/openvidu/inspector-api"; + // Static resources final public static String RECORDINGS = "/openvidu/recordings"; final public static String CUSTOM_LAYOUTS = "/openvidu/layouts"; final public static String FRONTEND_CE = "/dashboard"; From 6f33bf5def551dc53325082fc74c87c8dab6b9eb Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 14 Oct 2020 11:45:58 +0200 Subject: [PATCH 137/435] Dashboard: update info path from /info to /openvidu/info --- .../src/app/components/dashboard/dashboard.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/src/dashboard/src/app/components/dashboard/dashboard.component.ts b/openvidu-server/src/dashboard/src/app/components/dashboard/dashboard.component.ts index 4e896042..fe0b5787 100644 --- a/openvidu-server/src/dashboard/src/app/components/dashboard/dashboard.component.ts +++ b/openvidu-server/src/dashboard/src/app/components/dashboard/dashboard.component.ts @@ -47,7 +47,7 @@ export class DashboardComponent implements OnInit, OnDestroy { const protocol = location.protocol.includes('https') ? 'wss://' : 'ws://'; const port = (location.port) ? (':' + location.port) : ''; - this.websocket = new WebSocket(protocol + location.hostname + port + '/info'); + this.websocket = new WebSocket(protocol + location.hostname + port + '/openvidu/info'); this.websocket.onopen = (event) => { console.log('Info websocket connected'); From 1c72a1ce4e82863430961b530d9a6561d360a2a7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 14 Oct 2020 14:02:19 +0200 Subject: [PATCH 138/435] openvidu-server: new "status" property in Connection entities --- .../io/openvidu/java/client/Connection.java | 18 +++++++++++++ openvidu-node-client/src/Connection.ts | 14 ++++++++++ .../io/openvidu/server/core/Participant.java | 21 ++++++++++++++- .../java/io/openvidu/server/core/Token.java | 2 ++ .../test/e2e/OpenViduProTestAppE2eTest.java | 26 ++++++++++--------- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index a6a1f20b..a63f3849 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -31,6 +31,7 @@ import com.google.gson.JsonObject; public class Connection { private String connectionId; + private String status; private long createdAt; private String location; private String platform; @@ -77,6 +78,7 @@ public class Connection { // These properties won't ever be null this.connectionId = json.get("connectionId").getAsString(); + this.status = json.get("status").getAsString(); String token = json.has("token") ? json.get("token").getAsString() : null; OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); String data = json.get("serverData").getAsString(); @@ -96,6 +98,21 @@ public class Connection { return connectionId; } + /** + * Returns the status of the connection. Can be: + *
    + *
  • pending: if the Connection is waiting for any user to use + * its internal token to connect to the session, calling method Session.connect in OpenVidu Browser.
  • + *
  • active: if the internal token of the Connection has already + * been used by some user to connect to the session, and it cannot be used + * again.
  • + */ + public String getStatus() { + return this.status; + } + /** * Timestamp when this connection was established, in UTC milliseconds (ms since * Jan 1, 1970, 00:00:00 UTC) @@ -195,6 +212,7 @@ public class Connection { protected JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("id", this.getConnectionId()); + json.addProperty("status", this.getStatus()); json.addProperty("createdAt", this.createdAt()); json.addProperty("location", this.getLocation()); json.addProperty("platform", this.getPlatform()); diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 8919edfe..ce71cdc4 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -30,6 +30,18 @@ export class Connection { */ connectionId: string; + /** + * Returns the status of the connection. Can be: + * - `pending`: if the Connection is waiting for any user to use + * its internal token to connect to the session, calling method + * [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect) + * in OpenVidu Browser. + * - `active`: if the internal token of the Connection has already + * been used by some user to connect to the session, and it cannot be used + * again. + */ + status: string; + /** * Timestamp when this connection was established, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) */ @@ -106,6 +118,7 @@ export class Connection { // These properties won't ever be null this.connectionId = json.connectionId; + this.status = json.status; this.token = json.token; this.role = json.role; this.serverData = json.serverData; @@ -118,6 +131,7 @@ export class Connection { equalTo(other: Connection): boolean { let equals: boolean = ( this.connectionId === other.connectionId && + this.status === other.status && this.createdAt === other.createdAt && this.role === other.role && this.serverData === other.serverData && diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 0b1a5a56..55678da1 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -27,10 +27,27 @@ import io.openvidu.server.utils.GeoLocation; public class Participant { + enum ParticipantStatus { + + /** + * The participant has not called Session.publish in the client side yet. The + * internal token is available. + */ + pending, + + /** + * The participant has called Session.publish in the client side and a WebSocket + * connection is established. The internal token has been consumed and cannot be + * used again. + */ + active + } + protected String finalUserId; // ID to match this connection with a final user (HttpSession id) protected String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id) protected String participantPublicId; // ID to identify the user on clients - private String sessionId; // ID of the session to which the participant belongs + protected String sessionId; // ID of the session to which the participant belongs + protected ParticipantStatus status; // Status of the connection protected Long createdAt; // Timestamp when this connection was established protected String clientMetadata = ""; // Metadata provided on client side protected String serverMetadata = ""; // Metadata provided on server side @@ -65,6 +82,7 @@ public class Participant { this.participantPrivatetId = participantPrivatetId; this.participantPublicId = participantPublicId; this.sessionId = sessionId; + this.status = ParticipantStatus.active; if (createdAt != null) { this.createdAt = createdAt; } else { @@ -273,6 +291,7 @@ public class Participant { JsonObject json = new JsonObject(); json.addProperty("id", this.participantPublicId); json.addProperty("object", "connection"); + json.addProperty("status", this.status.name()); json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id" json.addProperty("sessionId", this.sessionId); json.addProperty("createdAt", this.createdAt); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 220d19f8..db31f8ad 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -22,6 +22,7 @@ import org.apache.commons.lang3.RandomStringUtils; import com.google.gson.JsonObject; import io.openvidu.java.client.OpenViduRole; +import io.openvidu.server.core.Participant.ParticipantStatus; import io.openvidu.server.coturn.TurnCredentials; import io.openvidu.server.kurento.core.KurentoTokenOptions; @@ -109,6 +110,7 @@ public class Token { JsonObject json = new JsonObject(); json.addProperty("id", this.getConnectionId()); json.addProperty("object", "connection"); + json.addProperty("status", ParticipantStatus.pending.name()); json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id json.addProperty("sessionId", this.sessionId); json.add("createdAt", null); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 33247fe5..cc253613 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -210,14 +210,14 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'MODERATOR','record':false,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'MODERATOR','record':true,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); // Test with openvidu-java-client @@ -278,24 +278,24 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'MODERATOR','record':false,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'MODERATOR','record':true,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'SUBSCRIBER','record':true,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + + tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','connectionId':'" + tokenConnectionId - + "','role':'PUBLISHER','record':true,'token':'" + token + "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + + tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); // Test with openvidu-node-client @@ -332,6 +332,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertTrue("Wrong record in Connection object", connection.record()); + Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); connection = session.updateConnection(tokenConnectionId, new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); @@ -342,6 +343,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); Assert.assertTrue("Wrong data in Connection object", connection.getServerData().isEmpty()); + Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); user.getEventManager().resetEventThread(); From 4eded98ad9862d827c9db45d5febe55c8d0221fa Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 14 Oct 2020 14:34:21 +0200 Subject: [PATCH 139/435] deployment-openvidu-ce: Update nginx to new API rules and use deprecated APIs. --- .../ce/docker-compose/docker-compose.yml | 3 +- .../openvidu-server-pro/docker-compose.yml | 3 +- .../ce/default-app-without-demos.conf | 54 +++-- .../default_nginx_conf/ce/default-app.conf | 54 +++-- .../default-app-without-demos.conf | 146 +++++++++++ .../support_deprecated_api/default-app.conf | 146 +++++++++++ .../pro/default-app-without-demos.conf | 76 +++--- .../default_nginx_conf/pro/default.conf | 66 +++-- .../default-app-without-demos.conf | 229 ++++++++++++++++++ .../pro/support_deprecated_api/default.conf | 229 ++++++++++++++++++ .../docker/openvidu-proxy/entrypoint.sh | 20 +- 11 files changed, 896 insertions(+), 130 deletions(-) create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 5ddce2df..ac5ced22 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -74,7 +74,7 @@ services: - MAX_PORT=65535 nginx: - image: openvidu/openvidu-proxy:3.0.0 + image: openvidu/openvidu-proxy:4.0.0-beta1 restart: on-failure network_mode: host volumes: @@ -91,3 +91,4 @@ services: - ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-} - PROXY_MODE=CE - WITH_APP=true + - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 7dadbac4..f5ed1e20 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -67,7 +67,7 @@ services: - MAX_PORT=65535 nginx: - image: openvidu/openvidu-proxy:4.0.0-dev1 + image: openvidu/openvidu-proxy:4.0.0-beta1 restart: on-failure network_mode: host volumes: @@ -84,6 +84,7 @@ services: - ALLOWED_ACCESS_TO_RESTAPI=${ALLOWED_ACCESS_TO_RESTAPI:-} - PROXY_MODE=PRO - WITH_APP=true + - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0 diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf index cdff24fe..c54706dd 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf @@ -46,56 +46,58 @@ server { # proxy_pass http://yourapp; # Openvidu call by default #} - # Openvidu Admin Panel + ################################# + # Common rules # + ################################# + # Dashboard rule location /dashboard { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - location /recordings { + # Websocket rule + location ~ /openvidu$ { proxy_pass http://openviduserver; } - location /api { + ################################# + # New API # + ################################# + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /info { + location /openvidu/info { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - location /config { + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # letsencrypt + ################################# + # LetsEncrypt # + ################################# location /.well-known/acme-challenge { root /var/www/certbot; try_files $uri $uri/ =404; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf index 0fcd2142..185bd25c 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf @@ -46,56 +46,58 @@ server { proxy_pass http://yourapp; # Openvidu call by default } - # Openvidu Admin Panel + ################################# + # Common rules # + ################################# + # Dashboard rule location /dashboard { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - location /recordings { + # Websocket rule + location ~ /openvidu$ { proxy_pass http://openviduserver; } - location /api { + ################################# + # New API # + ################################# + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /info { + location /openvidu/info { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - location /config { + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # letsencrypt + ################################# + # LetsEncrypt # + ################################# location /.well-known/acme-challenge { root /var/www/certbot; try_files $uri $uri/ =404; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf new file mode 100644 index 00000000..b7fa2188 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf @@ -0,0 +1,146 @@ +# Your app +#upstream yourapp { +# server localhost:5442; +#} + +upstream openviduserver { + server localhost:5443; +} + +server { + listen {https_port} ssl; + server_name {domain_name}; + + ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + + ssl_prefer_server_ciphers on; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto https; + proxy_headers_hash_bucket_size 512; + proxy_redirect off; + + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Welcome + root /var/www/html; + + # Your app + #location / { + # proxy_pass http://yourapp; # Openvidu call by default + #} + + ################################# + # Common rules # + ################################# + # Dashboard rule + location /dashboard { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + # Websocket rule + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # New API # + ################################# + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # LetsEncrypt # + ################################# + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } +} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf new file mode 100644 index 00000000..14a7d1e3 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf @@ -0,0 +1,146 @@ +# Openvidu call +upstream yourapp { + server localhost:5442; +} + +upstream openviduserver { + server localhost:5443; +} + +server { + listen {https_port} ssl; + server_name {domain_name}; + + ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + + ssl_prefer_server_ciphers on; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto https; + proxy_headers_hash_bucket_size 512; + proxy_redirect off; + + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Welcome + #root /var/www/html; + + # Your app + location / { + proxy_pass http://yourapp; # Openvidu call by default + } + + ################################# + # Common rules # + ################################# + # Dashboard rule + location /dashboard { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + # Websocket rule + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # New API # + ################################# + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # LetsEncrypt # + ################################# + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } +} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf index 9e5b254a..c4731c16 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf @@ -2,6 +2,11 @@ add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; +# Openvidu call +#upstream yourapp { +# server localhost:5442; +#} + upstream kibana { server localhost:5601; } @@ -72,7 +77,14 @@ server { # Welcome root /var/www/html; - # Openvidu Admin Panel + # Your app + # location / { + # proxy_pass http://yourapp; # Openvidu call by default + #} + + ################################# + # Common rules # + ################################# location /dashboard { {rules_access_dashboard} deny all; @@ -86,6 +98,10 @@ server { proxy_pass http://openviduserver; } + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + location /kibana { {rules_access_dashboard} deny all; @@ -94,68 +110,58 @@ server { proxy_pass http://kibana/; } - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + ################################# + # New API # + ################################# + # OpenVidu Server + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; root /opt/openvidu; } - location /recordings { + location /openvidu/recordings { proxy_pass http://openviduserver; } - location /api { + location /openvidu/api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /info { + location /openvidu/info { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - location /config { + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + # OpenVidu Server PRO + location /openvidu/elk { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { + location /openvidu/inspector-api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - # Openvidu Server Pro - location /pro { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - location /api-login { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } + ################################# + # LetsEncrypt # + ################################# - location /elasticsearch { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # letsencrypt location /.well-known/acme-challenge { root /var/www/certbot; try_files $uri $uri/ =404; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf index b1ffd189..fbbc0018 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf @@ -82,7 +82,9 @@ server { proxy_pass http://yourapp; # Openvidu call by default } - # Openvidu Admin Panel + ################################# + # Common rules # + ################################# location /dashboard { {rules_access_dashboard} deny all; @@ -96,6 +98,10 @@ server { proxy_pass http://openviduserver; } + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + location /kibana { {rules_access_dashboard} deny all; @@ -104,68 +110,58 @@ server { proxy_pass http://kibana/; } - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + ################################# + # New API # + ################################# + # OpenVidu Server + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; root /opt/openvidu; } - location /recordings { + location /openvidu/recordings { proxy_pass http://openviduserver; } - location /api { + location /openvidu/api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /info { + location /openvidu/info { {rules_access_dashboard} deny all; proxy_pass http://openviduserver; } - location /config { + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + # OpenVidu Server PRO + location /openvidu/elk { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { + location /openvidu/inspector-api { {rules_acess_api} deny all; proxy_pass http://openviduserver; } - # Openvidu Server Pro - location /pro { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - location /api-login { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } + ################################# + # LetsEncrypt # + ################################# - location /elasticsearch { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # letsencrypt location /.well-known/acme-challenge { root /var/www/certbot; try_files $uri $uri/ =404; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf new file mode 100644 index 00000000..089de746 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf @@ -0,0 +1,229 @@ +add_header X-Frame-Options SAMEORIGIN; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; + +# Openvidu call +#upstream yourapp { +# server localhost:5442; +#} + +upstream kibana { + server localhost:5601; +} + +upstream openviduserver { + server localhost:5443; +} + +server { + # Redirect to https + if ($host = {domain_name}) { + rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; + } # managed by Certbot + + listen {http_port} default_server; + server_name {domain_name}; + + # letsencrypt + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } + + # Kibana panel + location /kibana { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; + } +} + +server { + listen {https_port} ssl default deferred; + server_name {domain_name}; + + ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + + ssl_prefer_server_ciphers on; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto https; + proxy_headers_hash_bucket_size 512; + proxy_redirect off; + + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Welcome + root /var/www/html; + + # Your app + # location / { + # proxy_pass http://yourapp; # Openvidu call by default + #} + + ################################# + # Common rules # + ################################# + location /dashboard { + {rules_access_dashboard} + deny all; + rewrite ^/dashboard/(.*)$ /$1 break; + proxy_pass http://openviduserver/; + } + + location /inspector { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + + location /kibana { + {rules_access_dashboard} + deny all; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; + } + + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + # Openvidu Server Pro + location /pro { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /api-login { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /elasticsearch { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # New API # + ################################# + # OpenVidu Server + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + # OpenVidu Server PRO + location /openvidu/elk { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/inspector-api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + + ################################# + # LetsEncrypt # + ################################# + + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } +} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf new file mode 100644 index 00000000..7718016a --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf @@ -0,0 +1,229 @@ +add_header X-Frame-Options SAMEORIGIN; +add_header X-Content-Type-Options nosniff; +add_header X-XSS-Protection "1; mode=block"; + +# Openvidu call +upstream yourapp { + server localhost:5442; +} + +upstream kibana { + server localhost:5601; +} + +upstream openviduserver { + server localhost:5443; +} + +server { + # Redirect to https + if ($host = {domain_name}) { + rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; + } # managed by Certbot + + listen {http_port} default_server; + server_name {domain_name}; + + # letsencrypt + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } + + # Kibana panel + location /kibana { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; + } +} + +server { + listen {https_port} ssl default deferred; + server_name {domain_name}; + + ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + + ssl_prefer_server_ciphers on; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto https; + proxy_headers_hash_bucket_size 512; + proxy_redirect off; + + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Welcome + #root /var/www/html; + + # Your app + location / { + proxy_pass http://yourapp; # Openvidu call by default + } + + ################################# + # Common rules # + ################################# + location /dashboard { + {rules_access_dashboard} + deny all; + rewrite ^/dashboard/(.*)$ /$1 break; + proxy_pass http://openviduserver/; + } + + location /inspector { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + + location /kibana { + {rules_access_dashboard} + deny all; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; + } + + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + # Openvidu Server Pro + location /pro { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /api-login { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /elasticsearch { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + ################################# + # New API # + ################################# + # OpenVidu Server + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + # OpenVidu Server PRO + location /openvidu/elk { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/inspector-api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + + ################################# + # LetsEncrypt # + ################################# + + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } +} diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 98c8f2f0..37bd5f8f 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -36,6 +36,7 @@ CERTIFICATES_CONF="${CERTIFICATES_FOLDER}/certificates.conf" [ -z "${PROXY_HTTP_PORT}" ] && export PROXY_HTTP_PORT=80 [ -z "${PROXY_HTTPS_PORT}" ] && export PROXY_HTTPS_PORT=443 [ -z "${WITH_APP}" ] && export WITH_APP=true +[ -z "${SUPPORT_DEPRECATED_API}" ] && export SUPPORT_DEPRECATED_API=true [ -z "${PROXY_MODE}" ] && export PROXY_MODE=CE [ -z "${ALLOWED_ACCESS_TO_DASHBOARD}" ] && export ALLOWED_ACCESS_TO_DASHBOARD=all [ -z "${ALLOWED_ACCESS_TO_RESTAPI}" ] && export ALLOWED_ACCESS_TO_RESTAPI=all @@ -153,22 +154,29 @@ chmod -R 777 /etc/letsencrypt # Use certificates in folder '/default_nginx_conf' if [ "${PROXY_MODE}" == "CE" ]; then - if [ "${WITH_APP}" == "true" ]; then + if [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then + mv /default_nginx_conf/ce/support_deprecated_api/default-app.conf /default_nginx_conf/default-app.conf + elif [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then mv /default_nginx_conf/ce/default-app.conf /default_nginx_conf/default-app.conf - mv /default_nginx_conf/ce/default.conf /default_nginx_conf/default.conf - else + elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then + mv /default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf /default_nginx_conf/default-app.conf + elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then mv /default_nginx_conf/ce/default-app-without-demos.conf /default_nginx_conf/default-app.conf - mv /default_nginx_conf/ce/default.conf /default_nginx_conf/default.conf fi + mv /default_nginx_conf/ce/default.conf /default_nginx_conf/default.conf rm -rf /default_nginx_conf/ce rm -rf /default_nginx_conf/pro fi if [ "${PROXY_MODE}" == "PRO" ]; then - if [ "${WITH_APP}" == "true" ]; then + if [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then + mv /default_nginx_conf/pro/support_deprecated_api/default.conf /default_nginx_conf/default.conf + elif [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then mv /default_nginx_conf/pro/default.conf /default_nginx_conf/default.conf - else + elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then + mv /default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf /default_nginx_conf/default.conf + elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then mv /default_nginx_conf/pro/default-app-without-demos.conf /default_nginx_conf/default.conf fi From 511d7cb9c1c52fc3e3dcd0e325c458b3eea54764 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 14 Oct 2020 14:36:03 +0200 Subject: [PATCH 140/435] openvidu-test-e2e: fix ipCameraTest --- .../test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 96c6e2b5..be488351 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -83,7 +83,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','role':'STR','data':'STR','record':true}"; - final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; + final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; @BeforeAll() protected static void setupAll() { From 8fb0398971d1fb73f1e0e54fd50fb49f431fbf9d Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Wed, 14 Oct 2020 17:07:34 +0200 Subject: [PATCH 141/435] openvidu-browser: Updated network quality checks - Excluded ionic ios from stats resolution - Added ionic ios in basic version getting resolution from videoDimensions as Firefox --- openvidu-browser/src/OpenVidu/Session.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 31376bc2..6bc5a075 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -1137,8 +1137,8 @@ export class Session extends EventDispatcher { sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1) { if( platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || - platform.isOperaMobileBrowser() || platform.isElectron() || platform.isSafariBrowser() || - platform.isAndroidBrowser() || platform.isSamsungBrowser() || + platform.isOperaMobileBrowser() || platform.isElectron() || (platform.isSafariBrowser() && !platform.isIonicIos()) || + platform.isAndroidBrowser() || platform.isSamsungBrowser() || platform.isIonicAndroid() || (platform.isIPhoneOrIPad() && platform.isIOSWithSafari()) ) { setTimeout(async () => { @@ -1158,8 +1158,8 @@ export class Session extends EventDispatcher { } }); }, intervalSeconds * 1000); - } else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser()) { - // Basic version for Firefox. It does not support stats + } else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isIonicIos()) { + // Basic version for Firefox and Ionic iOS. They do not support stats this.openvidu.sendRequest('videoData', { height: streamManager.stream.videoDimensions.height, width: streamManager.stream.videoDimensions.width, From ff1b9821863c8c8a17ad7700f788bc80b475d17e Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 14 Oct 2020 17:30:28 +0200 Subject: [PATCH 142/435] deployment-openvidu-ce-and-pro: Fixing some turn problems in OpenVidu CE --- .../deployments/ce/aws/CF-OpenVidu.yaml.template | 4 ++-- .../deployments/ce/docker-compose/docker-compose.yml | 5 +++-- .../docker-compose/openvidu-server-pro/docker-compose.yml | 7 ++++--- openvidu-server/docker/openvidu-coturn/README.md | 4 ++-- .../docker/openvidu-coturn/configuration-files.sh | 5 ++++- openvidu-server/docker/openvidu-coturn/entrypoint.sh | 4 ++-- 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template index f6607d9c..d5e3a147 100644 --- a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template +++ b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template @@ -373,11 +373,11 @@ Resources: CidrIp: 0.0.0.0/0 - IpProtocol: udp FromPort: 40000 - ToPort: 65535 + ToPort: 57000 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 40000 - ToPort: 65535 + ToPort: 57000 CidrIp: 0.0.0.0/0 Outputs: diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index ac5ced22..386a7050 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -52,6 +52,7 @@ services: environment: - KMS_MIN_PORT=40000 - KMS_MAX_PORT=57000 + - KMS_EXTERNAL_ADDRESS=auto - GST_DEBUG=${KMS_DEBUG_LEVEL:-} redis: @@ -62,7 +63,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:2.0.0-dev1 + image: openvidu/openvidu-coturn:2.0.0-dev2 restart: on-failure network_mode: host environment: @@ -74,7 +75,7 @@ services: - MAX_PORT=65535 nginx: - image: openvidu/openvidu-proxy:4.0.0-beta1 + image: openvidu/openvidu-proxy:4.0.0-dev3 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index f5ed1e20..2fb2dddd 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -55,7 +55,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:2.0.0-dev1 + image: openvidu/openvidu-coturn:2.0.0-dev2 restart: on-failure network_mode: host environment: @@ -63,11 +63,12 @@ services: - TURN_LISTEN_PORT=3478 - DB_NAME=0 - DB_PASSWORD=${OPENVIDU_SECRET} - - MIN_PORT=57001 + - MIN_PORT=40000 - MAX_PORT=65535 + - TURN_PUBLIC_IP=auto nginx: - image: openvidu/openvidu-proxy:4.0.0-beta1 + image: openvidu/openvidu-proxy:4.0.0-dev3 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/docker/openvidu-coturn/README.md b/openvidu-server/docker/openvidu-coturn/README.md index fb8a93d6..4b1ea95e 100644 --- a/openvidu-server/docker/openvidu-coturn/README.md +++ b/openvidu-server/docker/openvidu-coturn/README.md @@ -28,12 +28,12 @@ docker run --rm --name some-redis -d -p 6379:6379 redis Get the ip of the container and after that, run coturn, you can use url as ip too, in this example I am running coturn with nip.io: ``` -docker run -it -e REDIS_IP=172.17.0.2 -e DB_NAME=0 -e DB_PASSWORD=turn -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn +docker run -it -e REDIS_IP=172.17.0.2 -e DB_NAME=0 -e DB_PASSWORD=turn -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_PUBLIC_IP=auto -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn ``` ## Execute turn locally with fixed username and password ``` -docker run -it -e TURN_USERNAME_PASSWORD=: -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn +docker run -it -e TURN_PUBLIC_IP=auto -e TURN_USERNAME_PASSWORD=: -e MIN_PORT=40000 -e MAX_PORT=65535 -e TURN_LISTEN_PORT=3478 --network=host openvidu/openvidu-coturn ``` diff --git a/openvidu-server/docker/openvidu-coturn/configuration-files.sh b/openvidu-server/docker/openvidu-coturn/configuration-files.sh index 18a7b779..4a88e4fb 100644 --- a/openvidu-server/docker/openvidu-coturn/configuration-files.sh +++ b/openvidu-server/docker/openvidu-coturn/configuration-files.sh @@ -7,7 +7,6 @@ EOF # Turn server configuration cat>/etc/turnserver.conf<> /etc/turnserver.conf +fi + if [[ ! -z "${REDIS_IP}" ]] && [[ ! -z "${DB_NAME}" ]] && [[ ! -z "${DB_PASSWORD}" ]]; then echo "redis-userdb=\"ip=${REDIS_IP} dbname=${DB_NAME} password=${DB_PASSWORD} connect_timeout=30\"" >> /etc/turnserver.conf fi diff --git a/openvidu-server/docker/openvidu-coturn/entrypoint.sh b/openvidu-server/docker/openvidu-coturn/entrypoint.sh index f935fcf0..c5799225 100644 --- a/openvidu-server/docker/openvidu-coturn/entrypoint.sh +++ b/openvidu-server/docker/openvidu-coturn/entrypoint.sh @@ -5,9 +5,9 @@ DEBUG=${DEBUG:-false} [ "$DEBUG" == "true" ] && set -x #Check parameters -[[ ! -z "${TURN_PUBLIC_IP}" ]] || export TURN_PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) +[[ "${TURN_PUBLIC_IP}" == "auto" ]] && export TURN_PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) -echo "TURN public IP: ${TURN_PUBLIC_IP}" +echo "TURN public IP: ${TURN_PUBLIC_IP:-"empty"}" [[ ! -z "${TURN_LISTEN_PORT}" ]] && echo "TURN listening port: ${TURN_LISTEN_PORT}" || { echo "TURN_LISTEN_PORT environment variable is not defined"; exit 1; } From a878cbe68a9c1261563c17be3f0d166bb4ce1ebc Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 14 Oct 2020 17:30:43 +0200 Subject: [PATCH 143/435] openvidu-server: protect old paths with BasicAuth only if SUPPORT_DEPRECATED_API=true --- .../server/config/SecurityConfig.java | 48 +++++++++++-------- .../server/rest/ApiRestPathRewriteFilter.java | 37 ++++++++++++-- 2 files changed, 62 insertions(+), 23 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/SecurityConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/SecurityConfig.java index 74042b51..c06b1a6e 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/SecurityConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/SecurityConfig.java @@ -20,8 +20,12 @@ package io.openvidu.server.config; import java.util.Arrays; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -31,41 +35,45 @@ import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter; -@Configuration +import io.openvidu.server.rest.ApiRestPathRewriteFilter; +import io.openvidu.server.rest.RequestMappings; + +@Configuration() +@ConditionalOnMissingBean(name = "securityConfigPro") +@Order(Ordered.LOWEST_PRECEDENCE) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired - OpenviduConfig openviduConf; + protected OpenviduConfig openviduConf; + + @Autowired + protected Environment environment; @Override protected void configure(HttpSecurity http) throws Exception { - // Security for API REST ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry conf = http.cors().and() .csrf().disable().authorizeRequests() - // /api - .antMatchers("/api/**").authenticated() - // /config - .antMatchers(HttpMethod.GET, "/config/openvidu-publicurl").permitAll() - .antMatchers(HttpMethod.GET, "/config/**").authenticated() - // /cdr - .antMatchers(HttpMethod.GET, "/cdr/**").authenticated() - // /accept-certificate - .antMatchers(HttpMethod.GET, "/accept-certificate").permitAll() - // Dashboard - .antMatchers(HttpMethod.GET, "/dashboard/**").authenticated(); + .antMatchers(HttpMethod.GET, RequestMappings.API + "/config/openvidu-publicurl").permitAll() + .antMatchers(HttpMethod.GET, RequestMappings.ACCEPT_CERTIFICATE).permitAll() + .antMatchers(RequestMappings.API + "/**").authenticated() + .antMatchers(HttpMethod.GET, RequestMappings.CDR + "/**").authenticated() + .antMatchers(HttpMethod.GET, RequestMappings.FRONTEND_CE + "/**").authenticated() + .antMatchers(HttpMethod.GET, RequestMappings.CUSTOM_LAYOUTS + "/**").authenticated(); - // Security for recording layouts - conf.antMatchers("/layouts/**").authenticated(); - - // Security for recorded video files + // Secure recordings depending on OPENVIDU_RECORDING_PUBLIC_ACCESS if (openviduConf.getOpenViduRecordingPublicAccess()) { - conf = conf.antMatchers("/recordings/**").permitAll(); + conf = conf.antMatchers(HttpMethod.GET, RequestMappings.RECORDINGS + "/**").permitAll(); } else { - conf = conf.antMatchers("/recordings/**").authenticated(); + conf = conf.antMatchers(HttpMethod.GET, RequestMappings.RECORDINGS + "/**").authenticated(); } conf.and().httpBasic(); + + // TODO: remove this when deprecating SUPPORT_DEPRECATED_API + if (Boolean.valueOf(environment.getProperty("SUPPORT_DEPRECATED_API"))) { + ApiRestPathRewriteFilter.protectOldPathsCe(conf, openviduConf); + } } @Bean diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java index a837f7f4..2abe443b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/ApiRestPathRewriteFilter.java @@ -16,8 +16,13 @@ import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.web.util.WebUtils; +import io.openvidu.server.config.OpenviduConfig; + public class ApiRestPathRewriteFilter implements Filter { protected static final Logger log = LoggerFactory.getLogger(ApiRestPathRewriteFilter.class); @@ -52,6 +57,11 @@ public class ApiRestPathRewriteFilter implements Filter { "Deprecated path support will be removed in a future release. You can disable old path support to test compatibility with property SUPPORT_DEPRECATED_API=false"); } + @Override + public void destroy() { + // Nothing to free up... + } + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @@ -106,9 +116,30 @@ public class ApiRestPathRewriteFilter implements Filter { } } - @Override - public void destroy() { - // Nothing to free up... + public static void protectOldPathsCe( + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry conf, + OpenviduConfig openviduConf) throws Exception { + + conf.antMatchers("/api/**").authenticated() + // /config + .antMatchers(HttpMethod.GET, "/config/openvidu-publicurl").permitAll() + .antMatchers(HttpMethod.GET, "/config/**").authenticated() + // /cdr + .antMatchers(HttpMethod.GET, "/cdr/**").authenticated() + // /accept-certificate + .antMatchers(HttpMethod.GET, "/accept-certificate").permitAll() + // Dashboard + .antMatchers(HttpMethod.GET, "/dashboard/**").authenticated(); + + // Security for recording layouts + conf.antMatchers("/layouts/**").authenticated(); + + // Security for recorded video files + if (openviduConf.getOpenViduRecordingPublicAccess()) { + conf = conf.antMatchers("/recordings/**").permitAll(); + } else { + conf = conf.antMatchers("/recordings/**").authenticated(); + } } } From cd101afac25709fb2587d47bc3e72ba13ac098ed Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 14 Oct 2020 20:02:08 +0200 Subject: [PATCH 144/435] deployment-openvidu-ce: bump openvidu-version 2.16.0-dev1 --- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 386a7050..83835225 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server:2.15.0 + image: openvidu/openvidu-server:2.16.0-dev1 restart: on-failure network_mode: host entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh'] From 8625a5f18e9f64108654249ce50bbebe25cee9a8 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 14 Oct 2020 22:44:17 +0200 Subject: [PATCH 145/435] openvidu-ce-deployment: Don't use externalAddress until find a better solution --- openvidu-server/deployments/ce/docker-compose/docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 83835225..6ea8a6b5 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -52,7 +52,6 @@ services: environment: - KMS_MIN_PORT=40000 - KMS_MAX_PORT=57000 - - KMS_EXTERNAL_ADDRESS=auto - GST_DEBUG=${KMS_DEBUG_LEVEL:-} redis: From bf6defc4ded13ecc1eb5040d2cdbbc0495bde23d Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 15 Oct 2020 02:23:43 +0200 Subject: [PATCH 146/435] deployment-openvidu-ce-and-pro: Fix nginx error on changing certificate types --- .../docker/openvidu-proxy/entrypoint.sh | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 37bd5f8f..85681102 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -28,10 +28,11 @@ if [[ "${CERTIFICATE_TYPE}" == "letsencrypt" && \ fi # Global variables -CERTIFICATES_FOLDER=/etc/letsencrypt/live -CERTIFICATES_CONF="${CERTIFICATES_FOLDER}/certificates.conf" +CERTIFICATES_FOLDER=/etc/letsencrypt +CERTIFICATES_LIVE_FOLDER="${CERTIFICATES_FOLDER}/live" +CERTIFICATES_CONF="${CERTIFICATES_LIVE_FOLDER}/certificates.conf" -[ ! -d "${CERTIFICATES_FOLDER}" ] && mkdir -p "${CERTIFICATES_FOLDER}" +[ ! -d "${CERTIFICATES_LIVE_FOLDER}" ] && mkdir -p "${CERTIFICATES_LIVE_FOLDER}" [ ! -f "${CERTIFICATES_CONF}" ] && touch "${CERTIFICATES_CONF}" [ -z "${PROXY_HTTP_PORT}" ] && export PROXY_HTTP_PORT=80 [ -z "${PROXY_HTTPS_PORT}" ] && export PROXY_HTTPS_PORT=443 @@ -41,10 +42,6 @@ CERTIFICATES_CONF="${CERTIFICATES_FOLDER}/certificates.conf" [ -z "${ALLOWED_ACCESS_TO_DASHBOARD}" ] && export ALLOWED_ACCESS_TO_DASHBOARD=all [ -z "${ALLOWED_ACCESS_TO_RESTAPI}" ] && export ALLOWED_ACCESS_TO_RESTAPI=all -# Start with default certbot conf -sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/conf.d/default.conf -nginx -g "daemon on;" - # Show input enviroment variables printf "\n =======================================" printf "\n = INPUT VARIABLES =" @@ -71,6 +68,7 @@ printf "\n =======================================" printf "\n" printf "\n Configure %s domain..." "${DOMAIN_OR_PUBLIC_IP}" +OLD_DOMAIN_OR_PUBLIC_IP=$(grep "${DOMAIN_OR_PUBLIC_IP}" "${CERTIFICATES_CONF}" | cut -f1 -d$'\t') CERTIFICATED_OLD_CONFIG=$(grep "${DOMAIN_OR_PUBLIC_IP}" "${CERTIFICATES_CONF}" | cut -f2 -d$'\t') printf "\n - New configuration: %s" "${CERTIFICATE_TYPE}" @@ -80,32 +78,39 @@ if [ -z "${CERTIFICATED_OLD_CONFIG}" ]; then else printf "\n - Old configuration: %s" "${CERTIFICATED_OLD_CONFIG}" - if [ "${CERTIFICATED_OLD_CONFIG}" != "${CERTIFICATE_TYPE}" ]; then - printf "\n - Restarting configuration... Removing old certificated..." + if [ "${CERTIFICATED_OLD_CONFIG}" != "${CERTIFICATE_TYPE}" ] || \ + [ "${OLD_DOMAIN_OR_PUBLIC_IP}" != "${DOMAIN_OR_PUBLIC_IP}" ]; then - rm -rf "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/"* + printf "\n - Restarting configuration... Removing old certificated..." + # Recreate certificates folder + rm -rf "${CERTIFICATES_FOLDER:?}" + mkdir -p "${CERTIFICATES_LIVE_FOLDER}" + touch "${CERTIFICATES_CONF}" fi fi # Save actual conf -sed -i "/${DOMAIN_OR_PUBLIC_IP}/d" "${CERTIFICATES_CONF}" -echo -e "${DOMAIN_OR_PUBLIC_IP}\t${CERTIFICATE_TYPE}" >> "${CERTIFICATES_CONF}" +echo -e "${DOMAIN_OR_PUBLIC_IP}\t${CERTIFICATE_TYPE}" > "${CERTIFICATES_CONF}" + +# Start with default certbot conf +sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/conf.d/default.conf +nginx -g "daemon on;" case ${CERTIFICATE_TYPE} in "selfsigned") - if [[ ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ - ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then + if [[ ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ + ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then printf "\n - Generating selfsigned certificate...\n" # Delete and create certificate folder - rm -rf "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true - mkdir -p "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" + rm -rf "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true + mkdir -p "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" openssl req -new -nodes -x509 \ -subj "/CN=${DOMAIN_OR_PUBLIC_IP}" -days 365 \ - -keyout "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" \ - -out "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" \ + -keyout "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" \ + -out "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" \ -extensions v3_ca else printf "\n - Selfsigned certificate already exists, using them..." @@ -113,16 +118,16 @@ case ${CERTIFICATE_TYPE} in ;; "owncert") - if [[ ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ - ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then + if [[ ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ + ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then printf "\n - Copying owmcert certificate..." # Delete and create certificate folder - rm -rf "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true - mkdir -p "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" + rm -rf "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true + mkdir -p "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" - cp /owncert/certificate.key "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" - cp /owncert/certificate.cert "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" + cp /owncert/certificate.key "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" + cp /owncert/certificate.cert "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" else printf "\n - Owmcert certificate already exists, using them..." fi @@ -133,12 +138,12 @@ case ${CERTIFICATE_TYPE} in /usr/sbin/crond -f & echo '0 */12 * * * certbot renew --post-hook "nginx -s reload" >> /var/log/cron-letsencrypt.log' | crontab - # Auto renew cert - if [[ ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ - ! -f "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then + if [[ ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/privkey.pem" && \ + ! -f "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}/fullchain.pem" ]]; then printf "\n - Requesting LetsEncrypt certificate..." # Delete certificate folder - rm -rf "${CERTIFICATES_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true + rm -rf "${CERTIFICATES_LIVE_FOLDER:?}/${DOMAIN_OR_PUBLIC_IP}" | true certbot certonly -n --webroot -w /var/www/certbot \ -m "${LETSENCRYPT_EMAIL}" \ From 0463230e9d4e5f87428d4de286293dd5fe909709 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 15 Oct 2020 13:16:29 +0200 Subject: [PATCH 147/435] OpenVidu SDKs: getConnection and getConnections --- .../io/openvidu/java/client/Connection.java | 2 +- .../io/openvidu/java/client/OpenVidu.java | 2 +- .../java/io/openvidu/java/client/Session.java | 85 +++++++++------ openvidu-node-client/src/Connection.ts | 2 +- openvidu-node-client/src/OpenVidu.ts | 2 +- openvidu-node-client/src/Session.ts | 100 +++++++++++------- 6 files changed, 116 insertions(+), 77 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index a63f3849..27a8879d 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -26,7 +26,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; /** - * See {@link io.openvidu.java.client.Session#getActiveConnections()} + * See {@link io.openvidu.java.client.Session#getConnections()} */ public class Connection { diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 1ba75945..005c6430 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -537,7 +537,7 @@ public class OpenVidu { * @throws OpenViduJavaClientException */ public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException { - HttpGet request = new HttpGet(this.hostname + API_SESSIONS); + HttpGet request = new HttpGet(this.hostname + API_SESSIONS + "?pendingConnections=true"); HttpResponse response; try { diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index b8256b14..75eef6da 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -19,7 +19,6 @@ package io.openvidu.java.client; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -49,7 +48,7 @@ public class Session { private long createdAt; private OpenVidu openVidu; private SessionProperties properties; - private Map activeConnections = new ConcurrentHashMap<>(); + private Map connections = new ConcurrentHashMap<>(); private boolean recording = false; protected Session(OpenVidu openVidu) throws OpenViduJavaClientException, OpenViduHttpException { @@ -165,7 +164,7 @@ public class Session { * Session.forceDisconnect()} to invalidate the token if no client has used it * yet or force the connected client to leave the session if it has. *
  • Call - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions) * Session.updateConnection()} to update the * {@link io.openvidu.java.client.Connection Connection} options. And this is * valid for unused tokens, but also for already used tokens, so you can @@ -254,7 +253,7 @@ public class Session { * those values to call * {@link io.openvidu.java.client.Session#forceDisconnect(Connection)}, * {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)}.
    + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)}.
    *
    * * To update all Session objects owned by OpenVidu object at once, call @@ -269,7 +268,8 @@ public class Session { */ public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException { final String beforeJSON = this.toJson(); - HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId); + HttpGet request = new HttpGet( + this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "?pendingConnections=true"); request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"); HttpResponse response; @@ -371,13 +371,13 @@ public class Session { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { // Remove connection from activeConnections map - Connection connectionClosed = this.activeConnections.remove(connectionId); + Connection connectionClosed = this.connections.remove(connectionId); // Remove every Publisher of the closed connection from every subscriber list of // other connections if (connectionClosed != null) { for (Publisher publisher : connectionClosed.getPublishers()) { String streamId = publisher.getStreamId(); - for (Connection connection : this.activeConnections.values()) { + for (Connection connection : this.connections.values()) { connection.setSubscribers(connection.getSubscribers().stream() .filter(subscriber -> !streamId.equals(subscriber)).collect(Collectors.toList())); } @@ -464,7 +464,7 @@ public class Session { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { - for (Connection connection : this.activeConnections.values()) { + for (Connection connection : this.connections.values()) { // Try to remove the Publisher from the Connection publishers collection if (connection.publishers.remove(streamId) != null) { continue; @@ -493,21 +493,14 @@ public class Session { *
*
* - * The connectionId parameter can be obtained from a Connection - * object with {@link io.openvidu.java.client.Connection#getConnectionId() - * Connection.getConnectionId()}, in which case the updated properties will - * modify an active Connection. But connectionId can also be - * obtained from a Token with {@link Token#getConnectionId()}, which allows - * modifying a still not used token.
- *
- * * This method automatically updates the properties of the local affected * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the * changes consequence of the execution of this method applied in the local * objects. * - * @param connectionId The Connection (or a still not used Token) to modify + * @param connectionId The Connection to modify * @param connectionOptions A ConnectionOptions object with the new values to * apply * @@ -551,12 +544,12 @@ public class Session { JsonObject json = httpResponseToJson(response); // Update the actual Connection object with the new options - Connection existingConnection = this.activeConnections.get(connectionId); + Connection existingConnection = this.connections.get(connectionId); if (existingConnection == null) { // The updated Connection is not available in local map Connection newConnection = new Connection(json); - this.activeConnections.put(connectionId, newConnection); + this.connections.put(connectionId, newConnection); return newConnection; } else { // The updated Connection was available in local map @@ -570,27 +563,55 @@ public class Session { } /** - * Returns the list of active connections to the session. This value - * will remain unchanged since the last time method - * {@link io.openvidu.java.client.Session#fetch()} was called. - * Exceptions to this rule are: + * Returns a Connection of the Session. This method only returns the local + * available object and does not query OpenVidu Server. To get the current + * actual value you must call first + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + */ + public Connection getConnection(String id) { + return this.connections.get(id); + } + + /** + * Returns all the Connections of the Session. This method only returns the + * local available objects and does not query OpenVidu Server. To get the + * current actual value you must call first + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + */ + public List getConnections() { + return this.connections.values().stream().collect(Collectors.toList()); + } + + /** + * Returns the list of active Connections of the Session. These are the + * Connections returning active in response to + * {@link io.openvidu.java.client.Connection#getStatus()}. This method only + * returns the local available objects and does not query OpenVidu Server. + * The list of active Connections will remain unchanged since the last + * time method {@link io.openvidu.java.client.Session#fetch() Session.fetch()} + * or {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was + * called. Exceptions to this rule are: *
    *
  • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} * automatically updates each affected local Connection object.
  • *
  • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} * automatically updates each affected local Connection object.
  • *
  • Calling - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)} * automatically updates the attributes of the affected local Connection * object.
  • *
*
* To get the list of active connections with their current actual value, you - * must call first {@link io.openvidu.java.client.Session#fetch()} and then - * {@link io.openvidu.java.client.Session#getActiveConnections()}. + * must call first {@link io.openvidu.java.client.Session#fetch() + * Session.fetch()} or {@link io.openvidu.java.client.OpenVidu#fetch() + * OpenVidu.fetch()}. */ public List getActiveConnections() { - return new ArrayList<>(this.activeConnections.values()); + return this.connections.values().stream().filter(con -> "active".equals(con.getStatus())) + .collect(Collectors.toList()); } /** @@ -694,10 +715,10 @@ public class Session { } this.properties = builder.build(); JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray(); - this.activeConnections.clear(); + this.connections.clear(); jsonArrayConnections.forEach(connectionJsonElement -> { Connection connectionObj = new Connection(connectionJsonElement.getAsJsonObject()); - this.activeConnections.put(connectionObj.getConnectionId(), connectionObj); + this.connections.put(connectionObj.getConnectionId(), connectionObj); }); return this; } @@ -714,9 +735,9 @@ public class Session { json.addProperty("defaultRecordingLayout", this.properties.defaultRecordingLayout().name()); json.addProperty("defaultCustomLayout", this.properties.defaultCustomLayout()); JsonObject connections = new JsonObject(); - connections.addProperty("numberOfElements", this.getActiveConnections().size()); + connections.addProperty("numberOfElements", this.getConnections().size()); JsonArray jsonArrayConnections = new JsonArray(); - this.getActiveConnections().forEach(con -> { + this.getConnections().forEach(con -> { jsonArrayConnections.add(con.toJson()); }); connections.add("content", jsonArrayConnections); diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index ce71cdc4..928f2665 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -20,7 +20,7 @@ import { Publisher } from './Publisher'; import { ConnectionOptions } from './ConnectionOptions'; /** - * See [[Session.activeConnections]] + * See [[Session.connections]] */ export class Connection { diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index 4f572dcb..5e21a6c1 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -419,7 +419,7 @@ export class OpenVidu { public fetch(): Promise { return new Promise((resolve, reject) => { axios.get( - this.host + OpenVidu.API_SESSIONS, + this.host + OpenVidu.API_SESSIONS + '?pendingConnections=true', { headers: { Authorization: this.basicAuth diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 79b8dfa9..6fac15ac 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -47,15 +47,25 @@ export class Session { properties: SessionProperties; /** - * Array of active connections to the session. This property always initialize as an empty array and - * **will remain unchanged since the last time method [[Session.fetch]] was called**. Exceptions to this rule are: + * Array of Connections to the Session. This property always initialize as an empty array and + * **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**. + * Exceptions to this rule are: * * - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object. * - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object. * - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object. * - * To get the array of active connections with their current actual value, you must call [[Session.fetch]] before consulting - * property [[activeConnections]] + * To get the array of Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]] + * before consulting property [[connections]] + */ + connections: Connection[] = []; + + /** + * Array containing the active Connections of the Session. It is a subset of [[Session.connections]] array containing only + * those Connections with property [[Connection.status]] to `active`. + * + * To get the array of active Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]] + * before consulting property [[activeConnections]] */ activeConnections: Connection[] = []; @@ -190,9 +200,9 @@ export class Session { } /** - * Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of active - * connections of the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]], [[Session.forceUnpublish]] or - * [[Session.updateConnection]]. + * Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of + * Connections of the Session ([[Session.connections]], [[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]], + * [[Session.forceUnpublish]] or [[Session.updateConnection]]. * * To update all Session objects owned by OpenVidu object at once, call [[OpenVidu.fetch]] * @@ -203,7 +213,7 @@ export class Session { return new Promise((resolve, reject) => { const beforeJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference); axios.get( - this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId, + this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '?pendingConnections=true', { headers: { 'Authorization': this.ov.basicAuth, @@ -230,22 +240,14 @@ export class Session { } /** - * Forces the user with Connection `connectionId` to leave the session, or invalidates the [[Token]] associated with that - * `connectionId` if no user has used it yet. - * - * In the first case you can get `connection` parameter from [[Session.activeConnections]] array (remember to call [[Session.fetch]] before - * to fetch the current actual properties of the Session from OpenVidu Server). As a result, OpenVidu Browser will trigger the proper - * events on the client-side (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`. - * - * In the second case you can get `connectionId` parameter with [[Token.connectionId]]. As a result, the token will be invalidated - * and no user will be able to connect to the session with it. + * Removes a Connection from the Session. * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @param connection The Connection object to disconnect from the session, or its `connectionId` property * - * @returns A Promise that is resolved if the user was successfully disconnected and rejected with an Error object if not + * @returns A Promise that is resolved if the Connection was successfully removed from the Session and rejected with an Error object if not */ public forceDisconnect(connection: string | Connection): Promise { return new Promise((resolve, reject) => { @@ -261,9 +263,9 @@ export class Session { .then(res => { if (res.status === 204) { // SUCCESS response from openvidu-server - // Remove connection from activeConnections array + // Remove connection from connections array let connectionClosed; - this.activeConnections = this.activeConnections.filter(con => { + this.connections = this.connections.filter(con => { if (con.connectionId !== connectionId) { return true; } else { @@ -274,7 +276,7 @@ export class Session { // Remove every Publisher of the closed connection from every subscriber list of other connections if (!!connectionClosed) { connectionClosed.publishers.forEach(publisher => { - this.activeConnections.forEach(con => { + this.connections.forEach(con => { con.subscribers = con.subscribers.filter(subscriber => { // tslint:disable:no-string-literal if (!!subscriber['streamId']) { @@ -289,8 +291,9 @@ export class Session { }); }); } else { - console.warn("The closed connection wasn't fetched in OpenVidu Java Client. No changes in the collection of active connections of the Session"); + console.warn("The closed connection wasn't fetched in OpenVidu Node Client. No changes in the collection of active connections of the Session"); } + this.updateActiveConnectionsArray(); console.log("Connection '" + connectionId + "' closed"); resolve(); } else { @@ -309,10 +312,10 @@ export class Session { * OpenVidu Browser will trigger the proper events on the client-side (`streamDestroyed`) with reason set to `"forceUnpublishByServer"`. * * You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property). - * Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server + * Remember to call [[Session.fetch]] or [[OpenVidu.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not */ @@ -331,7 +334,7 @@ export class Session { .then(res => { if (res.status === 204) { // SUCCESS response from openvidu-server - this.activeConnections.forEach(connection => { + this.connections.forEach(connection => { // Try to remove the Publisher from the Connection publishers collection connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId); // Try to remove the Publisher from the Connection subscribers collection @@ -347,6 +350,7 @@ export class Session { } } }); + this.updateActiveConnectionsArray(); console.log("Stream '" + streamId + "' unpublished"); resolve(); } else { @@ -366,16 +370,10 @@ export class Session { * - [[ConnectionOptions.role]] * - [[ConnectionOptions.record]] * - * The `connectionId` parameter can be obtained from a Connection object with - * [[Connection.connectionId]], in which case the updated properties will - * modify an active Connection. But `connectionId` can also be obtained from a - * Token with [[Token.connectionId]], which allows modifying a still not used token. - * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * - * @param connectionId The [[Connection.connectionId]] property of the Connection object to modify, - * or the [[Token.connectionId]] property of a still not used token to modify + * @param connectionId The [[Connection.connectionId]] of the Connection object to modify * @param connectionOptions A new [[ConnectionOptions]] object with the updated values to apply * * @returns A Promise that is resolved to the updated [[Connection]] object if the operation was @@ -404,15 +402,17 @@ export class Session { return; } // Update the actual Connection object with the new options - const existingConnection: Connection = this.activeConnections.find(con => con.connectionId === connectionId); + const existingConnection: Connection = this.connections.find(con => con.connectionId === connectionId); if (!existingConnection) { // The updated Connection is not available in local map const newConnection: Connection = new Connection(res.data); - this.activeConnections.push(newConnection); + this.connections.push(newConnection); + this.updateActiveConnectionsArray(); resolve(newConnection); } else { // The updated Connection was available in local map existingConnection.overrideConnectionOptions(connectionOptions); + this.updateActiveConnectionsArray(); resolve(existingConnection); } }).catch(error => { @@ -513,11 +513,17 @@ export class Session { this.properties.defaultCustomLayout = defaultCustomLayout; } + this.connections = []; this.activeConnections = []; - json.connections.content.forEach(jsonConnection => this.activeConnections.push(new Connection(jsonConnection))); + json.connections.content.forEach(jsonConnection => { + const con = new Connection(jsonConnection); + this.connections.push(con); + }); // Order connections by time of creation - this.activeConnections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); + this.connections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); + // Populate activeConnections array + this.updateActiveConnectionsArray(); return this; } @@ -529,13 +535,13 @@ export class Session { this.sessionId === other.sessionId && this.createdAt === other.createdAt && this.recording === other.recording && - this.activeConnections.length === other.activeConnections.length && + this.connections.length === other.connections.length && JSON.stringify(this.properties) === JSON.stringify(other.properties) ); if (equals) { let i = 0; - while (equals && i < this.activeConnections.length) { - equals = this.activeConnections[i].equalTo(other.activeConnections[i]); + while (equals && i < this.connections.length) { + equals = this.connections[i].equalTo(other.connections[i]); i++; } return equals; @@ -555,6 +561,18 @@ export class Session { } } + /** + * @hidden + */ + private updateActiveConnectionsArray() { + this.activeConnections = []; + this.connections.forEach(con => { + if (con.status === 'active') { + this.activeConnections.push(con); + } + }); + } + /** * @hidden */ From f73bafdd7aefe2bef94bfa7b78a9e3056a51a5e9 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 15 Oct 2020 13:35:15 +0200 Subject: [PATCH 148/435] Safely remove certificates folder --- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- openvidu-server/docker/openvidu-proxy/entrypoint.sh | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 6ea8a6b5..4e1cbdae 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -74,7 +74,7 @@ services: - MAX_PORT=65535 nginx: - image: openvidu/openvidu-proxy:4.0.0-dev3 + image: openvidu/openvidu-proxy:4.0.0-dev4 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 85681102..8df13142 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -68,22 +68,23 @@ printf "\n =======================================" printf "\n" printf "\n Configure %s domain..." "${DOMAIN_OR_PUBLIC_IP}" -OLD_DOMAIN_OR_PUBLIC_IP=$(grep "${DOMAIN_OR_PUBLIC_IP}" "${CERTIFICATES_CONF}" | cut -f1 -d$'\t') -CERTIFICATED_OLD_CONFIG=$(grep "${DOMAIN_OR_PUBLIC_IP}" "${CERTIFICATES_CONF}" | cut -f2 -d$'\t') +OLD_DOMAIN_OR_PUBLIC_IP=$(head -n 1 "${CERTIFICATES_CONF}" | cut -f1 -d$'\t') +CERTIFICATED_OLD_CONFIG=$(head -n 1 "${CERTIFICATES_CONF}" | cut -f2 -d$'\t') -printf "\n - New configuration: %s" "${CERTIFICATE_TYPE}" +printf "\n - New configuration: %s %s" "${CERTIFICATE_TYPE}" "${DOMAIN_OR_PUBLIC_IP}" if [ -z "${CERTIFICATED_OLD_CONFIG}" ]; then printf "\n - Old configuration: none" else - printf "\n - Old configuration: %s" "${CERTIFICATED_OLD_CONFIG}" + printf "\n - Old configuration: %s %s" "${CERTIFICATED_OLD_CONFIG}" "${OLD_DOMAIN_OR_PUBLIC_IP}" if [ "${CERTIFICATED_OLD_CONFIG}" != "${CERTIFICATE_TYPE}" ] || \ [ "${OLD_DOMAIN_OR_PUBLIC_IP}" != "${DOMAIN_OR_PUBLIC_IP}" ]; then printf "\n - Restarting configuration... Removing old certificated..." + # Remove certificate folder safely + find "${CERTIFICATES_FOLDER:?}" -mindepth 1 -delete # Recreate certificates folder - rm -rf "${CERTIFICATES_FOLDER:?}" mkdir -p "${CERTIFICATES_LIVE_FOLDER}" touch "${CERTIFICATES_CONF}" fi From afc6f52f91e30453050ecd23c97779f672bbf441 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 15 Oct 2020 14:47:53 +0200 Subject: [PATCH 149/435] deployment-openvidu-ce-and-pro: Add TLSv1.3 and some ssl_chiphers recommended for browsers compatibility: https://ssl-config.mozilla.org/\#server\=nginx\&version\=1.17.7\&config\=intermediate\&openssl\=1.1.1d\&guideline\=5.6 --- .../default_nginx_conf/ce/default-app-without-demos.conf | 4 ++-- .../openvidu-proxy/default_nginx_conf/ce/default-app.conf | 6 +++--- .../support_deprecated_api/default-app-without-demos.conf | 4 ++-- .../ce/support_deprecated_api/default-app.conf | 4 ++-- .../default_nginx_conf/pro/default-app-without-demos.conf | 4 ++-- .../openvidu-proxy/default_nginx_conf/pro/default.conf | 4 ++-- .../support_deprecated_api/default-app-without-demos.conf | 4 ++-- .../pro/support_deprecated_api/default.conf | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf index c54706dd..eecf11c5 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf @@ -20,8 +20,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf index 185bd25c..9b1c21ab 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf @@ -20,9 +20,9 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers on; proxy_set_header Host $host; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf index b7fa2188..6cb723f0 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf @@ -20,8 +20,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf index 14a7d1e3..e4c1f8d7 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf @@ -20,8 +20,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf index c4731c16..9bae1de9 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf @@ -56,8 +56,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf index fbbc0018..4c6a4df8 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf @@ -56,8 +56,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf index 089de746..e74c8782 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf @@ -56,8 +56,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf index 7718016a..a84514c7 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf @@ -56,8 +56,8 @@ server { ssl_stapling on; ssl_stapling_verify on; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; From 4c93cb7a7f0337b11673db3a5d041e6137514fd5 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 15 Oct 2020 16:25:26 +0200 Subject: [PATCH 150/435] deployment-openvidu-pro: bump nginx 4.0.0-dev4 --- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 2fb2dddd..e8681b99 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -68,7 +68,7 @@ services: - TURN_PUBLIC_IP=auto nginx: - image: openvidu/openvidu-proxy:4.0.0-dev3 + image: openvidu/openvidu-proxy:4.0.0-dev4 restart: on-failure network_mode: host volumes: From e20db3f5031a48c63f0a55111376e27be7cc2753 Mon Sep 17 00:00:00 2001 From: csantosm <4a.santos@gmail.com> Date: Thu, 15 Oct 2020 16:46:53 +0200 Subject: [PATCH 151/435] openvidu-server: Added publishedAt property to participant --- .../main/java/io/openvidu/server/core/Participant.java | 9 +++++++++ .../server/kurento/core/KurentoSessionManager.java | 2 ++ 2 files changed, 11 insertions(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 55678da1..ddf1e76a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -63,6 +63,7 @@ public class Participant { protected Integer videoHeight = 0; protected Boolean videoActive = false; protected Boolean audioActive = false; + protected Long publishedAt = null; // Timestamp when this participant was published protected boolean streaming = false; protected volatile boolean closed = false; @@ -196,6 +197,14 @@ public class Participant { return audioActive; } + public void setPublishedAt(Long publishedAt) { + this.publishedAt = publishedAt; + } + + public Long getPublishedAt() { + return publishedAt; + } + public void setAudioActive(Boolean audioActive) { this.audioActive = audioActive; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 81032cfb..8823a2db 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; +import java.sql.Timestamp; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -467,6 +468,7 @@ public class KurentoSessionManager extends SessionManager { } + participant.setPublishedAt(new Timestamp(System.currentTimeMillis()).getTime()); kSession.newPublisher(participant); participants = kParticipant.getSession().getParticipants(); From 77a63a8e545913ac8c89649dab5cf3dc783e79a6 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 16 Oct 2020 13:41:19 +0200 Subject: [PATCH 152/435] openvidu-server: GET /connection --- .../io/openvidu/server/core/Participant.java | 4 + .../java/io/openvidu/server/core/Session.java | 43 +-- .../server/core/SessionInterface.java | 4 +- .../kurento/core/KurentoParticipant.java | 1 + .../io/openvidu/server/kurento/kms/Kms.java | 2 +- .../server/rest/SessionRestController.java | 75 ++++- ...essionGarbageCollectorIntegrationTest.java | 2 +- .../test/e2e/OpenViduProTestAppE2eTest.java | 18 ++ .../test/e2e/OpenViduTestAppE2eTest.java | 264 ++++++++++++++++-- 9 files changed, 364 insertions(+), 49 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index ddf1e76a..1c450ff4 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -316,4 +316,8 @@ public class Participant { return json; } + public JsonObject withStatsToJson() { + return null; + } + } 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 1b6e88b5..f40f027f 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 @@ -29,7 +29,7 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.function.Function; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +43,6 @@ import io.openvidu.client.internal.ProtocolElements; import io.openvidu.java.client.RecordingLayout; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.config.OpenviduConfig; -import io.openvidu.server.kurento.core.KurentoParticipant; import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.utils.RecordingUtils; @@ -183,10 +182,6 @@ public class Session implements SessionInterface { return deleted; } - public boolean isTokenValid(String token) { - return this.tokens.containsKey(token); - } - public Token consumeToken(String token) { Token tokenObj = this.tokens.remove(token); return tokenObj; @@ -214,15 +209,30 @@ public class Session implements SessionInterface { } } - public JsonObject toJson() { - return this.sharedJson(KurentoParticipant::toJson); + public JsonArray getSnapshotOfConnectionsAsJsonArray(boolean withPendingConnections, boolean withWebrtcStats) { + + Set snapshotOfActiveConnections = this.getParticipants().stream().collect(Collectors.toSet()); + JsonArray jsonArray = new JsonArray(); + snapshotOfActiveConnections.forEach(participant -> { + // Filter recorder participant + if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(participant.getParticipantPublicId())) { + jsonArray.add(withWebrtcStats ? participant.withStatsToJson() : participant.toJson()); + } + }); + + if (withPendingConnections) { + Set snapshotOfPendingConnections = this.tokens.values().stream().collect(Collectors.toSet()); + // Eliminate duplicates in case some concurrent situation took place + Set activeConnectionIds = snapshotOfActiveConnections.stream() + .map(participant -> participant.getParticipantPublicId()).collect(Collectors.toSet()); + snapshotOfPendingConnections.removeIf(token -> activeConnectionIds.contains(token.getConnectionId())); + snapshotOfPendingConnections.forEach(token -> jsonArray.add(token.toJsonAsParticipant())); + } + + return jsonArray; } - public JsonObject withStatsToJson() { - return this.sharedJson(KurentoParticipant::withStatsToJson); - } - - private JsonObject sharedJson(Function toJsonFunction) { + public JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats) { JsonObject json = new JsonObject(); json.addProperty("id", this.sessionId); json.addProperty("object", "session"); @@ -241,12 +251,7 @@ public class Session implements SessionInterface { json.addProperty("customSessionId", this.sessionProperties.customSessionId()); } JsonObject connections = new JsonObject(); - JsonArray participants = new JsonArray(); - this.participants.values().forEach(p -> { - if (!ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(p.getParticipantPublicId())) { - participants.add(toJsonFunction.apply((KurentoParticipant) p)); - } - }); + JsonArray participants = this.getSnapshotOfConnectionsAsJsonArray(withPendingConnections, withWebrtcStats); connections.addProperty("numberOfElements", participants.size()); connections.add("content", participants); json.add("connections", connections); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java index fa398f22..08d1d805 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionInterface.java @@ -47,9 +47,7 @@ public interface SessionInterface { String getMediaNodeId(); - JsonObject toJson(); - - JsonObject withStatsToJson(); + JsonObject toJson(boolean withPendingConnections, boolean withWebrtcStats); Long getStartTime(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 560d8808..68a7008b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -568,6 +568,7 @@ public class KurentoParticipant extends Participant { return this.sharedJson(MediaEndpoint::toJson); } + @Override public JsonObject withStatsToJson() { return this.sharedJson(MediaEndpoint::withStatsToJson); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java index 31d74da9..d63ec9d9 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/kms/Kms.java @@ -171,7 +171,7 @@ public class Kms { if (withSessions) { JsonArray sessions = new JsonArray(); for (KurentoSession session : this.kurentoSessions.values()) { - sessions.add(session.toJson()); + sessions.add(session.toJson(false, false)); } json.add("sessions", sessions); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 75539422..7992af8a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -20,7 +20,9 @@ package io.openvidu.server.rest; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -177,25 +179,25 @@ public class SessionRestController { log.info("New session {} initialized {}", sessionId, this.sessionManager.getSessionsWithNotActive().stream() .map(Session::getSessionId).collect(Collectors.toList()).toString()); - return new ResponseEntity<>(sessionNotActive.toJson().toString(), RestUtils.getResponseHeaders(), + return new ResponseEntity<>(sessionNotActive.toJson(false, false).toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } @RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET) public ResponseEntity getSession(@PathVariable("sessionId") String sessionId, + @RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { log.info("REST API: GET {}/sessions/{}", RequestMappings.API, sessionId); Session session = this.sessionManager.getSession(sessionId); if (session != null) { - JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson(); + JsonObject response = session.toJson(pendingConnections, webRtcStats); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } else { Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId); if (sessionNotActive != null) { - JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson() - : sessionNotActive.toJson(); + JsonObject response = sessionNotActive.toJson(pendingConnections, webRtcStats); return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -205,15 +207,16 @@ public class SessionRestController { @RequestMapping(value = "/sessions", method = RequestMethod.GET) public ResponseEntity listSessions( + @RequestParam(value = "pendingConnections", defaultValue = "false", required = false) boolean pendingConnections, @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { - log.info("REST API: GET {}/sessions?webRtcStats={}", RequestMappings.API, webRtcStats); + log.info("REST API: GET {}/sessions", RequestMappings.API); Collection sessions = this.sessionManager.getSessionsWithNotActive(); JsonObject json = new JsonObject(); JsonArray jsonArray = new JsonArray(); - sessions.forEach(s -> { - JsonObject sessionJson = (webRtcStats == true) ? s.withStatsToJson() : s.toJson(); + sessions.forEach(session -> { + JsonObject sessionJson = session.toJson(pendingConnections, webRtcStats); jsonArray.add(sessionJson); }); json.addProperty("numberOfElements", sessions.size()); @@ -735,6 +738,51 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.OK); } + @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.GET) + public ResponseEntity getConnection(@PathVariable("sessionId") String sessionId, + @PathVariable("connectionId") String connectionId) { + + log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session != null) { + Participant p = session.getParticipantByPublicId(connectionId); + if (p != null) { + return new ResponseEntity<>(p.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + Token t = getTokenFromConnectionId(connectionId, session.getTokenIterator()); + if (t != null) { + return new ResponseEntity<>(t.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), + HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.GET) + public ResponseEntity listConnections(@PathVariable("sessionId") String sessionId, + @RequestParam(value = "pendingConnections", defaultValue = "true", required = false) boolean pendingConnections, + @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { + + log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + + if (session != null) { + JsonObject json = new JsonObject(); + JsonArray jsonArray = session.getSnapshotOfConnectionsAsJsonArray(pendingConnections, webRtcStats); + json.addProperty("numberOfElements", jsonArray.size()); + json.add("content", jsonArray); + return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST) public ResponseEntity publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map params) { @@ -812,6 +860,19 @@ public class SessionRestController { } } + protected Token getTokenFromConnectionId(String connectionId, Iterator> iterator) { + boolean found = false; + Token token = null; + while (iterator.hasNext() && !found) { + Token tAux = iterator.next().getValue(); + found = tAux.getConnectionId().equals(connectionId); + if (found) { + token = tAux; + } + } + return token; + } + protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { JsonObject responseJson = new JsonObject(); responseJson.addProperty("timestamp", System.currentTimeMillis()); diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 7e267ee6..e4abf225 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -110,7 +110,7 @@ public class SessionGarbageCollectorIntegrationTest { } private JsonObject listSessions() { - String stringResponse = (String) sessionRestController.listSessions(false).getBody(); + String stringResponse = (String) sessionRestController.listSessions(false, false).getBody(); return new Gson().fromJson(stringResponse, JsonObject.class); } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index cc253613..bd14255e 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -31,6 +31,7 @@ import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.Session; +import io.openvidu.java.client.Token; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; @@ -382,4 +383,21 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { "{'status':'UP'}"); } + @Test + @DisplayName("openvidu-java-client PRO test") + void openViduJavaClientProTest() throws Exception { + Session session = OV.createSession(); + Assert.assertFalse(session.fetch()); + Token token = session.createToken(); + Assert.assertTrue(session.fetch()); + Connection connection = session.getConnection(token.getConnectionId()); + Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole()); + Assert.assertTrue("Wrong record property", connection.record()); + session.updateConnection(connection.getConnectionId(), + new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); + Assert.assertEquals("Wrong role property", OpenViduRole.SUBSCRIBER, connection.getRole()); + Assert.assertFalse("Wrong record property", connection.record()); + Assert.assertFalse(session.fetch()); + } + } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index be488351..1ea36adf 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -42,7 +42,9 @@ import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Dimension; import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -64,6 +66,7 @@ import io.openvidu.java.client.RecordingMode; import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.Session; import io.openvidu.java.client.SessionProperties; +import io.openvidu.java.client.Token; import io.openvidu.java.client.TokenOptions; import io.openvidu.test.browsers.FirefoxUser; import io.openvidu.test.browsers.utils.CustomHttpClient; @@ -2114,8 +2117,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { log.info("openvidu-java-client test"); - System.out.println(getBase64Screenshot(user)); - user.getDriver().findElement(By.id("one2one-btn")).click(); final String customSessionId = "openviduJavaClientSession"; @@ -2142,13 +2143,34 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { .allowedFilters(new String[] { "GStreamerFilter" }).build(); TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - String tokenModerator = session.generateToken(tokenOptionsModerator); + Token tokenModerator = session.createToken(tokenOptionsModerator); + String tokenModeratorString = tokenModerator.getToken(); + String connectionIdModerator = tokenModerator.getConnectionId(); TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) .data(serverDataSubscriber).build(); - String tokenSubscriber = session.generateToken(tokenOptionsSubscriber); + Token tokenSubscriber = session.createToken(tokenOptionsSubscriber); + String tokenSubscriberString = tokenSubscriber.getToken(); + String connectionIdSubscriber = tokenSubscriber.getConnectionId(); - Assert.assertFalse("Session.fetch() should return false until a user has connected", session.fetch()); + Assert.assertTrue("Session.fetch() should return true if new pending connections", session.fetch()); + Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch()); + + Assert.assertEquals("Wrong number of active connections", 0, session.getActiveConnections().size()); + Assert.assertEquals("Wrong number of connections", 2, session.getConnections().size()); + Connection connectionModerator = session.getConnection(connectionIdModerator); + Connection connectionSubscriber = session.getConnection(connectionIdSubscriber); + Assert.assertEquals("Wrong connectionId property", connectionIdModerator, + connectionModerator.getConnectionId()); + Assert.assertEquals("Wrong status property", "pending", connectionModerator.getStatus()); + Assert.assertEquals("Wrong role property", OpenViduRole.MODERATOR, connectionModerator.getRole()); + Assert.assertTrue("Wrong record property", connectionModerator.record()); + Assert.assertNull("Wrong location property", connectionModerator.getLocation()); + Assert.assertNull("Wrong platform property", connectionModerator.getPlatform()); + Assert.assertEquals("Wrong createdAt property", 0, connectionModerator.createdAt()); + Assert.assertNull("Wrong clientData property", connectionModerator.getClientData()); + Assert.assertEquals("Wrong publishers property", 0, connectionModerator.getPublishers().size()); + Assert.assertEquals("Wrong subscribers property", 0, connectionModerator.getSubscribers().size()); // Set client data 1 WebElement clientDataInput = user.getDriver().findElement(By.cssSelector("#client-data-input-0")); @@ -2160,7 +2182,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenModerator); + tokeInput.sendKeys(tokenModeratorString); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2175,7 +2197,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenSubscriber); + tokeInput.sendKeys(tokenSubscriberString); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2215,17 +2237,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Expected 2 active connections but found " + session.getActiveConnections().size(), 2, session.getActiveConnections().size()); - Connection connectionModerator; - Connection connectionSubscriber; - if (OpenViduRole.MODERATOR.equals(session.getActiveConnections().get(0).getRole())) { - connectionModerator = session.getActiveConnections().get(0); - connectionSubscriber = session.getActiveConnections().get(1); - } else { - connectionModerator = session.getActiveConnections().get(1); - connectionSubscriber = session.getActiveConnections().get(0); - } - - Assert.assertEquals(OpenViduRole.SUBSCRIBER, connectionSubscriber.getRole()); + // Verify status + Assert.assertEquals("Wrong status for moderator connection", "active", connectionModerator.getStatus()); + Assert.assertEquals("Wrong status for subscriber connection", "active", connectionSubscriber.getStatus()); // Verify platform Assert.assertTrue("Wrong platform for moderator connection", @@ -2579,6 +2593,15 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.GET, "/openvidu/api/sessions", null, HttpStatus.SC_OK, true, true, false, "{'numberOfElements': 1, 'content': []}"); + /** GET /openvidu/api/sessions/ID/connection (with no connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection", HttpStatus.SC_NOT_FOUND); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, true, "{'numberOfElements':0,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/NOT_EXISTS/connection/NOT_EXISTS", + HttpStatus.SC_BAD_REQUEST); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/NOT_EXISTS", + HttpStatus.SC_NOT_FOUND); + /** POST /openvidu/api/tokens **/ // 400 body = "{}"; @@ -2599,6 +2622,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); + final String connectionId1 = res.get("connectionId").getAsString(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); @@ -2608,6 +2632,17 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_TOKEN); final String token2 = res.get("id").getAsString(); + final String connectionId2 = res.get("connectionId").getAsString(); + + /** GET /openvidu/api/sessions/ID/connection (with pending connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, false, "{'numberOfElements':2,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, + HttpStatus.SC_OK, true, true, true, + "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + + "','object':'connection','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" + + token1 + + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ body = "{}"; @@ -2695,6 +2730,20 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + /** GET /openvidu/api/sessions/ID/connection (with active connections) **/ + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, + true, true, false, "{'numberOfElements':2,'content':[]}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, + HttpStatus.SC_OK, false, true, false, + "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token1 + + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true}"); + restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId2, null, + HttpStatus.SC_OK, false, true, false, + "{'id':'" + connectionId2 + "','connectionId':'" + connectionId2 + + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token2 + + "','role':'PUBLISHER','serverData':'','record':true}"); + /** GET /openvidu/api/recordings (before recording started) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); restClient.rest(HttpMethod.GET, "/openvidu/api/recordings", null, HttpStatus.SC_OK, true, true, true, @@ -3434,4 +3483,183 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } } + @Test + @DisplayName("OpenVidu SDK fetch test") + void openviduSdkFetchTest() throws Exception { + isRecordingTest = true; + + setupBrowser("chrome"); + + log.info("OpenVidu SDK fetch test"); + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + Session session = OV.createSession(); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", "{'customSessionId':'REST_SESSION'}", + HttpStatus.SC_OK); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + Token token = session.createToken(); + // TODO: when using createConnection this below should be false! + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", "{'session':'REST_SESSION'}", HttpStatus.SC_OK); + Assert.assertFalse("Fetch should be true", session.fetch()); + Assert.assertTrue("Fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/REST_SESSION", HttpStatus.SC_NO_CONTENT); + Assert.assertFalse("Java fetch should be true", session.fetch()); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + + // Set token and join session + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("session-settings-btn-0")).click(); + Thread.sleep(1000); + WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); + tokeInput.clear(); + tokeInput.sendKeys(token.getToken()); + user.getDriver().findElement(By.id("save-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.className("join-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("accessAllowed", 1); + user.getEventManager().waitUntilEventReaches("streamCreated", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(true, false); + + // RECORD + user.getDriver().findElement(By.id("rec-properties-btn")).click(); + user.getDriver().findElement(By.id("rec-hasvideo-checkbox")).click(); + user.getDriver().findElement(By.id("rec-outputmode-select")).click(); + Thread.sleep(500); + user.getDriver().findElement(By.id("option-INDIVIDUAL")).click(); + Thread.sleep(500); + + user.getDriver().findElement(By.id("start-recording-btn")).click(); + user.getEventManager().waitUntilEventReaches("recordingStarted", 1); + + // Node SDK should return false as the recording has been started with it + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(true, false); + // Java SDK should return true as it doesn't know about the recording yet + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + + OV.stopRecording(session.getSessionId()); + user.getEventManager().waitUntilEventReaches("recordingStopped", 1); + // Java SDK should return false as the recording has been stopped with it + Assert.assertFalse("Java fetch should be false", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + // Node SDK should return true as it doesn't know about the recording stooped + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + + // NEW SUBSCRIBER + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.id("session-name-input-1")).clear(); + user.getDriver().findElement(By.id("session-name-input-1")).sendKeys(session.getSessionId()); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click(); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // MODIFY STREAM + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-0 .pub-video-btn")).click(); + user.getEventManager().waitUntilEventReaches("streamPropertyChanged", 2); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // REMOVE STREAM + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .sub-btn")).click(); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(true, true); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + + // REMOVE USER + user.getDriver().findElement(By.id("close-dialog-btn")).click(); + Thread.sleep(1000); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .leave-btn")).click(); + user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); + Thread.sleep(1000); + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(false, true); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + } + + private void checkNodeFetchChanged(boolean global, boolean hasChanged) { + user.getDriver().findElement(By.id(global ? "list-sessions-btn" : "get-session-btn")).click(); + user.getWaiter().until(new NodeFetchHasChanged(hasChanged)); + } + + private class NodeFetchHasChanged implements ExpectedCondition { + + private boolean hasChanged; + + public NodeFetchHasChanged(boolean hasChanged) { + this.hasChanged = hasChanged; + } + + @Override + public Boolean apply(WebDriver driver) { + return driver.findElement(By.id("api-response-text-area")).getAttribute("value") + .endsWith("Changes: " + hasChanged); + } + } + } From b4c1df18785e83b5670de84ee2e830f836d070b2 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 16 Oct 2020 13:45:15 +0200 Subject: [PATCH 153/435] OpenVidu SDKs: update with improved reset process --- .../io/openvidu/java/client/Connection.java | 124 +++++++++----- .../io/openvidu/java/client/OpenVidu.java | 44 +++-- .../io/openvidu/java/client/Publisher.java | 113 ++++++++----- .../java/io/openvidu/java/client/Session.java | 39 ++++- openvidu-node-client/src/Connection.ts | 78 +++++++-- openvidu-node-client/src/OpenVidu.ts | 154 ++++++++---------- openvidu-node-client/src/Publisher.ts | 8 + openvidu-node-client/src/Session.ts | 55 ++++--- 8 files changed, 375 insertions(+), 240 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index 27a8879d..aa5e9565 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -18,8 +18,10 @@ package io.openvidu.java.client; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import com.google.gson.JsonArray; @@ -42,50 +44,7 @@ public class Connection { protected List subscribers = new ArrayList<>(); protected Connection(JsonObject json) { - // These properties may be null - if (!json.get("publishers").isJsonNull()) { - JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); - jsonArrayPublishers.forEach(publisher -> { - JsonObject pubJson = publisher.getAsJsonObject(); - JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject(); - Publisher pub = new Publisher(pubJson.get("streamId").getAsString(), - pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(), - mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"), - mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"), - mediaOptions.get("videoDimensions")); - this.publishers.put(pub.getStreamId(), pub); - }); - } - - if (!json.get("subscribers").isJsonNull()) { - JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray(); - jsonArraySubscribers.forEach(subscriber -> { - this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString()); - }); - } - if (!json.get("createdAt").isJsonNull()) { - this.createdAt = json.get("createdAt").getAsLong(); - } - if (!json.get("location").isJsonNull()) { - this.location = json.get("location").getAsString(); - } - if (!json.get("platform").isJsonNull()) { - this.platform = json.get("platform").getAsString(); - } - if (!json.get("clientData").isJsonNull()) { - this.clientData = json.get("clientData").getAsString(); - } - - // These properties won't ever be null - this.connectionId = json.get("connectionId").getAsString(); - this.status = json.get("status").getAsString(); - String token = json.has("token") ? json.get("token").getAsString() : null; - OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); - String data = json.get("serverData").getAsString(); - Boolean record = json.get("record").getAsBoolean(); - - TokenOptions tokenOptions = new TokenOptions(role, data, record, null); - this.token = new Token(token, this.connectionId, tokenOptions); + this.resetWithJson(json); } /** @@ -248,4 +207,81 @@ public class Connection { this.subscribers = subscribers; } + protected Connection resetWithJson(JsonObject json) { + + if (!json.get("publishers").isJsonNull()) { + JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); + + // 1. Set to store fetched publishers and later remove closed ones + Set fetchedPublisherIds = new HashSet<>(); + jsonArrayPublishers.forEach(publisherJsonElement -> { + + JsonObject publisherJson = publisherJsonElement.getAsJsonObject(); + Publisher publisherObj = new Publisher(publisherJson); + String id = publisherObj.getStreamId(); + fetchedPublisherIds.add(id); + + // 2. Update existing Publisher + this.publishers.computeIfPresent(id, (pId, p) -> { + p = p.resetWithJson(publisherJson); + return p; + }); + + // 3. Add new Publisher + this.publishers.computeIfAbsent(id, pId -> { + return publisherObj; + }); + }); + + // 4. Remove closed connections from local collection + this.publishers.entrySet().removeIf(entry -> !fetchedPublisherIds.contains(entry.getValue().getStreamId())); + } + + if (!json.get("subscribers").isJsonNull()) { + JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray(); + + // 1. Array to store fetched Subscribers and later remove closed ones + Set fetchedSubscriberIds = new HashSet<>(); + jsonArraySubscribers.forEach(subscriber -> { + + String sub = subscriber.getAsJsonObject().get("streamId").getAsString(); + fetchedSubscriberIds.add(sub); + + if (!this.subscribers.contains(sub)) { + // 2. Add new Subscriber + this.subscribers.add(sub); + } + }); + + // 3. Remove closed Subscribers from local collection + this.subscribers.removeIf(subId -> !fetchedSubscriberIds.contains(subId)); + } + + if (!json.get("createdAt").isJsonNull()) { + this.createdAt = json.get("createdAt").getAsLong(); + } + if (!json.get("location").isJsonNull()) { + this.location = json.get("location").getAsString(); + } + if (!json.get("platform").isJsonNull()) { + this.platform = json.get("platform").getAsString(); + } + if (!json.get("clientData").isJsonNull()) { + this.clientData = json.get("clientData").getAsString(); + } + + // These properties won't ever be null + this.connectionId = json.get("connectionId").getAsString(); + this.status = json.get("status").getAsString(); + String token = json.has("token") ? json.get("token").getAsString() : null; + OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); + String data = json.get("serverData").getAsString(); + Boolean record = json.get("record").getAsBoolean(); + + TokenOptions tokenOptions = new TokenOptions(role, data, record, null); + this.token = new Token(token, this.connectionId, tokenOptions); + + return this; + } + } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 005c6430..0e1a660f 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -31,7 +31,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import javax.net.ssl.SSLContext; @@ -549,44 +548,55 @@ public class OpenVidu { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + JsonObject jsonSessions = httpResponseToJson(response); JsonArray jsonArraySessions = jsonSessions.get("content").getAsJsonArray(); - // Set to store fetched sessionIds and later remove closed sessions - Set fetchedSessionIds = new HashSet<>(); // Boolean to store if any Session has changed final boolean[] hasChanged = { false }; - jsonArraySessions.forEach(session -> { - String sessionId = (session.getAsJsonObject()).get("sessionId").getAsString(); - fetchedSessionIds.add(sessionId); - this.activeSessions.computeIfPresent(sessionId, (sId, s) -> { + + // 1. Set to store fetched sessionIds and later remove closed ones + Set fetchedSessionIds = new HashSet<>(); + jsonArraySessions.forEach(sessionJsonElement -> { + + JsonObject sessionJson = sessionJsonElement.getAsJsonObject(); + final Session sessionObj = new Session(this, sessionJson); + String id = sessionObj.getSessionId(); + fetchedSessionIds.add(id); + + // 2. Update existing Session + this.activeSessions.computeIfPresent(id, (sId, s) -> { String beforeJSON = s.toJson(); - s = s.resetSessionWithJson(session.getAsJsonObject()); + s = s.resetWithJson(sessionJson); String afterJSON = s.toJson(); boolean changed = !beforeJSON.equals(afterJSON); hasChanged[0] = hasChanged[0] || changed; - log.info("Available session '{}' info fetched. Any change: {}", sessionId, changed); + log.info("Available session '{}' info fetched. Any change: {}", id, changed); return s; }); - this.activeSessions.computeIfAbsent(sessionId, sId -> { - log.info("New session '{}' fetched", sessionId); + + // 3. Add new Session + this.activeSessions.computeIfAbsent(id, sId -> { + log.info("New session '{}' fetched", id); hasChanged[0] = true; - return new Session(this, session.getAsJsonObject()); + return sessionObj; }); }); - // Remove closed sessions from activeSessions map - this.activeSessions = this.activeSessions.entrySet().stream().filter(entry -> { + // 4. Remove closed sessions from local collection + this.activeSessions.entrySet().removeIf(entry -> { if (fetchedSessionIds.contains(entry.getKey())) { - return true; + return false; } else { log.info("Removing closed session {}", entry.getKey()); hasChanged[0] = true; - return false; + return true; } - }).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())); + }); + log.info("Active sessions info fetched: {}", this.activeSessions.keySet()); return hasChanged[0]; + } else { throw new OpenViduHttpException(statusCode); } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Publisher.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Publisher.java index 89030b51..7eeefe0e 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Publisher.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Publisher.java @@ -17,16 +17,15 @@ package io.openvidu.java.client; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; /** * See {@link io.openvidu.java.client.Connection#getPublishers()}. * *
- * This is a backend representation of a published media stream (see - * OpenVidu - * Browser Stream class). + * This is a backend representation of a published media stream (see OpenVidu Browser Stream class). */ public class Publisher { @@ -40,36 +39,18 @@ public class Publisher { private String typeOfVideo; private String videoDimensions; - protected Publisher(String streamId, long createdAt, boolean hasAudio, boolean hasVideo, JsonElement audioActive, - JsonElement videoActive, JsonElement frameRate, JsonElement typeOfVideo, JsonElement videoDimensions) { - this.streamId = streamId; - this.createdAt = createdAt; - this.hasAudio = hasAudio; - this.hasVideo = hasVideo; - if (audioActive != null && !audioActive.isJsonNull()) { - this.audioActive = audioActive.getAsBoolean(); - } - if (videoActive != null && !videoActive.isJsonNull()) { - this.videoActive = videoActive.getAsBoolean(); - } - if (frameRate != null && !frameRate.isJsonNull()) { - this.frameRate = frameRate.getAsInt(); - } - if (typeOfVideo != null && !typeOfVideo.isJsonNull()) { - this.typeOfVideo = typeOfVideo.getAsString(); - } - if (videoDimensions != null && !videoDimensions.isJsonNull()) { - this.videoDimensions = videoDimensions.getAsString(); - } + protected Publisher(JsonObject json) { + this.resetWithJson(json); } /** - * Returns the unique identifier of the - * Stream associated to this Publisher. Each Publisher is paired - * with only one Stream, so you can identify each Publisher by its - * Stream.streamId + * Returns the unique identifier of the Stream associated to this Publisher. Each Publisher is + * paired with only one Stream, so you can identify each Publisher by its + * Stream.streamId */ public String getStreamId() { return streamId; @@ -84,56 +65,70 @@ public class Publisher { } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public boolean hasVideo() { return this.hasVideo; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public boolean hasAudio() { return this.hasAudio; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public Boolean isAudioActive() { return this.audioActive; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public Boolean isVideoActive() { return this.videoActive; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public Integer getFrameRate() { return this.frameRate; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public String getTypeOfVideo() { return this.typeOfVideo; } /** - * See properties of Stream object in OpenVidu Browser library to find out more + * See properties of Stream object in OpenVidu Browser library to find out + * more */ public String getVideoDimensions() { return this.videoDimensions; @@ -152,4 +147,32 @@ public class Publisher { return json; } + protected Publisher resetWithJson(JsonObject json) { + this.streamId = json.get("streamId").getAsString(); + this.createdAt = json.get("createdAt").getAsLong(); + + if (json.has("mediaOptions") && !json.get("mediaOptions").isJsonNull()) { + JsonObject mediaOptions = json.get("mediaOptions").getAsJsonObject(); + this.hasAudio = mediaOptions.get("hasAudio").getAsBoolean(); + this.hasVideo = mediaOptions.get("hasVideo").getAsBoolean(); + if (mediaOptions.has("audioActive") && !mediaOptions.get("audioActive").isJsonNull()) { + this.audioActive = mediaOptions.get("audioActive").getAsBoolean(); + } + if (mediaOptions.has("videoActive") && !mediaOptions.get("videoActive").isJsonNull()) { + this.videoActive = mediaOptions.get("videoActive").getAsBoolean(); + } + if (mediaOptions.has("frameRate") && !mediaOptions.get("frameRate").isJsonNull()) { + this.frameRate = mediaOptions.get("frameRate").getAsInt(); + } + if (mediaOptions.has("typeOfVideo") && !mediaOptions.get("typeOfVideo").isJsonNull()) { + this.typeOfVideo = mediaOptions.get("typeOfVideo").getAsString(); + } + if (mediaOptions.has("videoDimensions") && !mediaOptions.get("videoDimensions").isJsonNull()) { + this.videoDimensions = mediaOptions.get("videoDimensions").getAsString(); + } + } + + return this; + } + } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index 75eef6da..e1ef12b4 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -19,8 +19,10 @@ package io.openvidu.java.client; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -66,7 +68,7 @@ public class Session { protected Session(OpenVidu openVidu, JsonObject json) { this.openVidu = openVidu; - this.resetSessionWithJson(json); + this.resetWithJson(json); } /** @@ -282,7 +284,7 @@ public class Session { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { - this.resetSessionWithJson(httpResponseToJson(response)); + this.resetWithJson(httpResponseToJson(response)); final String afterJSON = this.toJson(); boolean hasChanged = !beforeJSON.equals(afterJSON); log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged); @@ -694,7 +696,7 @@ public class Session { this.recording = recording; } - protected Session resetSessionWithJson(JsonObject json) { + protected Session resetWithJson(JsonObject json) { this.sessionId = json.get("sessionId").getAsString(); this.createdAt = json.get("createdAt").getAsLong(); this.recording = json.get("recording").getAsBoolean(); @@ -708,18 +710,37 @@ public class Session { if (json.has("defaultCustomLayout")) { builder.defaultCustomLayout(json.get("defaultCustomLayout").getAsString()); } - if (this.properties != null && this.properties.customSessionId() != null) { - builder.customSessionId(this.properties.customSessionId()); - } else if (json.has("customSessionId")) { + if (json.has("customSessionId")) { builder.customSessionId(json.get("customSessionId").getAsString()); } + this.properties = builder.build(); JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray(); - this.connections.clear(); + + // 1. Set to store fetched connections and later remove closed ones + Set fetchedConnectionIds = new HashSet<>(); jsonArrayConnections.forEach(connectionJsonElement -> { - Connection connectionObj = new Connection(connectionJsonElement.getAsJsonObject()); - this.connections.put(connectionObj.getConnectionId(), connectionObj); + + JsonObject connectionJson = connectionJsonElement.getAsJsonObject(); + Connection connectionObj = new Connection(connectionJson); + String id = connectionObj.getConnectionId(); + fetchedConnectionIds.add(id); + + // 2. Update existing Connection + this.connections.computeIfPresent(id, (cId, c) -> { + c = c.resetWithJson(connectionJson); + return c; + }); + + // 3. Add new Connection + this.connections.computeIfAbsent(id, cId -> { + return connectionObj; + }); }); + + // 4. Remove closed connections from local collection + this.connections.entrySet() + .removeIf(entry -> !fetchedConnectionIds.contains(entry.getValue().getConnectionId())); return this; } diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 928f2665..5bd0df9b 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -100,21 +100,13 @@ export class Connection { * @hidden */ constructor(json) { - // These properties may be null - if (json.publishers != null) { - json.publishers.forEach(publisher => { - this.publishers.push(new Publisher(publisher)); - }); - } - if (json.subscribers != null) { - json.subscribers.forEach(subscriber => { - this.subscribers.push(subscriber.streamId); - }); - } - this.createdAt = json.createdAt; - this.location = json.location; - this.platform = json.platform; - this.clientData = json.clientData; + this.resetWithJson(json); + } + + /** + * @hidden + */ + resetWithJson(json): Connection { // These properties won't ever be null this.connectionId = json.connectionId; @@ -123,6 +115,62 @@ export class Connection { this.role = json.role; this.serverData = json.serverData; this.record = json.record; + + // These properties may be null + if (json.publishers != null) { + + // 1. Array to store fetched Publishers and later remove closed ones + const fetchedPublisherIds: string[] = []; + json.publishers.forEach(jsonPublisher => { + + const publisherObj: Publisher = new Publisher(jsonPublisher); + fetchedPublisherIds.push(publisherObj.streamId); + let storedPublisher = this.publishers.find(c => c.streamId === publisherObj.streamId); + + if (!!storedPublisher) { + // 2. Update existing Publisher + storedPublisher.resetWithJson(jsonPublisher); + } else { + // 3. Add new Publisher + this.publishers.push(publisherObj); + } + }); + + // 4. Remove closed Publishers from local collection + for (var i = this.publishers.length - 1; i >= 0; --i) { + if (!fetchedPublisherIds.includes(this.publishers[i].streamId)) { + this.publishers.splice(i, 1); + } + } + + } + + if (json.subscribers != null) { + + // 1. Array to store fetched Subscribers and later remove closed ones + const fetchedSubscriberIds: string[] = []; + json.subscribers.forEach(jsonSubscriber => { + fetchedSubscriberIds.push(jsonSubscriber.streamId) + if (this.subscribers.indexOf(jsonSubscriber.streamId) === -1) { + // 2. Add new Subscriber + this.subscribers.push(jsonSubscriber.streamId); + } + }); + + // 3. Remove closed Subscribers from local collection + for (var i = this.subscribers.length - 1; i >= 0; --i) { + if (!fetchedSubscriberIds.includes(this.subscribers[i])) { + this.subscribers.splice(i, 1); + } + } + } + + this.createdAt = json.createdAt; + this.location = json.location; + this.platform = json.platform; + this.clientData = json.clientData; + + return this; } /** diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index 5e21a6c1..6979352b 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -429,47 +429,44 @@ export class OpenVidu { .then(res => { if (res.status === 200) { - // Array to store fetched sessionIds and later remove closed sessions - const fetchedSessionIds: string[] = []; // Boolean to store if any Session has changed let hasChanged = false; - res.data.content.forEach(session => { - fetchedSessionIds.push(session.sessionId); - let sessionIndex = -1; - let storedSession = this.activeSessions.find((s, index) => { - if (s.sessionId === session.sessionId) { - sessionIndex = index; - return true; - } else { - return false; - } - }); + // 1. Array to store fetched sessionIds and later remove closed ones + const fetchedSessionIds: string[] = []; + res.data.content.forEach(jsonSession => { + + const fetchedSession: Session = new Session(this, jsonSession); + fetchedSessionIds.push(fetchedSession.sessionId); + let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId); + if (!!storedSession) { - const fetchedSession: Session = new Session(this).resetSessionWithJson(session); + + // 2. Update existing Session const changed: boolean = !storedSession.equalTo(fetchedSession); - if (changed) { - storedSession = fetchedSession; - this.activeSessions[sessionIndex] = storedSession; - } + storedSession.resetWithJson(jsonSession); console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed); hasChanged = hasChanged || changed; + } else { - this.activeSessions.push(new Session(this, session)); - console.log("New session '" + session.sessionId + "' info fetched"); + + // 3. Add new Session + this.activeSessions.push(fetchedSession); + console.log("New session '" + fetchedSession.sessionId + "' info fetched"); hasChanged = true; } }); - // Remove closed sessions from activeSessions array - this.activeSessions = this.activeSessions.filter(session => { - if (fetchedSessionIds.includes(session.sessionId)) { - return true; - } else { - console.log("Removing closed session '" + session.sessionId + "'"); + + // 4. Remove closed sessions from local collection + for (var i = this.activeSessions.length - 1; i >= 0; --i) { + let sessionId = this.activeSessions[i].sessionId; + if (!fetchedSessionIds.includes(sessionId)) { + console.log("Removing closed session '" + sessionId + "'"); hasChanged = true; - return false; + this.activeSessions.splice(i, 1); } - }); + } + console.log('Active sessions info fetched: ', fetchedSessionIds); resolve(hasChanged); } else { @@ -505,26 +502,9 @@ export class OpenVidu { const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => { const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId); if (!!connectionExtended) { - const publisherArray = []; connection.publishers.forEach(pub => { const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId); - const pubAux = {}; - // Standard properties - pubAux['streamId'] = pub.streamId; - pubAux['createdAt'] = pub.createdAt; - const mediaOptions = { - audioActive: pub.audioActive, - videoActive: pub.videoActive, - hasAudio: pub.hasAudio, - hasVideo: pub.hasVideo, - typeOfVideo: pub.typeOfVideo, - frameRate: pub.frameRate, - videoDimensions: pub.videoDimensions - }; - pubAux['mediaOptions'] = mediaOptions; - const newPublisher = new Publisher(pubAux); - // WebRtc properties - newPublisher['webRtc'] = { + pub['webRtc'] = { kms: { events: publisherExtended.events, localCandidate: publisherExtended.localCandidate, @@ -536,11 +516,10 @@ export class OpenVidu { remoteSdp: publisherExtended.remoteSdp } }; - newPublisher['localCandidatePair'] = parseRemoteCandidatePair(newPublisher['webRtc'].kms.remoteCandidate); + pub['localCandidatePair'] = parseRemoteCandidatePair(pub['webRtc'].kms.remoteCandidate); if (!!publisherExtended.serverStats) { - newPublisher['webRtc'].kms.serverStats = publisherExtended.serverStats; + pub['webRtc'].kms.serverStats = publisherExtended.serverStats; } - publisherArray.push(newPublisher); }); const subscriberArray = []; connection.subscribers.forEach(sub => { @@ -569,7 +548,6 @@ export class OpenVidu { } subscriberArray.push(subAux); }); - connection.publishers = publisherArray; connection.subscribers = subscriberArray; } }; @@ -601,68 +579,64 @@ export class OpenVidu { .then(res => { if (res.status === 200) { - // Array to store fetched sessionIds and later remove closed sessions - const fetchedSessionIds: string[] = []; // Global changes let globalChanges = false; // Collection of sessionIds telling whether each one of them has changed or not const sessionChanges: ObjMap = {}; - res.data.content.forEach(session => { - fetchedSessionIds.push(session.sessionId); - let sessionIndex = -1; - let storedSession = this.activeSessions.find((s, index) => { - if (s.sessionId === session.sessionId) { - sessionIndex = index; - return true; - } else { - return false; - } - }); - if (!!storedSession) { - const fetchedSession: Session = new Session(this).resetSessionWithJson(session); - fetchedSession.activeConnections.forEach(connection => { - addWebRtcStatsToConnections(connection, session.connections.content); - }); + // 1. Array to store fetched sessionIds and later remove closed ones + const fetchedSessionIds: string[] = []; + res.data.content.forEach(jsonSession => { + const fetchedSession: Session = new Session(this, jsonSession); + fetchedSession.connections.forEach(connection => { + addWebRtcStatsToConnections(connection, jsonSession.connections.content); + }); + fetchedSessionIds.push(fetchedSession.sessionId); + let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId); + + if (!!storedSession) { + + // 2. Update existing Session let changed = !storedSession.equalTo(fetchedSession); if (!changed) { // Check if server webrtc information has changed in any Publisher object (Session.equalTo does not check Publisher.webRtc auxiliary object) - fetchedSession.activeConnections.forEach((connection, index1) => { + fetchedSession.connections.forEach((connection, index1) => { for (let index2 = 0; (index2 < connection['publishers'].length && !changed); index2++) { - changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishers'][index2]['webRtc']); + changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.connections[index1]['publishers'][index2]['webRtc']); } }); } - if (changed) { - storedSession = fetchedSession; - this.activeSessions[sessionIndex] = storedSession; - } + storedSession.resetWithJson(jsonSession); + storedSession.connections.forEach(connection => { + addWebRtcStatsToConnections(connection, jsonSession.connections.content); + }); console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed); sessionChanges[storedSession.sessionId] = changed; globalChanges = globalChanges || changed; + } else { - const newSession = new Session(this, session); - newSession.activeConnections.forEach(connection => { - addWebRtcStatsToConnections(connection, session.connections.content); - }); - this.activeSessions.push(newSession); - console.log("New session '" + session.sessionId + "' info fetched"); - sessionChanges[session.sessionId] = true; + + // 3. Add new Session + this.activeSessions.push(fetchedSession); + console.log("New session '" + fetchedSession.sessionId + "' info fetched"); + sessionChanges[fetchedSession.sessionId] = true; globalChanges = true; + } }); - // Remove closed sessions from activeSessions array - this.activeSessions = this.activeSessions.filter(session => { - if (fetchedSessionIds.includes(session.sessionId)) { - return true; - } else { - console.log("Removing closed session '" + session.sessionId + "'"); - sessionChanges[session.sessionId] = true; + + // 4. Remove closed sessions from local collection + for (var i = this.activeSessions.length - 1; i >= 0; --i) { + let sessionId = this.activeSessions[i].sessionId; + if (!fetchedSessionIds.includes(sessionId)) { + console.log("Removing closed session '" + sessionId + "'"); + sessionChanges[sessionId] = true; globalChanges = true; - return false; + this.activeSessions.splice(i, 1); } - }); + } + console.log('Active sessions info fetched: ', fetchedSessionIds); resolve({ changes: globalChanges, sessionChanges }); } else { diff --git a/openvidu-node-client/src/Publisher.ts b/openvidu-node-client/src/Publisher.ts index d88a009a..fa3ce8d2 100644 --- a/openvidu-node-client/src/Publisher.ts +++ b/openvidu-node-client/src/Publisher.ts @@ -74,6 +74,13 @@ export class Publisher { * @hidden */ constructor(json) { + this.resetWithJson(json); + } + + /** + * @hidden + */ + resetWithJson(json): Publisher { this.streamId = json.streamId; this.createdAt = json.createdAt; this.hasAudio = json.mediaOptions.hasAudio; @@ -83,6 +90,7 @@ export class Publisher { this.frameRate = json.mediaOptions.frameRate; this.typeOfVideo = json.mediaOptions.typeOfVideo; this.videoDimensions = json.mediaOptions.videoDimensions; + return this; } /** diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 6fac15ac..10711654 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -82,7 +82,7 @@ export class Session { // Defined parameter if (!!propertiesOrJson.sessionId) { // Parameter is a JSON representation of Session ('sessionId' property always defined) - this.resetSessionWithJson(propertiesOrJson); + this.resetWithJson(propertiesOrJson); } else { // Parameter is a SessionProperties object this.properties = propertiesOrJson; @@ -224,7 +224,7 @@ export class Session { .then(res => { if (res.status === 200) { // SUCCESS response from openvidu-server - this.resetSessionWithJson(res.data); + this.resetWithJson(res.data); const afterJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference); const hasChanged: boolean = !(beforeJSON === afterJSON); console.log("Session info fetched for session '" + this.sessionId + "'. Any change: " + hasChanged); @@ -488,42 +488,57 @@ export class Session { /** * @hidden */ - public resetSessionWithJson(json): Session { + public resetWithJson(json): Session { this.sessionId = json.sessionId; this.createdAt = json.createdAt; this.recording = json.recording; - let customSessionId: string; - let defaultCustomLayout: string; - if (!!this.properties) { - customSessionId = this.properties.customSessionId; - defaultCustomLayout = !!json.defaultCustomLayout ? json.defaultCustomLayout : this.properties.defaultCustomLayout; - } this.properties = { + customSessionId: json.customSessionId, mediaMode: json.mediaMode, recordingMode: json.recordingMode, defaultOutputMode: json.defaultOutputMode, - defaultRecordingLayout: json.defaultRecordingLayout + defaultRecordingLayout: json.defaultRecordingLayout, + defaultCustomLayout: json.defaultCustomLayout }; - if (!!customSessionId) { - this.properties.customSessionId = customSessionId; - } else if (!!json.customSessionId) { - this.properties.customSessionId = json.customSessionId; + if (json.defaultRecordingLayout == null) { + delete this.properties.defaultRecordingLayout; } - if (!!defaultCustomLayout) { - this.properties.defaultCustomLayout = defaultCustomLayout; + if (json.customSessionId == null) { + delete this.properties.customSessionId; + } + if (json.defaultCustomLayout == null) { + delete this.properties.defaultCustomLayout; } - this.connections = []; - this.activeConnections = []; + // 1. Array to store fetched connections and later remove closed ones + const fetchedConnectionIds: string[] = []; json.connections.content.forEach(jsonConnection => { - const con = new Connection(jsonConnection); - this.connections.push(con); + + const connectionObj: Connection = new Connection(jsonConnection); + fetchedConnectionIds.push(connectionObj.connectionId); + let storedConnection = this.connections.find(c => c.connectionId === connectionObj.connectionId); + + if (!!storedConnection) { + // 2. Update existing Connection + storedConnection.resetWithJson(jsonConnection); + } else { + // 3. Add new Connection + this.connections.push(connectionObj); + } }); + // 4. Remove closed sessions from local collection + for (var i = this.connections.length - 1; i >= 0; --i) { + if (!fetchedConnectionIds.includes(this.connections[i].connectionId)) { + this.connections.splice(i, 1); + } + } + // Order connections by time of creation this.connections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); // Populate activeConnections array this.updateActiveConnectionsArray(); + return this; } From 47f090b2cb661d30bd21b96d8ad3dd7f96f76098 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 17 Oct 2020 19:46:22 +0200 Subject: [PATCH 154/435] openvidu-browser: minor updates in NetworkQualityLevelChangedEvent --- openvidu-browser/src/OpenVidu/Session.ts | 13 +++++++++---- .../src/OpenViduInternal/Events/FilterEvent.ts | 1 - .../Events/NetworkQualityLevelChangedEvent.ts | 13 ++++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 6bc5a075..14906d24 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -71,6 +71,7 @@ const platform: PlatformUtils = PlatformUtils.getInstance(); * - signal ([[SignalEvent]]) * - recordingStarted ([[RecordingEvent]]) * - recordingStopped ([[RecordingEvent]]) + * - networkQualityLevelChanged ([[NetworkQualityLevelChangedEvent]]) * - reconnecting * - reconnected * @@ -935,9 +936,13 @@ export class Session extends EventDispatcher { if (msg.connectionId === this.connection.connectionId) { this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, this.connection)]); } else { - this.getConnection(msg.connectionId, 'Connection not found for connectionId ' + msg.connectionId).then((connection: Connection) => { - this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, connection)]); - }); + this.getConnection(msg.connectionId, 'Connection not found for connectionId ' + msg.connectionId) + .then((connection: Connection) => { + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, connection)]); + }) + .catch(openViduError => { + logger.error(openViduError); + }); } } @@ -1135,7 +1140,7 @@ export class Session extends EventDispatcher { } sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1) { - if( + if ( platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser() || platform.isElectron() || (platform.isSafariBrowser() && !platform.isIonicIos()) || platform.isAndroidBrowser() || platform.isSamsungBrowser() || platform.isIonicAndroid() || diff --git a/openvidu-browser/src/OpenViduInternal/Events/FilterEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/FilterEvent.ts index bdb0fa58..ab327f17 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/FilterEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/FilterEvent.ts @@ -16,7 +16,6 @@ */ import { Event } from './Event'; -import { Stream } from '../../OpenVidu/Stream'; import { Filter } from '../../OpenVidu/Filter'; diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts index 0eb423b2..a9eba26b 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts @@ -20,22 +20,25 @@ import { Session } from '../../OpenVidu/Session'; import { Connection } from '../../OpenVidu/Connection'; /** - * Defines event `networkQualityLevelChangedEvent` dispatched by [[Session]]. - * This event is fired when the network quality of the local connection changes + * Defines event `networkQualityLevelChanged` dispatched by [[Session]]. + * This event is fired when the network quality level of a [[Connection]] changes. */ export class NetworkQualityLevelChangedEvent extends Event { + /** + * New value of the network quality level + */ + qualityLevel: number; /** - * New value of the property (after change, current value) + * Connection for whom the network quality level changed */ - qualityLevel: Object; connection: Connection /** * @hidden */ - constructor(target: Session, qualityLevel: Object, connection: Connection) { + constructor(target: Session, qualityLevel: number, connection: Connection) { super(false, target, 'networkQualityLevelChanged'); this.qualityLevel = qualityLevel; this.connection = connection; From 4a7a2808b648a35a6ce5fca37ad6db80215d6cb1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 17 Oct 2020 19:51:26 +0200 Subject: [PATCH 155/435] openvidu-server: new activeAt property for Connection entity --- .../io/openvidu/java/client/Connection.java | 22 +++++++++++++---- openvidu-node-client/src/Connection.ts | 10 +++++++- .../server/cdr/CDREventParticipant.java | 2 +- .../io/openvidu/server/core/Participant.java | 23 +++++++++--------- .../server/core/SessionEventsHandler.java | 6 ++--- .../java/io/openvidu/server/core/Token.java | 10 +++++++- .../kurento/core/KurentoParticipant.java | 2 +- .../test/e2e/OpenViduTestAppE2eTest.java | 24 +++++++++++++------ 8 files changed, 70 insertions(+), 29 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index aa5e9565..6ba1a9e6 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -34,7 +34,8 @@ public class Connection { private String connectionId; private String status; - private long createdAt; + private Long createdAt; + private Long activeAt; private String location; private String platform; private String clientData; @@ -73,13 +74,22 @@ public class Connection { } /** - * Timestamp when this connection was established, in UTC milliseconds (ms since - * Jan 1, 1970, 00:00:00 UTC) + * Timestamp when this connection was created, in UTC milliseconds (ms since Jan + * 1, 1970, 00:00:00 UTC) */ - public long createdAt() { + public Long createdAt() { return this.createdAt; } + /** + * Timestamp when this connection was taken by a user (passing from status + * "pending" to "active"), in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 + * UTC) + */ + public Long activeAt() { + return this.activeAt; + } + /** * Returns the role of the connection */ @@ -173,6 +183,7 @@ public class Connection { json.addProperty("id", this.getConnectionId()); json.addProperty("status", this.getStatus()); json.addProperty("createdAt", this.createdAt()); + json.addProperty("activeAt", this.activeAt()); json.addProperty("location", this.getLocation()); json.addProperty("platform", this.getPlatform()); json.addProperty("token", this.getToken()); @@ -260,6 +271,9 @@ public class Connection { if (!json.get("createdAt").isJsonNull()) { this.createdAt = json.get("createdAt").getAsLong(); } + if (!json.get("activeAt").isJsonNull()) { + this.activeAt = json.get("activeAt").getAsLong(); + } if (!json.get("location").isJsonNull()) { this.location = json.get("location").getAsString(); } diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 5bd0df9b..0f724f71 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -43,10 +43,16 @@ export class Connection { status: string; /** - * Timestamp when this connection was established, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) + * Timestamp when this connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) */ createdAt: number; + /** + * Timestamp when this connection was taken by a user (passing from status "pending" to "active") + * in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) + */ + activeAt: number; + /** * Role of the connection */ @@ -166,6 +172,7 @@ export class Connection { } this.createdAt = json.createdAt; + this.activeAt = json.activeAt; this.location = json.location; this.platform = json.platform; this.clientData = json.clientData; @@ -181,6 +188,7 @@ export class Connection { this.connectionId === other.connectionId && this.status === other.status && this.createdAt === other.createdAt && + this.activeAt === other.activeAt && this.role === other.role && this.serverData === other.serverData && this.record === other.record && diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventParticipant.java index 8c4fc5b5..6081aab1 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventParticipant.java @@ -28,7 +28,7 @@ public class CDREventParticipant extends CDREventEnd { // participantJoined public CDREventParticipant(Participant participant) { - super(CDREventName.participantJoined, participant.getSessionId(), participant.getCreatedAt()); + super(CDREventName.participantJoined, participant.getSessionId(), participant.getActiveAt()); this.participant = participant; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 1c450ff4..9a638013 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -48,7 +48,7 @@ public class Participant { protected String participantPublicId; // ID to identify the user on clients protected String sessionId; // ID of the session to which the participant belongs protected ParticipantStatus status; // Status of the connection - protected Long createdAt; // Timestamp when this connection was established + protected Long activeAt; // Timestamp when this connection entered status "active" protected String clientMetadata = ""; // Metadata provided on client side protected String serverMetadata = ""; // Metadata provided on server side protected Token token; // Token associated to this participant @@ -78,18 +78,18 @@ public class Participant { public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId, Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType, - Long createdAt) { + Long activeAt) { this.finalUserId = finalUserId; this.participantPrivatetId = participantPrivatetId; this.participantPublicId = participantPublicId; this.sessionId = sessionId; this.status = ParticipantStatus.active; - if (createdAt != null) { - this.createdAt = createdAt; - } else { - this.createdAt = System.currentTimeMillis(); - } this.token = token; + if (activeAt != null) { + this.activeAt = activeAt; + } else { + this.activeAt = System.currentTimeMillis(); + } if (clientMetadata != null) { this.clientMetadata = clientMetadata; } @@ -125,8 +125,8 @@ public class Participant { return sessionId; } - public Long getCreatedAt() { - return this.createdAt; + public Long getActiveAt() { + return this.activeAt; } public String getClientMetadata() { @@ -200,7 +200,7 @@ public class Participant { public void setPublishedAt(Long publishedAt) { this.publishedAt = publishedAt; } - + public Long getPublishedAt() { return publishedAt; } @@ -303,7 +303,8 @@ public class Participant { json.addProperty("status", this.status.name()); json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id" json.addProperty("sessionId", this.sessionId); - json.addProperty("createdAt", this.createdAt); + json.addProperty("createdAt", this.token.getCreatedAt()); + json.addProperty("activeAt", this.activeAt); json.addProperty("location", this.location != null ? this.location.toString() : "unknown"); json.addProperty("platform", this.platform); if (this.token.getToken() != null) { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 153e69c6..54344d8c 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -82,7 +82,7 @@ public class SessionEventsHandler { participantJson.addProperty(ProtocolElements.JOINROOM_PEERID_PARAM, existingParticipant.getParticipantPublicId()); participantJson.addProperty(ProtocolElements.JOINROOM_PEERCREATEDAT_PARAM, - existingParticipant.getCreatedAt()); + existingParticipant.getActiveAt()); // Metadata associated to each existing participant participantJson.addProperty(ProtocolElements.JOINROOM_METADATA_PARAM, @@ -138,7 +138,7 @@ public class SessionEventsHandler { // Metadata associated to new participant notifParams.addProperty(ProtocolElements.PARTICIPANTJOINED_USER_PARAM, participant.getParticipantPublicId()); - notifParams.addProperty(ProtocolElements.PARTICIPANTJOINED_CREATEDAT_PARAM, participant.getCreatedAt()); + notifParams.addProperty(ProtocolElements.PARTICIPANTJOINED_CREATEDAT_PARAM, participant.getActiveAt()); notifParams.addProperty(ProtocolElements.PARTICIPANTJOINED_METADATA_PARAM, participant.getFullMetadata()); @@ -147,7 +147,7 @@ public class SessionEventsHandler { } } result.addProperty(ProtocolElements.PARTICIPANTJOINED_USER_PARAM, participant.getParticipantPublicId()); - result.addProperty(ProtocolElements.PARTICIPANTJOINED_CREATEDAT_PARAM, participant.getCreatedAt()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_CREATEDAT_PARAM, participant.getActiveAt()); result.addProperty(ProtocolElements.PARTICIPANTJOINED_METADATA_PARAM, participant.getFullMetadata()); result.add("value", resultArray); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index db31f8ad..947c99f3 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -30,6 +30,7 @@ public class Token { private String token; private String sessionId; + private Long createdAt; private OpenViduRole role; private String serverMetadata = ""; private boolean record; @@ -43,6 +44,7 @@ public class Token { TurnCredentials turnCredentials, KurentoTokenOptions kurentoTokenOptions) { this.token = token; this.sessionId = sessionId; + this.createdAt = System.currentTimeMillis(); this.role = role; this.serverMetadata = serverMetadata; this.record = record; @@ -58,6 +60,10 @@ public class Token { this.token = token; } + public Long getCreatedAt() { + return this.createdAt; + } + public OpenViduRole getRole() { return role; } @@ -96,6 +102,7 @@ public class Token { json.addProperty("object", "token"); json.addProperty("token", this.getToken()); json.addProperty("connectionId", this.getConnectionId()); + json.addProperty("createdAt", this.createdAt); json.addProperty("session", this.sessionId); json.addProperty("role", this.getRole().toString()); json.addProperty("data", this.getServerMetadata()); @@ -113,7 +120,8 @@ public class Token { json.addProperty("status", ParticipantStatus.pending.name()); json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id json.addProperty("sessionId", this.sessionId); - json.add("createdAt", null); + json.addProperty("createdAt", this.createdAt); + json.add("activeAt", null); json.add("location", null); json.add("platform", null); json.addProperty("token", this.getToken()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 68a7008b..306e5034 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -80,7 +80,7 @@ public class KurentoParticipant extends Participant { super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(), kurentoSession.getSessionId(), participant.getToken(), participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(), participant.getEndpointType(), - participant.getCreatedAt()); + participant.getActiveAt()); this.endpointConfig = endpointConfig; this.openviduConfig = openviduConfig; this.recordingManager = recordingManager; diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 1ea36adf..8d10bb35 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.Assert; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -85,8 +86,8 @@ import io.openvidu.test.browsers.utils.webhook.CustomWebhook; public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; - final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','role':'STR','data':'STR','record':true}"; - final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; + final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','createdAt':0,'role':'STR','data':'STR','record':true}"; + final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; @BeforeAll() protected static void setupAll() { @@ -2167,7 +2168,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertTrue("Wrong record property", connectionModerator.record()); Assert.assertNull("Wrong location property", connectionModerator.getLocation()); Assert.assertNull("Wrong platform property", connectionModerator.getPlatform()); - Assert.assertEquals("Wrong createdAt property", 0, connectionModerator.createdAt()); + Assert.assertTrue("Wrong createdAt property", connectionModerator.createdAt() > 0); + Assert.assertNull("Wrong activeAt property", connectionModerator.activeAt()); Assert.assertNull("Wrong clientData property", connectionModerator.getClientData()); Assert.assertEquals("Wrong publishers property", 0, connectionModerator.getPublishers().size()); Assert.assertEquals("Wrong subscribers property", 0, connectionModerator.getSubscribers().size()); @@ -2241,6 +2243,11 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong status for moderator connection", "active", connectionModerator.getStatus()); Assert.assertEquals("Wrong status for subscriber connection", "active", connectionSubscriber.getStatus()); + // Verify createdAt and activeAt + Assert.assertTrue("Wrong createdAt property", connectionModerator.createdAt() > 0); + Assert.assertTrue("Wrong activeAt property", connectionModerator.activeAt() > 0); + Assert.assertTrue("Wrong activeAt property", connectionModerator.activeAt() > connectionModerator.createdAt()); + // Verify platform Assert.assertTrue("Wrong platform for moderator connection", connectionModerator.getPlatform().startsWith("Chrome")); @@ -2319,7 +2326,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { String widthAndHeight = user.getEventManager().getDimensionOfViewport(); JsonObject obj = JsonParser.parseString(widthAndHeight).getAsJsonObject(); Assert.assertEquals( - "{\"width\":" + obj.get("width").getAsLong() + ",\"height\":" + (obj.get("height").getAsLong()) + "}", + "{\"width\":" + obj.get("width").getAsLong() + ",\"height\":" + obj.get("height").getAsLong() + "}", pub.getVideoDimensions()); Assert.assertEquals(new Integer(30), pub.getFrameRate()); Assert.assertEquals("SCREEN", pub.getTypeOfVideo()); @@ -2620,9 +2627,10 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 200 body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'videoMaxSendBandwidth':777,'allowedFilters': ['GStreamerFilter']}}"; res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, - "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); + "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','createdAt':0,'role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); final String token1 = res.get("token").getAsString(); final String connectionId1 = res.get("connectionId").getAsString(); + final long createdAt1 = res.get("createdAt").getAsLong(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); @@ -2641,8 +2649,9 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { HttpStatus.SC_OK, true, true, true, "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + "','object':'connection','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" - + token1 - + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); + + token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':" + + createdAt1 + + ",'activeAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ body = "{}"; @@ -2932,6 +2941,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("Kurento reconnect test") + @Disabled void kurentoReconnectTest() throws Exception { isRecordingTest = true; isKurentoRestartTest = true; From 99cd6d2f9ce7120547fb9aa9afa18c68b79f34a9 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 17 Oct 2020 20:22:51 +0200 Subject: [PATCH 156/435] openvidu-server: limit OPENVIDU_SECRET format to [a-zA-Z0-9_-] --- .../io/openvidu/server/config/OpenviduConfig.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index 66906af1..165d3cd6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -483,7 +483,8 @@ public class OpenviduConfig { coturnRedisConnectTimeout = getValue("COTURN_REDIS_CONNECT_TIMEOUT"); - openviduSecret = asNonEmptyString("OPENVIDU_SECRET"); + openviduSecret = asNonEmptyAlphanumericString("OPENVIDU_SECRET", + "Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens (\"-\") and underscores (\"_\")"); openviduCdr = asBoolean("OPENVIDU_CDR"); openviduCdrPath = openviduCdr ? asWritableFileSystemPath("OPENVIDU_CDR_PATH") @@ -741,6 +742,17 @@ public class OpenviduConfig { } } + protected String asNonEmptyAlphanumericString(String property, String errorMessage) { + final String REGEX = "^[a-zA-Z0-9_-]+$"; + String stringValue = getValue(property); + if (stringValue != null && !stringValue.isEmpty() && stringValue.matches(REGEX)) { + return stringValue; + } else { + addError(property, errorMessage); + return null; + } + } + protected String asOptionalString(String property) { return getValue(property); } From 5e39e4322276b34de2fd2f2a4b8cb62d8273d6b5 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 17 Oct 2020 20:44:43 +0200 Subject: [PATCH 157/435] openvidu-test-e2e: fix pro REST API test --- .../io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index bd14255e..81c35c33 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -193,6 +193,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); final String token = res.get("token").getAsString(); final String tokenConnectionId = res.get("connectionId").getAsString(); + final long createdAt = res.get("createdAt").getAsLong(); /** UPDATE TOKEN **/ @@ -213,13 +214,15 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" + + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, true, true, true, "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':null,'platform':null,'location':null,'clientData':null}"); + + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" + + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); // Test with openvidu-java-client OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); From 43f2f26dbde66f8fdd16b758b0f02b8659a7f842 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 19 Oct 2020 10:35:49 +0200 Subject: [PATCH 158/435] openvidu-test-e2e: enable test --- .../test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 8d10bb35..ba61abe0 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -34,7 +34,6 @@ import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.Assert; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -2941,7 +2940,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("Kurento reconnect test") - @Disabled void kurentoReconnectTest() throws Exception { isRecordingTest = true; isKurentoRestartTest = true; From 759acb1f7c4ea092992d466b76b29f2ccf736fe9 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 19 Oct 2020 12:52:29 +0200 Subject: [PATCH 159/435] openvidu-server: POST Connection --- .../openvidu/server/core/ConnectionType.java | 5 + .../io/openvidu/server/core/Participant.java | 13 +- .../openvidu/server/core/SessionManager.java | 14 +- .../java/io/openvidu/server/core/Token.java | 1 + .../kurento/core/KurentoParticipant.java | 2 +- .../server/rest/SessionRestController.java | 447 ++++++++++-------- ...essionGarbageCollectorIntegrationTest.java | 2 +- .../test/e2e/OpenViduProTestAppE2eTest.java | 21 +- .../test/e2e/OpenViduTestAppE2eTest.java | 13 +- 9 files changed, 302 insertions(+), 216 deletions(-) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java b/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java new file mode 100644 index 00000000..a5206826 --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java @@ -0,0 +1,5 @@ +package io.openvidu.server.core; + +public enum ConnectionType { + WEBRTC, IPCAM +} \ No newline at end of file diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 9a638013..b20f0220 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -43,6 +43,7 @@ public class Participant { active } + protected ConnectionType type; // WEBRTC, IPCAM protected String finalUserId; // ID to match this connection with a final user (HttpSession id) protected String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id) protected String participantPublicId; // ID to identify the user on clients @@ -76,9 +77,10 @@ public class Participant { */ public Lock singleRecordingLock = new ReentrantLock(); - public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId, - Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType, - Long activeAt) { + public Participant(ConnectionType type, String finalUserId, String participantPrivatetId, + String participantPublicId, String sessionId, Token token, String clientMetadata, GeoLocation location, + String platform, EndpointType endpointType, Long activeAt) { + this.type = type; this.finalUserId = finalUserId; this.participantPrivatetId = participantPrivatetId; this.participantPublicId = participantPublicId; @@ -101,6 +103,10 @@ public class Participant { this.endpointType = endpointType; } + public ConnectionType getType() { + return type; + } + public String getFinalUserId() { return finalUserId; } @@ -300,6 +306,7 @@ public class Participant { JsonObject json = new JsonObject(); json.addProperty("id", this.participantPublicId); json.addProperty("object", "connection"); + json.addProperty("type", this.type.name()); json.addProperty("status", this.status.name()); json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id" json.addProperty("sessionId", this.sessionId); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 75e75e44..e6f4fcaf 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -363,8 +363,9 @@ public abstract class SessionManager { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnectionId(), sessionId, - token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null); + Participant p = new Participant(ConnectionType.WEBRTC, finalUserId, participantPrivatetId, + token.getConnectionId(), sessionId, token, clientMetadata, location, platform, + EndpointType.WEBRTC_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p); @@ -384,8 +385,9 @@ public abstract class SessionManager { public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token, String clientMetadata) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(null, participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, - sessionId, token, clientMetadata, null, null, EndpointType.WEBRTC_ENDPOINT, null); + Participant p = new Participant(ConnectionType.WEBRTC, null, participantPrivatetId, + ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, sessionId, token, clientMetadata, null, null, + EndpointType.WEBRTC_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId) .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); return p; @@ -397,8 +399,8 @@ public abstract class SessionManager { public Participant newIpcamParticipant(String sessionId, String ipcamId, Token token, GeoLocation location, String platform) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(ipcamId, ipcamId, ipcamId, sessionId, token, null, location, platform, - EndpointType.PLAYER_ENDPOINT, null); + Participant p = new Participant(ConnectionType.IPCAM, ipcamId, ipcamId, ipcamId, sessionId, token, null, + location, platform, EndpointType.PLAYER_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId).put(ipcamId, p); return p; } else { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 947c99f3..85411ce1 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -117,6 +117,7 @@ public class Token { JsonObject json = new JsonObject(); json.addProperty("id", this.getConnectionId()); json.addProperty("object", "connection"); + json.addProperty("type", ConnectionType.WEBRTC.name()); json.addProperty("status", ParticipantStatus.pending.name()); json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id json.addProperty("sessionId", this.sessionId); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 306e5034..6af8375d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -77,7 +77,7 @@ public class KurentoParticipant extends Participant { public KurentoParticipant(Participant participant, KurentoSession kurentoSession, KurentoParticipantEndpointConfig endpointConfig, OpenviduConfig openviduConfig, RecordingManager recordingManager) { - super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(), + super(participant.getType(), participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(), kurentoSession.getSessionId(), participant.getToken(), participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(), participant.getEndpointType(), participant.getActiveAt()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 7992af8a..ca3ef2dc 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -20,6 +20,7 @@ package io.openvidu.server.rest; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -57,6 +58,7 @@ import io.openvidu.java.client.RecordingMode; import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.config.OpenviduConfig; +import io.openvidu.server.core.ConnectionType; import io.openvidu.server.core.EndReason; import io.openvidu.server.core.IdentifierPrefixes; import io.openvidu.server.core.Participant; @@ -92,7 +94,7 @@ public class SessionRestController { protected OpenviduConfig openviduConfig; @RequestMapping(value = "/sessions", method = RequestMethod.POST) - public ResponseEntity getSessionId(@RequestBody(required = false) Map params) { + public ResponseEntity initializeSession(@RequestBody(required = false) Map params) { log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}"); @@ -267,8 +269,99 @@ public class SessionRestController { } } + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST) + public ResponseEntity initializeConnection(@PathVariable("sessionId") String sessionId, + @RequestBody Map params) { + + log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString()); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + String typeString; + String data; + Boolean record; + try { + typeString = (String) params.get("type"); + data = (String) params.get("data"); + record = (Boolean) params.get("record"); + } catch (ClassCastException e) { + return this.generateErrorResponse("Type error in parameter \"type\"", + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + } + + ConnectionType type; + try { + if (typeString != null) { + type = ConnectionType.valueOf(typeString); + } else { + type = ConnectionType.WEBRTC; + } + } catch (IllegalArgumentException e) { + return this.generateErrorResponse("Parameter type " + params.get("typeString") + " is not defined", + RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + } + + switch (type) { + case WEBRTC: + return this.newWebrtcConnection(session, data, record, params); + case IPCAM: + return this.newIpcamConnection(session, data, record, params); + default: + return this.generateErrorResponse("Wrong type " + typeString, + RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.GET) + public ResponseEntity getConnection(@PathVariable("sessionId") String sessionId, + @PathVariable("connectionId") String connectionId) { + + log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session != null) { + Participant p = session.getParticipantByPublicId(connectionId); + if (p != null) { + return new ResponseEntity<>(p.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + Token t = getTokenFromConnectionId(connectionId, session.getTokenIterator()); + if (t != null) { + return new ResponseEntity<>(t.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), + HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + } else { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + } + + @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.GET) + public ResponseEntity listConnections(@PathVariable("sessionId") String sessionId, + @RequestParam(value = "pendingConnections", defaultValue = "true", required = false) boolean pendingConnections, + @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { + + log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + + if (session != null) { + JsonObject json = new JsonObject(); + JsonArray jsonArray = session.getSnapshotOfConnectionsAsJsonArray(pendingConnections, webRtcStats); + json.addProperty("numberOfElements", jsonArray.size()); + json.add("content", jsonArray); + return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.DELETE) - public ResponseEntity disconnectParticipant(@PathVariable("sessionId") String sessionId, + public ResponseEntity closeConnection(@PathVariable("sessionId") String sessionId, @PathVariable("connectionId") String participantPublicId) { log.info("REST API: DELETE {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, participantPublicId); @@ -292,127 +385,8 @@ public class SessionRestController { } } - @RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE) - public ResponseEntity unpublishStream(@PathVariable("sessionId") String sessionId, - @PathVariable("streamId") String streamId) { - - log.info("REST API: DELETE {}/sessions/{}/stream/{}", RequestMappings.API, sessionId, streamId); - - Session session = this.sessionManager.getSessionWithNotActive(sessionId); - if (session == null) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); - } - - session = this.sessionManager.getSession(sessionId); - if (session != null) { - - final String participantPrivateId = this.sessionManager.getParticipantPrivateIdFromStreamId(sessionId, - streamId); - - if (participantPrivateId == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - Participant participant = this.sessionManager.getParticipant(participantPrivateId); - if (participant.isIpcam()) { - return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED); - } - - this.sessionManager.unpublishStream(session, streamId, null, null, EndReason.forceUnpublishByServer); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } else { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - } - - @RequestMapping(value = "/tokens", method = RequestMethod.POST) - public ResponseEntity newToken(@RequestBody Map params) { - - if (params == null) { - return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/tokens", - HttpStatus.BAD_REQUEST); - } - - log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString()); - - String sessionId; - String roleString; - String metadata; - Boolean record; - try { - sessionId = (String) params.get("session"); - roleString = (String) params.get("role"); - metadata = (String) params.get("data"); - record = (Boolean) params.get("record"); - } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST); - } - - if (sessionId == null) { - return this.generateErrorResponse("\"session\" parameter is mandatory", "/tokens", HttpStatus.BAD_REQUEST); - } - - final Session session = this.sessionManager.getSessionWithNotActive(sessionId); - if (session == null) { - return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); - } - - JsonObject kurentoOptions = null; - - if (params.get("kurentoOptions") != null) { - try { - kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject(); - } catch (Exception e) { - return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object", - "/tokens", HttpStatus.BAD_REQUEST); - } - } - - OpenViduRole role; - try { - if (roleString != null) { - role = OpenViduRole.valueOf(roleString); - } else { - role = OpenViduRole.PUBLISHER; - } - } catch (IllegalArgumentException e) { - return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", "/tokens", - HttpStatus.BAD_REQUEST); - } - - KurentoTokenOptions kurentoTokenOptions = null; - if (kurentoOptions != null) { - try { - kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions); - } catch (Exception e) { - return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", "/tokens", - HttpStatus.BAD_REQUEST); - } - } - - metadata = (metadata != null) ? metadata : ""; - record = (record != null) ? record : true; - - // While closing a session tokens can't be generated - if (session.closingLock.readLock().tryLock()) { - try { - Token token = sessionManager.newToken(session, role, metadata, record, kurentoTokenOptions); - return new ResponseEntity<>(token.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); - } catch (Exception e) { - return this.generateErrorResponse( - "Error generating token for session " + sessionId + ": " + e.getMessage(), "/tokens", - HttpStatus.INTERNAL_SERVER_ERROR); - } finally { - session.closingLock.readLock().unlock(); - } - } else { - log.error("Session {} is in the process of closing. Token couldn't be generated", sessionId); - return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); - } - } - @RequestMapping(value = "/recordings/start", method = RequestMethod.POST) - public ResponseEntity startRecordingSession(@RequestBody Map params) { + public ResponseEntity startRecording(@RequestBody Map params) { if (params == null) { return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/recordings/start", @@ -568,7 +542,7 @@ public class SessionRestController { } @RequestMapping(value = "/recordings/stop/{recordingId}", method = RequestMethod.POST) - public ResponseEntity stopRecordingSession(@PathVariable("recordingId") String recordingId) { + public ResponseEntity stopRecording(@PathVariable("recordingId") String recordingId) { log.info("REST API: POST {}/recordings/stop/{}", RequestMappings.API, recordingId); @@ -632,7 +606,7 @@ public class SessionRestController { } @RequestMapping(value = "/recordings", method = RequestMethod.GET) - public ResponseEntity getAllRecordings() { + public ResponseEntity listRecordings() { log.info("REST API: GET {}/recordings", RequestMappings.API); @@ -669,6 +643,87 @@ public class SessionRestController { return new ResponseEntity<>(this.recordingManager.deleteRecordingFromHost(recordingId, false)); } + @RequestMapping(value = "/tokens", method = RequestMethod.POST) + public ResponseEntity newToken(@RequestBody Map params) { + + if (params == null) { + return this.generateErrorResponse("Error in body parameters. Cannot be empty", "/tokens", + HttpStatus.BAD_REQUEST); + } + + log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString()); + + String sessionId; + String metadata; + Boolean record; + try { + sessionId = (String) params.get("session"); + metadata = (String) params.get("data"); + record = (Boolean) params.get("record"); + } catch (ClassCastException e) { + return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST); + } + + if (sessionId == null) { + return this.generateErrorResponse("\"session\" parameter is mandatory", "/tokens", HttpStatus.BAD_REQUEST); + } + + log.warn("Token API is deprecated. Use Connection API instead (POST {}/sessions/{}/connection)", + RequestMappings.API, sessionId); + + final Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session == null) { + return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); + } + Map map = new HashMap<>(); + params.entrySet().forEach(entry -> map.put((String) entry.getKey(), entry.getValue())); + map.put("type", "WEBRTC"); + ResponseEntity entity = this.newWebrtcConnection(session, metadata, record, params); + JsonObject jsonResponse = JsonParser.parseString(entity.getBody().toString()).getAsJsonObject(); + + if (jsonResponse.has("error")) { + return this.generateErrorResponse(jsonResponse.get("message").getAsString(), "/tokens", + HttpStatus.valueOf(jsonResponse.get("status").getAsInt())); + } else { + String connectionId = jsonResponse.get("id").getAsString(); + Token token = getTokenFromConnectionId(connectionId, session.getTokenIterator()); + return new ResponseEntity<>(token.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + } + } + + @RequestMapping(value = "/sessions/{sessionId}/stream/{streamId}", method = RequestMethod.DELETE) + public ResponseEntity unpublishStream(@PathVariable("sessionId") String sessionId, + @PathVariable("streamId") String streamId) { + + log.info("REST API: DELETE {}/sessions/{}/stream/{}", RequestMappings.API, sessionId, streamId); + + Session session = this.sessionManager.getSessionWithNotActive(sessionId); + if (session == null) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + } + + session = this.sessionManager.getSession(sessionId); + if (session != null) { + + final String participantPrivateId = this.sessionManager.getParticipantPrivateIdFromStreamId(sessionId, + streamId); + + if (participantPrivateId == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + Participant participant = this.sessionManager.getParticipant(participantPrivateId); + if (participant.isIpcam()) { + return new ResponseEntity<>(HttpStatus.METHOD_NOT_ALLOWED); + } + + this.sessionManager.unpublishStream(session, streamId, null, null, EndReason.forceUnpublishByServer); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + @RequestMapping(value = "/signal", method = RequestMethod.POST) public ResponseEntity signal(@RequestBody Map params) { @@ -738,99 +793,108 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.OK); } - @RequestMapping(value = "/sessions/{sessionId}/connection/{connectionId}", method = RequestMethod.GET) - public ResponseEntity getConnection(@PathVariable("sessionId") String sessionId, - @PathVariable("connectionId") String connectionId) { + protected ResponseEntity newWebrtcConnection(Session session, String serverData, Boolean record, + Map params) { - log.info("REST API: GET {}/sessions/{}/connection/{}", RequestMappings.API, sessionId, connectionId); + final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection"; - Session session = this.sessionManager.getSessionWithNotActive(sessionId); - if (session != null) { - Participant p = session.getParticipantByPublicId(connectionId); - if (p != null) { - return new ResponseEntity<>(p.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); + String roleString = null; + try { + roleString = (String) params.get("role"); + } catch (ClassCastException e) { + return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST); + } + + OpenViduRole role = null; + try { + if (roleString != null) { + role = OpenViduRole.valueOf(roleString); } else { - Token t = getTokenFromConnectionId(connectionId, session.getTokenIterator()); - if (t != null) { - return new ResponseEntity<>(t.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), - HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } + role = OpenViduRole.PUBLISHER; + } + } catch (IllegalArgumentException e) { + return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", REQUEST_PATH, + HttpStatus.BAD_REQUEST); + } + + JsonObject kurentoOptions = null; + if (params.get("kurentoOptions") != null) { + try { + kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject(); + } catch (Exception e) { + return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object", + REQUEST_PATH, HttpStatus.BAD_REQUEST); + } + } + + KurentoTokenOptions kurentoTokenOptions = null; + if (kurentoOptions != null) { + try { + kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions); + } catch (Exception e) { + return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", REQUEST_PATH, + HttpStatus.BAD_REQUEST); + } + } + + serverData = (serverData != null) ? serverData : ""; + record = (record != null) ? record : true; + + // While closing a session tokens can't be generated + if (session.closingLock.readLock().tryLock()) { + try { + Token token = sessionManager.newToken(session, role, serverData, record, kurentoTokenOptions); + return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), + HttpStatus.OK); + } catch (Exception e) { + return this.generateErrorResponse( + "Error creating Connection for session " + session.getSessionId() + ": " + e.getMessage(), + REQUEST_PATH, HttpStatus.INTERNAL_SERVER_ERROR); + } finally { + session.closingLock.readLock().unlock(); } } else { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + log.error("Session {} is in the process of closing. Connection couldn't be created", + session.getSessionId()); + return this.generateErrorResponse("Session " + session.getSessionId() + " not found", REQUEST_PATH, + HttpStatus.NOT_FOUND); } } - @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.GET) - public ResponseEntity listConnections(@PathVariable("sessionId") String sessionId, - @RequestParam(value = "pendingConnections", defaultValue = "true", required = false) boolean pendingConnections, - @RequestParam(value = "webRtcStats", defaultValue = "false", required = false) boolean webRtcStats) { + protected ResponseEntity newIpcamConnection(Session session, String serverData, Boolean record, + Map params) { - log.info("REST API: GET {}/sessions/{}/connection", RequestMappings.API, sessionId); + final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection"; - Session session = this.sessionManager.getSessionWithNotActive(sessionId); - - if (session != null) { - JsonObject json = new JsonObject(); - JsonArray jsonArray = session.getSnapshotOfConnectionsAsJsonArray(pendingConnections, webRtcStats); - json.addProperty("numberOfElements", jsonArray.size()); - json.add("content", jsonArray); - return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); - } else { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - } - - @RequestMapping(value = "/sessions/{sessionId}/connection", method = RequestMethod.POST) - public ResponseEntity publishIpcam(@PathVariable("sessionId") String sessionId, @RequestBody Map params) { - - if (params == null) { - return this.generateErrorResponse("Error in body parameters. Cannot be empty", - "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); - } - - log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString()); - - Session session = this.sessionManager.getSessionWithNotActive(sessionId); - if (session == null) { - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - - String type; String rtspUri; Boolean adaptativeBitrate; Boolean onlyPlayWithSubscribers; Integer networkCache; - String data; try { - type = (String) params.get("type"); rtspUri = (String) params.get("rtspUri"); adaptativeBitrate = (Boolean) params.get("adaptativeBitrate"); onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers"); networkCache = (Integer) params.get("networkCache"); - data = (String) params.get("data"); } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/sessions/" + sessionId + "/connection", - HttpStatus.BAD_REQUEST); - } - if (rtspUri == null) { - return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", - "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST); + } + + if (rtspUri == null) { + return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", REQUEST_PATH, + HttpStatus.BAD_REQUEST); } - type = "IPCAM"; // Other possible values in the future adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true; onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true; networkCache = networkCache != null ? networkCache : 2000; - data = data != null ? data : ""; + serverData = serverData != null ? serverData : ""; + record = (record != null) ? record : true; boolean hasAudio = true; boolean hasVideo = true; boolean audioActive = true; boolean videoActive = true; - String typeOfVideo = type; + String typeOfVideo = ConnectionType.IPCAM.name(); Integer frameRate = null; String videoDimensions = null; KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive, @@ -843,15 +907,14 @@ public class SessionRestController { if (session.isClosed()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, data); + Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, serverData); return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (MalformedURLException e) { - return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri", - "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri", REQUEST_PATH, + HttpStatus.BAD_REQUEST); } catch (Exception e) { - return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", - HttpStatus.INTERNAL_SERVER_ERROR); + return this.generateErrorResponse(e.getMessage(), REQUEST_PATH, HttpStatus.INTERNAL_SERVER_ERROR); } finally { session.closingLock.readLock().unlock(); } diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index e4abf225..125c1ea3 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -98,7 +98,7 @@ public class SessionGarbageCollectorIntegrationTest { } private String getSessionId() { - String stringResponse = (String) sessionRestController.getSessionId(new HashMap<>()).getBody(); + String stringResponse = (String) sessionRestController.initializeSession(new HashMap<>()).getBody(); return new Gson().fromJson(stringResponse, JsonObject.class).get("id").getAsString(); } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 81c35c33..84957007 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -212,14 +212,16 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'pending','connectionId':'" + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); @@ -282,23 +284,28 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" + tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId + "','object':'connection','status':'active','connectionId':'" + "{'role':'PUBLISHER'}", HttpStatus.SC_OK, + false, true, true, + "{'id':'" + tokenConnectionId + + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" + tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index ba61abe0..eee638ac 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -86,7 +86,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','createdAt':0,'role':'STR','data':'STR','record':true}"; - final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; + final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','type':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; @BeforeAll() protected static void setupAll() { @@ -2647,7 +2647,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, HttpStatus.SC_OK, true, true, true, "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 - + "','object':'connection','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" + + "','object':'connection','type':'WEBRTC','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" + token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':" + createdAt1 + ",'activeAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); @@ -2744,13 +2744,13 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, HttpStatus.SC_OK, false, true, false, "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 - + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token1 - + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true}"); + + "','object':'connection','type':'WEBRTC','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + + token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true}"); restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId2, null, HttpStatus.SC_OK, false, true, false, "{'id':'" + connectionId2 + "','connectionId':'" + connectionId2 - + "','object':'connection','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + token2 - + "','role':'PUBLISHER','serverData':'','record':true}"); + + "','object':'connection','type':'WEBRTC','status':'active','sessionId':'CUSTOM_SESSION_ID','token':'" + + token2 + "','role':'PUBLISHER','serverData':'','record':true}"); /** GET /openvidu/api/recordings (before recording started) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/recordings/NOT_EXISTS", HttpStatus.SC_NOT_FOUND); @@ -3291,6 +3291,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong serverData property", "MY_IP_CAMERA", response.get("serverData").getAsString()); Assert.assertEquals("Wrong platform property", "IPCAM", response.get("platform").getAsString()); Assert.assertEquals("Wrong role property", "PUBLISHER", response.get("role").getAsString()); + Assert.assertEquals("Wrong type property", "IPCAM", response.get("type").getAsString()); Assert.assertEquals("Wrong number of publishers in IPCAM participant", 1, response.get("publishers").getAsJsonArray().size()); From 98d73023d03497b9ef00ea139b2854ae444de9e4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 19 Oct 2020 13:38:54 +0200 Subject: [PATCH 160/435] openvidu-test-e2e: fix ipCamera test --- .../openvidu/test/e2e/OpenViduProTestAppE2eTest.java | 3 +-- .../io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 84957007..f075ec1b 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -302,8 +302,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, - "{'role':'PUBLISHER'}", HttpStatus.SC_OK, - false, true, true, + "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, "{'id':'" + tokenConnectionId + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" + tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index eee638ac..7316d1f6 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -3264,7 +3264,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); // Wrong session [404] - restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/WRONG_SESSION/connection", "{}", + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/WRONG_SESSION/connection", "{'type':'IPCAM'}", HttpStatus.SC_NOT_FOUND); // Init a session and publish IP camera AS FIRST PARTICIPANT @@ -3272,12 +3272,16 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_SESSION); // No rtspUri [400] - restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", "{}", + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", "{'type':'IPCAM'}", HttpStatus.SC_BAD_REQUEST); // Wrong rtspUri (invalid url format) [400] restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", - "{'rtspUri': 'NOT_A_URL'}", HttpStatus.SC_BAD_REQUEST); + "{'type':'IPCAM','rtspUri': 'NOT_A_URL'}", HttpStatus.SC_BAD_REQUEST); + // Wrong adaptativeBitrate [400] + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", + "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':123,}", + HttpStatus.SC_BAD_REQUEST); // Publish IP camera. Dummy URL because no user will subscribe to it [200] String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; @@ -3458,7 +3462,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Publish video only IPCAM fullRecordingPath = "file://" + recPath + "TestSession-1/videoOnly.mp4"; - ipCamBody = "{'rtspUri':'" + fullRecordingPath + "'}"; + ipCamBody = "{'type':'IPCAM','rtspUri':'" + fullRecordingPath + "'}"; response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, HttpStatus.SC_OK); CustomWebhook.waitForEvent("sessionCreated", 1); From 06a602cf62b9ca51ebbd56a1358d4c217240bef8 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 19 Oct 2020 14:21:49 +0200 Subject: [PATCH 161/435] openvidu-server: ConnectionType transferred to openvidu-java-client --- .../openvidu/java/client/ConnectionType.java | 20 +++++++++++++++++++ .../openvidu/server/core/ConnectionType.java | 5 ----- .../io/openvidu/server/core/Participant.java | 1 + .../openvidu/server/core/SessionManager.java | 1 + .../java/io/openvidu/server/core/Token.java | 1 + .../server/rest/SessionRestController.java | 2 +- 6 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionType.java delete mode 100644 openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionType.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionType.java new file mode 100644 index 00000000..11c1d2a8 --- /dev/null +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionType.java @@ -0,0 +1,20 @@ +package io.openvidu.java.client; + +/** + * See + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)} + */ +public enum ConnectionType { + + /** + * WebRTC connection. This is the normal type of Connection for a regular user + * connecting to a session from an application. + */ + WEBRTC, + + /** + * IP camera connection. This is the type of Connection used by IP cameras to + * connect to a session. + */ + IPCAM +} diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java b/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java deleted file mode 100644 index a5206826..00000000 --- a/openvidu-server/src/main/java/io/openvidu/server/core/ConnectionType.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.openvidu.server.core; - -public enum ConnectionType { - WEBRTC, IPCAM -} \ No newline at end of file diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index b20f0220..4acc2671 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -22,6 +22,7 @@ import java.util.concurrent.locks.ReentrantLock; import com.google.gson.JsonObject; +import io.openvidu.java.client.ConnectionType; import io.openvidu.server.kurento.endpoint.EndpointType; import io.openvidu.server.utils.GeoLocation; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index e6f4fcaf..e51dd190 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -45,6 +45,7 @@ import com.google.gson.JsonSyntaxException; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.SessionProperties; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 85411ce1..b0fe7d30 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -21,6 +21,7 @@ import org.apache.commons.lang3.RandomStringUtils; import com.google.gson.JsonObject; +import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.core.Participant.ParticipantStatus; import io.openvidu.server.coturn.TurnCredentials; diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index ca3ef2dc..4b7dea45 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -50,6 +50,7 @@ import com.google.gson.JsonParser; import io.openvidu.client.OpenViduException; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording.OutputMode; @@ -58,7 +59,6 @@ import io.openvidu.java.client.RecordingMode; import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.config.OpenviduConfig; -import io.openvidu.server.core.ConnectionType; import io.openvidu.server.core.EndReason; import io.openvidu.server.core.IdentifierPrefixes; import io.openvidu.server.core.Participant; From f989b0c2ee930a6483c1532d49431044794cda6d Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 20 Oct 2020 22:09:06 +0200 Subject: [PATCH 162/435] POST Connection API --- .../io/openvidu/java/client/Connection.java | 190 +++++++++-- .../java/client/ConnectionOptions.java | 308 +++++++++++++++--- .../openvidu/java/client/KurentoOptions.java | 82 +++-- .../io/openvidu/java/client/OpenVidu.java | 4 + .../java/io/openvidu/java/client/Session.java | 275 ++++++++-------- .../java/io/openvidu/java/client/Token.java | 127 -------- .../io/openvidu/java/client/TokenOptions.java | 31 +- openvidu-node-client/src/Connection.ts | 117 ++++--- openvidu-node-client/src/ConnectionOptions.ts | 62 +++- openvidu-node-client/src/ConnectionType.ts | 34 ++ openvidu-node-client/src/OpenVidu.ts | 1 + openvidu-node-client/src/Session.ts | 92 ++++-- openvidu-node-client/src/Token.ts | 81 ----- openvidu-node-client/src/TokenOptions.ts | 2 +- openvidu-node-client/src/index.ts | 2 +- .../io/openvidu/server/core/Participant.java | 43 +-- .../openvidu/server/core/SessionManager.java | 35 +- .../java/io/openvidu/server/core/Token.java | 151 ++++++--- .../openvidu/server/core/TokenGenerator.java | 12 +- .../kurento/core/KurentoParticipant.java | 2 +- .../kurento/core/KurentoSessionManager.java | 14 +- .../kurento/core/KurentoTokenOptions.java | 107 ------ .../kurento/endpoint/MediaEndpoint.java | 4 +- .../recording/RecorderEndpointWrapper.java | 4 +- .../server/rest/SessionRestController.java | 268 ++++++++------- .../io/openvidu/server/rpc/RpcHandler.java | 5 +- ...essionGarbageCollectorIntegrationTest.java | 5 +- .../test/browsers/utils/CustomHttpClient.java | 5 +- .../e2e/AbstractOpenViduTestAppE2eTest.java | 20 ++ .../test/e2e/OpenViduProTestAppE2eTest.java | 70 ++-- .../test/e2e/OpenViduTestAppE2eTest.java | 153 ++++++--- 31 files changed, 1350 insertions(+), 956 deletions(-) delete mode 100644 openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java create mode 100644 openvidu-node-client/src/ConnectionType.ts delete mode 100644 openvidu-node-client/src/Token.ts delete mode 100644 openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index 6ba1a9e6..600ef600 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -39,7 +39,8 @@ public class Connection { private String location; private String platform; private String clientData; - private Token token; + private ConnectionOptions connectionOptions; + private String token; protected Map publishers = new ConcurrentHashMap<>(); protected List subscribers = new ArrayList<>(); @@ -49,7 +50,7 @@ public class Connection { } /** - * Returns the identifier of the connection. You can call methods + * Returns the identifier of the Connection. You can call methods * {@link io.openvidu.java.client.Session#forceDisconnect(String)} or * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} * passing this property as parameter @@ -59,7 +60,7 @@ public class Connection { } /** - * Returns the status of the connection. Can be: + * Returns the status of the Connection. Can be: *
    *
  • pending: if the Connection is waiting for any user to use * its internal token to connect to the session, calling method INDIVIDUAL recording. */ public boolean record() { - return this.token.record(); + return this.connectionOptions.record(); } /** - * Returns the token string associated to the connection + * Returns the role of the Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#WEBRTC} + */ + public OpenViduRole getRole() { + return this.connectionOptions.getRole(); + } + + /** + * Returns the RTSP URI of the Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public String getRtspUri() { + return this.connectionOptions.getRtspUri(); + } + + /** + * Whether the Connection uses adaptative bitrate (and therefore adaptative + * quality) or not. For local network connections that do not require media + * transcoding this can be disabled to save CPU power. If you are not sure if + * transcoding might be necessary, setting this property to false may + * result in media connections not being established. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public boolean adaptativeBitrate() { + return this.connectionOptions.adaptativeBitrate(); + } + + /** + * Whether the IP camera stream of this Connection will only be enabled when + * some user is subscribed to it, or not. This allows you to reduce power + * consumption and network bandwidth in your server while nobody is asking to + * receive the camera's video. On the counterpart, first user subscribing to the + * IP camera stream will take a little longer to receive its video. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public boolean onlyPlayWithSubscribers() { + return this.connectionOptions.onlyPlayWithSubscribers(); + } + + /** + * Returns the size of the buffer of the endpoint receiving the IP camera's + * stream, in milliseconds. The smaller it is, the less delay the signal will + * have, but more problematic will be in unstable networks. Use short buffers + * only if there is a quality connection between the IP camera and OpenVidu + * Server. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public int getNetworkCache() { + return this.connectionOptions.getNetworkCache(); + } + + /** + * Returns the token string associated to the Connection */ public String getToken() { - return this.token.getToken(); + return this.token; } /** @@ -180,17 +253,23 @@ public class Connection { protected JsonObject toJson() { JsonObject json = new JsonObject(); - json.addProperty("id", this.getConnectionId()); + json.addProperty("connectionId", this.getConnectionId()); json.addProperty("status", this.getStatus()); json.addProperty("createdAt", this.createdAt()); json.addProperty("activeAt", this.activeAt()); json.addProperty("location", this.getLocation()); json.addProperty("platform", this.getPlatform()); - json.addProperty("token", this.getToken()); - json.addProperty("role", this.getRole().name()); - json.addProperty("serverData", this.getServerData()); - json.addProperty("record", this.record()); json.addProperty("clientData", this.getClientData()); + json.addProperty("token", this.getToken()); + + JsonObject jsonConnectionOptions = this.connectionOptions.toJson(""); + jsonConnectionOptions.remove("session"); + json.addProperty("serverData", jsonConnectionOptions.get("data").getAsString()); + jsonConnectionOptions.remove("data"); + jsonConnectionOptions.entrySet().forEach(entry -> { + json.add(entry.getKey(), entry.getValue()); + }); + JsonArray pubs = new JsonArray(); this.getPublishers().forEach(p -> { pubs.add(p.toJson()); @@ -204,14 +283,33 @@ public class Connection { return json; } - /** - * For now only properties data, role and record can be updated - */ - protected void overrideConnectionOptions(ConnectionOptions connectionOptions) { - TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(connectionOptions.getRole()) - .record(connectionOptions.record()); - modifiableTokenOptions.data(this.token.getData()); - this.token.overrideTokenOptions(modifiableTokenOptions.build()); + protected void overrideConnectionOptions(ConnectionOptions newConnectionOptions) { + ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + // For now only properties role and record can be updated + if (newConnectionOptions.getRole() != null) { + builder.role(newConnectionOptions.getRole()); + } else { + builder.role(this.connectionOptions.getRole()); + } + if (newConnectionOptions.record() != null) { + builder.record(newConnectionOptions.record()); + } else { + builder.record(this.connectionOptions.record()); + } + // Keep old configuration in the rest of properties + builder.type(this.connectionOptions.getType()).data(this.connectionOptions.getData()) + .kurentoOptions(this.connectionOptions.getKurentoOptions()) + .rtspUri(this.connectionOptions.getRtspUri()); + if (this.connectionOptions.adaptativeBitrate() != null) { + builder.adaptativeBitrate(this.connectionOptions.adaptativeBitrate()); + } + if (this.connectionOptions.onlyPlayWithSubscribers() != null) { + builder.onlyPlayWithSubscribers(this.connectionOptions.onlyPlayWithSubscribers()); + } + if (this.connectionOptions.getNetworkCache() != null) { + builder.networkCache(this.connectionOptions.getNetworkCache()); + } + this.connectionOptions = builder.build(); } protected void setSubscribers(List subscribers) { @@ -220,6 +318,10 @@ public class Connection { protected Connection resetWithJson(JsonObject json) { + this.connectionId = json.get("connectionId").getAsString(); + this.status = json.get("status").getAsString(); + this.token = !json.get("token").isJsonNull() ? json.get("token").getAsString() : null; + if (!json.get("publishers").isJsonNull()) { JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray(); @@ -284,16 +386,34 @@ public class Connection { this.clientData = json.get("clientData").getAsString(); } - // These properties won't ever be null - this.connectionId = json.get("connectionId").getAsString(); - this.status = json.get("status").getAsString(); - String token = json.has("token") ? json.get("token").getAsString() : null; - OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); - String data = json.get("serverData").getAsString(); - Boolean record = json.get("record").getAsBoolean(); + // COMMON + ConnectionType type = ConnectionType.valueOf(json.get("type").getAsString()); + String data = (json.has("serverData") && !json.get("serverData").isJsonNull()) + ? json.get("serverData").getAsString() + : null; + Boolean record = (json.has("record") && !json.get("record").isJsonNull()) ? json.get("record").getAsBoolean() + : null; - TokenOptions tokenOptions = new TokenOptions(role, data, record, null); - this.token = new Token(token, this.connectionId, tokenOptions); + // WEBRTC + OpenViduRole role = (json.has("role") && !json.get("role").isJsonNull()) + ? OpenViduRole.valueOf(json.get("role").getAsString()) + : null; + + // IPCAM + String rtspUri = (json.has("rtspUri") && !json.get("rtspUri").isJsonNull()) ? json.get("rtspUri").getAsString() + : null; + Boolean adaptativeBitrate = (json.has("adaptativeBitrate") && !json.get("adaptativeBitrate").isJsonNull()) + ? json.get("adaptativeBitrate").getAsBoolean() + : null; + Boolean onlyPlayWithSubscribers = (json.has("onlyPlayWithSubscribers") + && !json.get("onlyPlayWithSubscribers").isJsonNull()) + ? json.get("onlyPlayWithSubscribers").getAsBoolean() + : null; + Integer networkCache = (json.has("networkCache") && !json.get("networkCache").isJsonNull()) + ? json.get("networkCache").getAsInt() + : null; + this.connectionOptions = new ConnectionOptions(type, data, record, role, null, rtspUri, adaptativeBitrate, + onlyPlayWithSubscribers, networkCache); return this; } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java index 45b32efb..8fbaea86 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java @@ -1,15 +1,26 @@ package io.openvidu.java.client; -import com.google.gson.JsonArray; import com.google.gson.JsonNull; import com.google.gson.JsonObject; +/** + * See + * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)} + */ public class ConnectionOptions { - private OpenViduRole role; + private ConnectionType type; + // COMMON private String data; private Boolean record; + // WEBRTC + private OpenViduRole role; private KurentoOptions kurentoOptions; + // IPCAM + private String rtspUri; + private Boolean adaptativeBitrate; + private Boolean onlyPlayWithSubscribers; + private Integer networkCache; /** * @@ -18,23 +29,58 @@ public class ConnectionOptions { */ public static class Builder { - private OpenViduRole role = OpenViduRole.PUBLISHER; + private ConnectionType type; + // COMMON private String data; - private Boolean record = true; + private Boolean record; + // WEBRTC + private OpenViduRole role; private KurentoOptions kurentoOptions; + // IPCAM + private String rtspUri; + private Boolean adaptativeBitrate; + private Boolean onlyPlayWithSubscribers; + private Integer networkCache; /** * Builder for {@link io.openvidu.java.client.ConnectionOptions}. */ public ConnectionOptions build() { - return new ConnectionOptions(this.role, this.data, this.record, this.kurentoOptions); + return new ConnectionOptions(this.type, this.data, this.record, this.role, this.kurentoOptions, + this.rtspUri, this.adaptativeBitrate, this.onlyPlayWithSubscribers, this.networkCache); } /** - * Call this method to set the role assigned to this Connection. + * Call this method to set the type of Connection. The + * {@link io.openvidu.java.client.ConnectionType} dictates what properties will + * have effect: + *
      + *
    • {@link io.openvidu.java.client.ConnectionType#WEBRTC}: + * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) + * record}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole) + * role}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#kurentoOptions(KurentoOptions) + * kurentoOptions}
    • + *
    • {@link io.openvidu.java.client.ConnectionType#IPCAM}: + * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) + * record}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#rtspUri(String) + * rtspUri}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#adaptativeBitrate(boolean) + * adaptativeBitrate}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#onlyPlayWithSubscribers(boolean) + * onlyPlayWithSubscribers}, + * {@link io.openvidu.java.client.ConnectionOptions.Builder#networkCache(int) + * networkCache}
    • + *
    + * If not set by default will be @link + * io.openvidu.java.client.ConnectionType#WEBRTC}. */ - public Builder role(OpenViduRole role) { - this.role = role; + public Builder type(ConnectionType type) { + this.type = type; return this; } @@ -76,29 +122,122 @@ public class ConnectionOptions { return this; } + /** + * Call this method to set the role assigned to this Connection. If not set by + * default will be {@link io.openvidu.java.client.OpenViduRole#PUBLISHER + * PUBLISHER}. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#WEBRTC} + */ + public Builder role(OpenViduRole role) { + this.role = role; + return this; + } + /** * Call this method to set a {@link io.openvidu.java.client.KurentoOptions} * object for this Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#WEBRTC} */ public Builder kurentoOptions(KurentoOptions kurentoOptions) { this.kurentoOptions = kurentoOptions; return this; } + /** + * Call this method to set the RTSP URI of an IP camera. For example: + * rtsp://your.camera.ip:7777/path + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Builder rtspUri(String rtspUri) { + this.rtspUri = rtspUri; + return this; + } + + /** + * Call this method to set whether to use adaptative bitrate (and therefore + * adaptative quality) or not. For local network connections that do not require + * media transcoding this can be disabled to save CPU power. If you are not sure + * if transcoding might be necessary, setting this property to false may + * result in media connections not being established. Default to + * true. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Builder adaptativeBitrate(boolean adaptativeBitrate) { + this.adaptativeBitrate = adaptativeBitrate; + return this; + } + + /** + * Call this method to set whether to enable the IP camera stream only when some + * user is subscribed to it, or not. This allows you to reduce power consumption + * and network bandwidth in your server while nobody is asking to receive the + * camera's video. On the counterpart, first user subscribing to the IP camera + * stream will take a little longer to receive its video. Default to + * true. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Builder onlyPlayWithSubscribers(boolean onlyPlayWithSubscribers) { + this.onlyPlayWithSubscribers = onlyPlayWithSubscribers; + return this; + } + + /** + * Call this method to set the size of the buffer of the endpoint receiving the + * IP camera's stream, in milliseconds. The smaller it is, the less delay the + * signal will have, but more problematic will be in unstable networks. Use + * short buffers only if there is a quality connection between the IP camera and + * OpenVidu Server. Default to 2000. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Builder networkCache(int networkCache) { + this.networkCache = networkCache; + return this; + } } - ConnectionOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) { - this.role = role; + ConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role, + KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers, + Integer networkCache) { + this.type = type; this.data = data; this.record = record; + this.role = role; this.kurentoOptions = kurentoOptions; + this.rtspUri = rtspUri; + this.adaptativeBitrate = adaptativeBitrate; + this.onlyPlayWithSubscribers = onlyPlayWithSubscribers; + this.networkCache = networkCache; } /** - * Returns the role assigned to this Connection. + * Returns the type of Connection. */ - public OpenViduRole getRole() { - return this.role; + public ConnectionType getType() { + return this.type; } /** @@ -118,13 +257,97 @@ public class ConnectionOptions { return this.record; } - protected JsonObject toJsonObject(String sessionId) { + /** + * Returns the role assigned to this Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#WEBRTC} + */ + public OpenViduRole getRole() { + return this.role; + } + + /** + * Returns the KurentoOptions assigned to this Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#WEBRTC} + */ + public KurentoOptions getKurentoOptions() { + return this.kurentoOptions; + } + + /** + * Returns the RTSP URI of this Connection. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public String getRtspUri() { + return this.rtspUri; + } + + /** + * Whether this Connection uses adaptative bitrate (and therefore adaptative + * quality) or not. For local network connections that do not require media + * transcoding this can be disabled to save CPU power. If you are not sure if + * transcoding might be necessary, setting this property to false may + * result in media connections not being established. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Boolean adaptativeBitrate() { + return this.adaptativeBitrate; + } + + /** + * Whether to enable the IP camera stream only when some user is subscribed to + * it. This allows you to reduce power consumption and network bandwidth in your + * server while nobody is asking to receive the camera's video. On the + * counterpart, first user subscribing to the IP camera stream will take a + * little longer to receive its video. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Boolean onlyPlayWithSubscribers() { + return this.onlyPlayWithSubscribers; + } + + /** + * Size of the buffer of the endpoint receiving the IP camera's stream, in + * milliseconds. The smaller it is, the less delay the signal will have, but + * more problematic will be in unstable networks. Use short buffers only if + * there is a quality connection between the IP camera and OpenVidu Server. + * + *
    + *
    + * Only for + * {@link io.openvidu.java.client.ConnectionType#IPCAM} + */ + public Integer getNetworkCache() { + return this.networkCache; + } + + public JsonObject toJson(String sessionId) { JsonObject json = new JsonObject(); json.addProperty("session", sessionId); - if (getRole() != null) { - json.addProperty("role", getRole().name()); + // COMMON + if (getType() != null) { + json.addProperty("type", getType().name()); } else { - json.add("role", JsonNull.INSTANCE); + json.add("type", JsonNull.INSTANCE); } if (getData() != null) { json.addProperty("data", getData()); @@ -136,28 +359,37 @@ public class ConnectionOptions { } else { json.add("record", JsonNull.INSTANCE); } + // WEBRTC + if (getRole() != null) { + json.addProperty("role", getRole().name()); + } else { + json.add("role", JsonNull.INSTANCE); + } if (this.kurentoOptions != null) { - JsonObject kurentoOptions = new JsonObject(); - if (this.kurentoOptions.getVideoMaxRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMaxRecvBandwidth", this.kurentoOptions.getVideoMaxRecvBandwidth()); - } - if (this.kurentoOptions.getVideoMinRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMinRecvBandwidth", this.kurentoOptions.getVideoMinRecvBandwidth()); - } - if (this.kurentoOptions.getVideoMaxSendBandwidth() != null) { - kurentoOptions.addProperty("videoMaxSendBandwidth", this.kurentoOptions.getVideoMaxSendBandwidth()); - } - if (this.kurentoOptions.getVideoMinSendBandwidth() != null) { - kurentoOptions.addProperty("videoMinSendBandwidth", this.kurentoOptions.getVideoMinSendBandwidth()); - } - if (this.kurentoOptions.getAllowedFilters().length > 0) { - JsonArray allowedFilters = new JsonArray(); - for (String filter : this.kurentoOptions.getAllowedFilters()) { - allowedFilters.add(filter); - } - kurentoOptions.add("allowedFilters", allowedFilters); - } - json.add("kurentoOptions", kurentoOptions); + json.add("kurentoOptions", kurentoOptions.toJson()); + } else { + json.add("kurentoOptions", JsonNull.INSTANCE); + } + // IPCAM + if (getRtspUri() != null) { + json.addProperty("rtspUri", getRtspUri()); + } else { + json.add("rtspUri", JsonNull.INSTANCE); + } + if (adaptativeBitrate() != null) { + json.addProperty("adaptativeBitrate", adaptativeBitrate()); + } else { + json.add("adaptativeBitrate", JsonNull.INSTANCE); + } + if (onlyPlayWithSubscribers() != null) { + json.addProperty("onlyPlayWithSubscribers", onlyPlayWithSubscribers()); + } else { + json.add("onlyPlayWithSubscribers", JsonNull.INSTANCE); + } + if (getNetworkCache() != null) { + json.addProperty("networkCache", getNetworkCache()); + } else { + json.add("networkCache", JsonNull.INSTANCE); } return json; } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/KurentoOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/KurentoOptions.java index c29730ac..0f5f5fa3 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/KurentoOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/KurentoOptions.java @@ -17,6 +17,11 @@ package io.openvidu.java.client; +import java.util.Arrays; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + /** * See {@link io.openvidu.java.client.TokenOptions#getKurentoOptions()} */ @@ -105,10 +110,10 @@ public class KurentoOptions { } /** - * Defines the maximum number of Kbps that the client owning the token will be - * able to receive from Kurento Media Server. 0 means unconstrained. Giving a - * value to this property will override the global configuration set in OpenVidu Server configuration (parameter * OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH) for every incoming * stream of the user owning the token.
    @@ -122,10 +127,10 @@ public class KurentoOptions { } /** - * Defines the minimum number of Kbps that the client owning the token will try - * to receive from Kurento Media Server. 0 means unconstrained. Giving a value - * to this property will override the global configuration set in OpenVidu Server configuration (parameter * OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH) for every incoming * stream of the user owning the token. @@ -135,10 +140,10 @@ public class KurentoOptions { } /** - * Defines the maximum number of Kbps that the client owning the token will be - * able to send to Kurento Media Server. 0 means unconstrained. Giving a value - * to this property will override the global configuration set in OpenVidu Server configuration (parameter * OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH) for every outgoing * stream of the user owning the token.
    @@ -151,10 +156,10 @@ public class KurentoOptions { } /** - * Defines the minimum number of Kbps that the client owning the token will try - * to send to Kurento Media Server. 0 means unconstrained. Giving a value to - * this property will override the global configuration set in OpenVidu Server configuration (parameter * OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH) for every outgoing * stream of the user owning the token. @@ -164,13 +169,50 @@ public class KurentoOptions { } /** - * Defines the names of the filters the user owning the token will be able to - * apply. See - * Voice and - * video filters + * Defines the names of the filters the Connection will be able to apply to its + * published streams. See + * Voice and video filters. */ public String[] getAllowedFilters() { return allowedFilters; } + /** + * See if the Connection can apply certain filter. See + * Voice and video filters. + */ + public boolean isFilterAllowed(String filterType) { + if (filterType == null) { + return false; + } + return Arrays.stream(allowedFilters).anyMatch(filterType::equals); + } + + public JsonObject toJson() { + JsonObject json = new JsonObject(); + if (this.getVideoMaxRecvBandwidth() != null) { + json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth()); + } + if (this.getVideoMinRecvBandwidth() != null) { + json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth()); + } + if (this.getVideoMaxSendBandwidth() != null) { + json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth()); + } + if (this.getVideoMinSendBandwidth() != null) { + json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth()); + } + if (this.getAllowedFilters().length > 0) { + JsonArray filtersJson = new JsonArray(); + String[] filters = this.getAllowedFilters(); + for (String filter : filters) { + filtersJson.add(filter); + } + json.add("allowedFilters", filtersJson); + } + return json; + } + } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 0e1a660f..d657dbec 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -497,6 +497,10 @@ public class OpenVidu { * since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()} * was called
    . Exceptions to this rule are: *
      + *
    • Calling + * {@link io.openvidu.java.client.OpenVidu#createSession(SessionProperties) + * OpenVidu.createSession} automatically adds the new Session object to the + * local collection.
    • *
    • Calling {@link io.openvidu.java.client.Session#fetch()} updates that * specific Session status
    • *
    • Calling {@link io.openvidu.java.client.Session#close()} automatically diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index e1ef12b4..9c54f6a7 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -89,8 +89,9 @@ public class Session { } /** - * @deprecated Use {@link Session#createToken() Session.createToken()} instead - * to get a {@link io.openvidu.java.client.Token} object. + * @deprecated Use {@link Session#createConnection() Session.createConnection()} + * instead to get a {@link io.openvidu.java.client.Connection} + * object. * * @return The generated token String * @@ -99,14 +100,14 @@ public class Session { */ @Deprecated public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException { - return createToken().getToken(); + return generateToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); } /** * @deprecated Use - * {@link Session#createToken(io.openvidu.java.client.TokenOptions) - * Session.createToken(TokenOptions)} instead to get a - * {@link io.openvidu.java.client.Token} object. + * {@link Session#createConnection(io.openvidu.java.client.ConnectionOptions) + * Session.createConnection(ConnectionOptions)} instead to get a + * {@link io.openvidu.java.client.Connection} object. * * @return The generated token String * @@ -115,70 +116,6 @@ public class Session { */ @Deprecated public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException { - return createToken(tokenOptions).getToken(); - } - - /** - * Gets a new token object associated to Session object with default values for - * {@link io.openvidu.java.client.TokenOptions}. The token string value to send - * to the client side can be retrieved with - * {@link io.openvidu.java.client.Token#getToken() Token.getToken()}.
      - *
      - * You can use method {@link io.openvidu.java.client.Token#getConnectionId() - * Token.getConnectionId()} to get the connection identifier that will be given - * to the user consuming the token. With connectionId you can call - * the following methods without having to fetch and search for the actual - * {@link io.openvidu.java.client.Connection Connection} object: - *
        - *
      • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) - * Session.forceDisconnect()} to invalidate the token if no client has used it - * yet or force the connected client to leave the session if it has.
      • - *
      • Call - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) - * Session.updateConnection()} to update the - * {@link io.openvidu.java.client.Connection Connection} options. And this is - * valid for unused tokens, but also for already used tokens, so you can - * dynamically change the connection options on the fly.
      • - *
      - * - * @return The generated {@link io.openvidu.java.client.Token Token} object. - * - * @throws OpenViduJavaClientException - * @throws OpenViduHttpException - */ - public Token createToken() throws OpenViduJavaClientException, OpenViduHttpException { - return createToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); - } - - /** - * Gets a new token object associated to Session object configured with - * tokenOptions. The token string value to send to the client side - * can be retrieved with {@link io.openvidu.java.client.Token#getToken() - * Token.getToken()}.
      - *
      - * You can use method {@link io.openvidu.java.client.Token#getConnectionId() - * Token.getConnectionId()} to get the connection identifier that will be given - * to the user consuming the token. With connectionId you can call - * the following methods without having to fetch and search for the actual - * {@link io.openvidu.java.client.Connection Connection} object: - *
        - *
      • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) - * Session.forceDisconnect()} to invalidate the token if no client has used it - * yet or force the connected client to leave the session if it has.
      • - *
      • Call - * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions) - * Session.updateConnection()} to update the - * {@link io.openvidu.java.client.Connection Connection} options. And this is - * valid for unused tokens, but also for already used tokens, so you can - * dynamically change the user connection options on the fly.
      • - *
      - * - * @return The generated {@link io.openvidu.java.client.Token Token} object. - * - * @throws OpenViduJavaClientException - * @throws OpenViduHttpException - */ - public Token createToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException { if (!this.hasSessionId()) { this.getSessionId(); } @@ -205,8 +142,8 @@ public class Session { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { - Token token = new Token(httpResponseToJson(response)); - log.info("Returning a TOKEN: {}", token.getToken()); + String token = httpResponseToJson(response).get("id").getAsString(); + log.info("Returning a TOKEN: {}", token); return token; } else { throw new OpenViduHttpException(statusCode); @@ -216,6 +153,75 @@ public class Session { } } + /** + * Same as + * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) + * but with default ConnectionOptions values. + * + * @return The generated {@link io.openvidu.java.client.Connection Connection} + * object. + * + * @throws OpenViduJavaClientException + * @throws OpenViduHttpException + */ + public Connection createConnection() throws OpenViduJavaClientException, OpenViduHttpException { + return createConnection( + new ConnectionOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); + } + + /** + * Creates a new Connection object associated to Session object and configured + * with connectionOptions. Each user connecting to the Session + * requires a Connection. The token string value to send to the client side can + * be retrieved with {@link io.openvidu.java.client.Connection#getToken() + * Connection.getToken()}. + * + * @return The generated {@link io.openvidu.java.client.Connection Connection} + * object. + * + * @throws OpenViduJavaClientException + * @throws OpenViduHttpException + */ + public Connection createConnection(ConnectionOptions connectionOptions) + throws OpenViduJavaClientException, OpenViduHttpException { + if (!this.hasSessionId()) { + this.getSessionId(); + } + + HttpPost request = new HttpPost( + this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection"); + + StringEntity params; + try { + params = new StringEntity(connectionOptions.toJson(sessionId).toString()); + } catch (UnsupportedEncodingException e1) { + throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); + } + + request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + request.setEntity(params); + + HttpResponse response; + try { + response = this.openVidu.httpClient.execute(request); + } catch (IOException e2) { + throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause()); + } + + try { + int statusCode = response.getStatusLine().getStatusCode(); + if ((statusCode == org.apache.http.HttpStatus.SC_OK)) { + Connection connection = new Connection(httpResponseToJson(response)); + this.connections.put(connection.getConnectionId(), connection); + return connection; + } else { + throw new OpenViduHttpException(statusCode); + } + } finally { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + /** * Gracefully closes the Session: unpublishes all streams and evicts every * participant. @@ -298,24 +304,31 @@ public class Session { } /** - * Forces the user represented by connection to leave the session. - * OpenVidu Browser will trigger the proper events on the client-side - * (streamDestroyed, connectionDestroyed, + * Removes the Connection from the Session. This can translate into a forced + * eviction of a user from the Session if the Connection had status + * active, or into a token invalidation if no user had taken the + * Connection yet (status pending).
      + *
      + * + * In the first case, OpenVidu Browser will trigger the proper events on the + * client-side (streamDestroyed, connectionDestroyed, * sessionDisconnected) with reason set to * "forceDisconnectByServer".
      *
      * - * You can get connection parameter with - * {@link io.openvidu.java.client.Session#fetch()} and then - * {@link io.openvidu.java.client.Session#getActiveConnections()}.
      + * In the second case, the token of the Connection will be invalidated and no + * user will be able to connect to the session with it.
      *
      * * This method automatically updates the properties of the local affected * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the * changes consequence of the execution of this method applied in the local * objects. * + * @param connection The Connection to remove + * * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ @@ -324,35 +337,12 @@ public class Session { } /** - * Forces the user with Connection connectionId to leave the - * session, or invalidates the {@link Token} associated with that - * connectionId if no user has used it yet.
      - *
      + * Same as {@link io.openvidu.java.client.Session#forceDisconnect(Connection) + * forceDisconnect(ConnectionOptions)} but providing the + * {@link io.openvidu.java.client.Connection#getConnectionId() connectionId} + * instead of the Connection object. * - * In the first case you can get connectionId parameter from - * {@link io.openvidu.java.client.Connection#getConnectionId() - * Connection.getConnectionId()}. Connection objects can be listed with - * {@link io.openvidu.java.client.Session#getActiveConnections() - * Session.getActiveConnections()} (remember to use first - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to fetch the - * current active connections from OpenVidu Server). As a result, OpenVidu - * Browser will trigger the proper events on the client-side - * (streamDestroyed, connectionDestroyed, - * sessionDisconnected) with reason set to - * "forceDisconnectByServer".
      - *
      - * - * In the second case you can get connectionId parameter from a - * {@link Token} with {@link Token#getConnectionId()}. As a result, the token - * will be invalidated and no user will be able to connect to the session with - * it.
      - *
      - * - * This method automatically updates the properties of the local affected - * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the - * changes consequence of the execution of this method applied in the local - * objects. + * @param connectionId The identifier of the Connection object to remove * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -400,9 +390,9 @@ public class Session { } /** - * Forces some user to unpublish a Stream. OpenVidu Browser will trigger the - * proper events on the client-side (streamDestroyed) with reason - * set to "forceUnpublishByServer".
      + * Forces some Connection to unpublish a Stream. OpenVidu Browser will trigger + * the proper events in the client-side (streamDestroyed) with + * reason set to "forceUnpublishByServer".
      *
      * * You can get publisher parameter with @@ -415,10 +405,13 @@ public class Session { * * This method automatically updates the properties of the local affected * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the * changes consequence of the execution of this method applied in the local * objects. * + * @param publisher The Publisher object to unpublish + * * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ @@ -427,26 +420,12 @@ public class Session { } /** - * Forces some user to unpublish a Stream. OpenVidu Browser will trigger the - * proper events on the client-side (streamDestroyed) with reason - * set to "forceUnpublishByServer".
      - *
      + * Same as {@link io.openvidu.java.client.Session#forceUnpublish(Publisher) + * forceUnpublish(Publisher)} but providing the + * {@link io.openvidu.java.client.Publisher#getStreamId() streamId} instead of + * the Publisher object. * - * You can get streamId parameter with - * {@link io.openvidu.java.client.Session#getActiveConnections()} and then for - * each Connection you can call - * {@link io.openvidu.java.client.Connection#getPublishers()}. Finally - * {@link io.openvidu.java.client.Publisher#getStreamId()}) will give you the - * streamId. Remember to call - * {@link io.openvidu.java.client.Session#fetch()} before to fetch the current - * actual properties of the Session from OpenVidu Server.
      - *
      - * - * This method automatically updates the properties of the local affected - * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the - * changes consequence of the execution of this method applied in the local - * objects. + * @param streamId The identifier of the Publisher object to remove * * @throws OpenViduJavaClientException * @throws OpenViduHttpException @@ -520,7 +499,7 @@ public class Session { StringEntity params; try { - params = new StringEntity(connectionOptions.toJsonObject(this.sessionId).toString()); + params = new StringEntity(connectionOptions.toJson(this.sessionId).toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } @@ -570,6 +549,11 @@ public class Session { * actual value you must call first * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + * + * @param id The Connection to get + * + * @return The {@link io.openvidu.java.client.Connection Connection} object, or + * null if no Connection is found for param id */ public Connection getConnection(String id) { return this.connections.get(id); @@ -581,6 +565,29 @@ public class Session { * current actual value you must call first * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + * + * The list of Connections will remain unchanged since the last time + * method {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was + * called. Exceptions to this rule are: + *
        + *
      • Calling + * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) + * createConnection(ConnectionOptions)} automatically adds the new Connection + * object to the local collection.
      • + *
      • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} + * automatically updates each affected local Connection object.
      • + *
      • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} + * automatically updates each affected local Connection object.
      • + *
      • Calling + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)} + * automatically updates the attributes of the affected local Connection + * object.
      • + *
      + *
      + * To get the list of connections with their current actual value, you must call + * first {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. */ public List getConnections() { return this.connections.values().stream().collect(Collectors.toList()); @@ -596,6 +603,10 @@ public class Session { * or {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was * called. Exceptions to this rule are: *
        + *
      • Calling + * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) + * createConnection(ConnectionOptions)} automatically adds the new Connection + * object to the local collection.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} * automatically updates each affected local Connection object.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} @@ -609,7 +620,7 @@ public class Session { * To get the list of active connections with their current actual value, you * must call first {@link io.openvidu.java.client.Session#fetch() * Session.fetch()} or {@link io.openvidu.java.client.OpenVidu#fetch() - * OpenVidu.fetch()}. + * OpenVidu.fetch()} OpenVidu.fetch()}. */ public List getActiveConnections() { return this.connections.values().stream().filter(con -> "active".equals(con.getStatus())) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java deleted file mode 100644 index b629d323..00000000 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Token.java +++ /dev/null @@ -1,127 +0,0 @@ -package io.openvidu.java.client; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -public class Token { - - private String token; - private String connectionId; - private TokenOptions tokenOptions; - - protected Token(String token, String connectionId, TokenOptions tokenOptions) { - this.token = token; - this.connectionId = connectionId; - this.tokenOptions = tokenOptions; - } - - protected Token(JsonObject json) { - - this.token = json.get("token").getAsString(); - this.connectionId = json.get("connectionId").getAsString(); - - OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString()); - String data = json.get("data").getAsString(); - Boolean record = json.get("record").getAsBoolean(); - - KurentoOptions kurentoOptions = null; - if (json.has("kurentoOptions")) { - JsonObject kurentoOptionsJson = json.get("kurentoOptions").getAsJsonObject(); - - Integer videoMaxRecvBandwidth = null; - Integer videoMinRecvBandwidth = null; - Integer videoMaxSendBandwidth = null; - Integer videoMinSendBandwidth = null; - String[] allowedFilters = null; - - if (kurentoOptionsJson.has("videoMaxRecvBandwidth")) { - videoMaxRecvBandwidth = kurentoOptionsJson.get("videoMaxRecvBandwidth").getAsInt(); - } - if (kurentoOptionsJson.has("videoMinRecvBandwidth")) { - videoMinRecvBandwidth = kurentoOptionsJson.get("videoMinRecvBandwidth").getAsInt(); - } - if (kurentoOptionsJson.has("videoMaxSendBandwidth")) { - videoMaxSendBandwidth = kurentoOptionsJson.get("videoMaxSendBandwidth").getAsInt(); - } - if (kurentoOptionsJson.has("videoMinSendBandwidth")) { - videoMinSendBandwidth = kurentoOptionsJson.get("videoMinSendBandwidth").getAsInt(); - } - if (kurentoOptionsJson.has("allowedFilters")) { - JsonArray filters = kurentoOptionsJson.get("allowedFilters").getAsJsonArray(); - allowedFilters = new String[filters.size()]; - for (int i = 0; i < filters.size(); i++) { - allowedFilters[i] = filters.get(i).getAsString(); - } - } - kurentoOptions = new KurentoOptions(videoMaxRecvBandwidth, videoMinRecvBandwidth, videoMaxSendBandwidth, - videoMinSendBandwidth, allowedFilters); - } - - this.tokenOptions = new TokenOptions(role, data, record, kurentoOptions); - } - - /** - * Returns the token string value that must be sent to clients. They need to use - * it to connect to the session. - */ - public String getToken() { - return this.token; - } - - /** - * Returns the connection identifier that will be associated to the user - * consuming this token. This means that the future - * {@link io.openvidu.java.client.Connection Connection} object created with - * this token will have as connectionId this string. In other - * words, method {@link io.openvidu.java.client.Connection#getConnectionId() - * Connection.getConnectionId()} will return this same value. - * - * With connectionId you can call the following methods without - * having to fetch and search for the actual - * {@link io.openvidu.java.client.Connection Connection} object: - *
          - *
        • Call {@link io.openvidu.java.client.Session#forceDisconnect(String) - * Session.forceDisconnect()} to invalidate the token if no client has used it - * yet or force the connected client to leave the session if it has.
        • - *
        • Call - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) - * Session.updateConnection()} to update the - * {@link io.openvidu.java.client.Connection Connection} options. And this is - * valid for unused tokens, but also for already used tokens, so you can - * dynamically change the connection options on the fly.
        • - *
        - * - */ - public String getConnectionId() { - return this.connectionId; - } - - /** - * Returns the role assigned to this token. - */ - public OpenViduRole getRole() { - return this.tokenOptions.getRole(); - } - - /** - * Returns the secure (server-side) metadata assigned to this token. - */ - public String getData() { - return this.tokenOptions.getData(); - } - - /** - * Whether the streams published by the participant owning this token will be - * recorded or not. This only affects INDIVIDUAL recording. - */ - public Boolean record() { - return this.tokenOptions.record(); - } - - protected void overrideTokenOptions(TokenOptions tokenOptions) { - this.tokenOptions = tokenOptions; - } - -} diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java index f9338064..f450399b 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java @@ -17,12 +17,12 @@ package io.openvidu.java.client; -import com.google.gson.JsonArray; import com.google.gson.JsonNull; import com.google.gson.JsonObject; /** - * See {@link io.openvidu.java.client.Session#generateToken(TokenOptions)} + * @deprecated Use {@link io.openvidu.java.client.ConnectionOptions + * ConnectionOptions} instead */ public class TokenOptions { @@ -32,9 +32,8 @@ public class TokenOptions { private KurentoOptions kurentoOptions; /** - * - * Builder for {@link io.openvidu.java.client.TokenOptions} - * + * @deprecated Use {@link io.openvidu.java.client.ConnectionOptions.Builder + * ConnectionOptions.Builder} instead */ public static class Builder { @@ -157,27 +156,7 @@ public class TokenOptions { json.add("record", JsonNull.INSTANCE); } if (this.kurentoOptions != null) { - JsonObject kurentoOptions = new JsonObject(); - if (this.kurentoOptions.getVideoMaxRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMaxRecvBandwidth", this.kurentoOptions.getVideoMaxRecvBandwidth()); - } - if (this.kurentoOptions.getVideoMinRecvBandwidth() != null) { - kurentoOptions.addProperty("videoMinRecvBandwidth", this.kurentoOptions.getVideoMinRecvBandwidth()); - } - if (this.kurentoOptions.getVideoMaxSendBandwidth() != null) { - kurentoOptions.addProperty("videoMaxSendBandwidth", this.kurentoOptions.getVideoMaxSendBandwidth()); - } - if (this.kurentoOptions.getVideoMinSendBandwidth() != null) { - kurentoOptions.addProperty("videoMinSendBandwidth", this.kurentoOptions.getVideoMinSendBandwidth()); - } - if (this.kurentoOptions.getAllowedFilters().length > 0) { - JsonArray allowedFilters = new JsonArray(); - for (String filter : this.kurentoOptions.getAllowedFilters()) { - allowedFilters.add(filter); - } - kurentoOptions.add("allowedFilters", allowedFilters); - } - json.add("kurentoOptions", kurentoOptions); + json.add("kurentoOptions", kurentoOptions.toJson()); } return json; } diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 0f724f71..44be496b 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -15,9 +15,9 @@ * */ -import { OpenViduRole } from './OpenViduRole'; import { Publisher } from './Publisher'; import { ConnectionOptions } from './ConnectionOptions'; +import { OpenViduRole } from 'OpenViduRole'; /** * See [[Session.connections]] @@ -25,13 +25,13 @@ import { ConnectionOptions } from './ConnectionOptions'; export class Connection { /** - * Identifier of the connection. You can call methods [[Session.forceDisconnect]] + * Identifier of the Connection. You can call methods [[Session.forceDisconnect]] * or [[Session.updateConnection]] passing this property as parameter */ connectionId: string; /** - * Returns the status of the connection. Can be: + * Returns the status of the Connection. Can be: * - `pending`: if the Connection is waiting for any user to use * its internal token to connect to the session, calling method * [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect) @@ -43,39 +43,19 @@ export class Connection { status: string; /** - * Timestamp when this connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) + * Timestamp when the Connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) */ createdAt: number; /** - * Timestamp when this connection was taken by a user (passing from status "pending" to "active") + * Timestamp when the Connection was taken by a user (passing from status "pending" to "active") * in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC) */ activeAt: number; - /** - * Role of the connection - */ - role: OpenViduRole; - - /** - * Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]] - */ - serverData: string; - - /** - * Whether to record the streams published by the participant owning this token or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) - */ - record: boolean; - - /** - * Token associated to the connection - */ - token: string; - /** * PRO - * Geo location of the connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it) + * Geo location of the Connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it) */ location: string; @@ -85,11 +65,21 @@ export class Connection { platform: string; /** - * Data associated to the connection on the client-side. This value is set with second parameter of method + * Data associated to the Connection on the client-side. This value is set with second parameter of method * [Session.connect](/en/stable/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser */ clientData: string; + /** + * The [[ConnectionOptions]] assigned to the Connection + */ + connectionOptions: ConnectionOptions; + + /** + * Token associated to the Connection + */ + token: string; + /** * Array of Publisher objects this particular Connection is publishing to the Session (each Publisher object has one Stream, uniquely * identified by its `streamId`). You can call [[Session.forceUnpublish]] passing any of this values as parameter @@ -102,6 +92,15 @@ export class Connection { */ subscribers: string[] = []; + /** + * @hidden deprecated. Inside ConnectionOptions + */ + role?: OpenViduRole; + /** + * @hidden deprecated. Inside ConnectionOptions + */ + serverData?: string; + /** * @hidden */ @@ -114,15 +113,41 @@ export class Connection { */ resetWithJson(json): Connection { - // These properties won't ever be null this.connectionId = json.connectionId; this.status = json.status; + this.createdAt = json.createdAt; + this.activeAt = json.activeAt; + this.location = json.location; + this.platform = json.platform; + this.clientData = json.clientData; this.token = json.token; + if (this.connectionOptions != null) { + this.connectionOptions.type = json.type; + this.connectionOptions.data = json.data; + this.connectionOptions.record = json.record; + this.connectionOptions.role = json.role; + this.connectionOptions.kurentoOptions = json.kurentoOptions; + this.connectionOptions.rtspUri = json.rtspUri; + this.connectionOptions.adaptativeBitrate = json.adaptativeBitrate; + this.connectionOptions.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers; + this.connectionOptions.networkCache = json.networkCache; + } else { + this.connectionOptions = { + type: json.type, + data: json.data, + record: json.record, + role: json.role, + kurentoOptions: json.kurentoOptions, + rtspUri: json.rtspUri, + adaptativeBitrate: json.adaptativeBitrate, + onlyPlayWithSubscribers: json.onlyPlayWithSubscribers, + networkCache: json.networkCache + } + } this.role = json.role; - this.serverData = json.serverData; - this.record = json.record; + this.serverData = json.data; - // These properties may be null + // publishers may be null if (json.publishers != null) { // 1. Array to store fetched Publishers and later remove closed ones @@ -151,6 +176,7 @@ export class Connection { } + // subscribers may be null if (json.subscribers != null) { // 1. Array to store fetched Subscribers and later remove closed ones @@ -171,12 +197,6 @@ export class Connection { } } - this.createdAt = json.createdAt; - this.activeAt = json.activeAt; - this.location = json.location; - this.platform = json.platform; - this.clientData = json.clientData; - return this; } @@ -189,9 +209,15 @@ export class Connection { this.status === other.status && this.createdAt === other.createdAt && this.activeAt === other.activeAt && - this.role === other.role && - this.serverData === other.serverData && - this.record === other.record && + this.connectionOptions.type === other.connectionOptions.type && + this.connectionOptions.data === other.connectionOptions.data && + this.connectionOptions.record === other.connectionOptions.record && + this.connectionOptions.role === other.connectionOptions.role && + this.connectionOptions.kurentoOptions === other.connectionOptions.kurentoOptions && + this.connectionOptions.rtspUri === other.connectionOptions.rtspUri && + this.connectionOptions.adaptativeBitrate === other.connectionOptions.adaptativeBitrate && + this.connectionOptions.onlyPlayWithSubscribers === other.connectionOptions.onlyPlayWithSubscribers && + this.connectionOptions.networkCache === other.connectionOptions.networkCache && this.token === other.token && this.location === other.location && this.platform === other.platform && @@ -218,12 +244,13 @@ export class Connection { /** * @hidden */ - overrideConnectionOptions(connectionOptions: ConnectionOptions): void { - if (connectionOptions.role != null) { - this.role = connectionOptions.role; + overrideConnectionOptions(newConnectionOptions: ConnectionOptions): void { + // For now only properties record and role + if (newConnectionOptions.record != null) { + this.connectionOptions.record = newConnectionOptions.record; } - if (connectionOptions.record != null) { - this.record = connectionOptions.record + if (newConnectionOptions.role != null) { + this.connectionOptions.role = newConnectionOptions.role; } } diff --git a/openvidu-node-client/src/ConnectionOptions.ts b/openvidu-node-client/src/ConnectionOptions.ts index bd10bbaf..222bc2ec 100644 --- a/openvidu-node-client/src/ConnectionOptions.ts +++ b/openvidu-node-client/src/ConnectionOptions.ts @@ -15,16 +15,20 @@ * */ +import { ConnectionType } from 'ConnectionType'; import { OpenViduRole } from './OpenViduRole'; export interface ConnectionOptions { /** - * The role assigned to this Connection + * Type of Connection. The [[ConnectionType]] dictates what properties will have effect: * - * @default PUBLISHER + * - **[[ConnectionType.WEBRTC]]**: [[data]], [[record]], [[role]], [[kurentoOptions]] + * - **[[ConnectionType.IPCAM]]**: [[data]], [[record]], [[rtspUri]], [[adaptativeBitrate]], [[onlyPlayWithSubscribers]], [[networkCache]] + * + * @default WEBRTC */ - role?: OpenViduRole; + type?: ConnectionType; /** * Secure (server-side) data associated to this Connection. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object. @@ -41,6 +45,15 @@ export interface ConnectionOptions { */ record?: boolean; + /** + * The role assigned to this Connection + * + * **Only for [[ConnectionType.WEBRTC]]** + * + * @default PUBLISHER + */ + role?: OpenViduRole; + /** * **WARNING**: experimental option. This interface may change in the near future * @@ -61,6 +74,8 @@ export interface ConnectionOptions { * the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/) * (parameter `OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH`) for every outgoing stream of the Connection. * - `allowedFilters`: names of the filters the Connection will be able to apply. See [Voice and video filters](/en/stable/advanced-features/filters/) + * + * **Only for [[ConnectionType.WEBRTC]]** */ kurentoOptions?: { videoMaxRecvBandwidth?: number, @@ -69,4 +84,45 @@ export interface ConnectionOptions { videoMinSendBandwidth?: number, allowedFilters?: string[] }; + + /** + * RTSP URI of an IP camera. For example: `rtsp://your.camera.ip:7777/path` + * + * **Only for [[ConnectionType.IPCAM]]** + */ + rtspUri?: string; + + /** + * Whether to use adaptative bitrate (and therefore adaptative quality) or not. For local network connections + * that do not require media transcoding this can be disabled to save CPU power. If you are not sure if transcoding + * might be necessary, setting this property to false **may result in media connections not being established**. + * + * **Only for [[ConnectionType.IPCAM]]** + * + * @default true + */ + adaptativeBitrate?: boolean; + + /** + * Whether to enable the IP camera stream only when some user is subscribed to it, or not. This allows you to reduce + * power consumption and network bandwidth in your server while nobody is asking to receive the camera's video. + * On the counterpart, first user subscribing to the IP camera stream will take a little longer to receive its video. + * + * **Only for [[ConnectionType.IPCAM]]** + * + * @default true + */ + onlyPlayWithSubscribers?: boolean; + + /** + * Size of the buffer of the endpoint receiving the IP camera's stream, in milliseconds. The smaller it is, the less + * delay the signal will have, but more problematic will be in unstable networks. Use short buffers only if there is + * a quality connection between the IP camera and OpenVidu Server. + * + * **Only for [[ConnectionType.IPCAM]]** + * + * @default 2000 + */ + networkCache?: number; + } \ No newline at end of file diff --git a/openvidu-node-client/src/ConnectionType.ts b/openvidu-node-client/src/ConnectionType.ts new file mode 100644 index 00000000..29268f4b --- /dev/null +++ b/openvidu-node-client/src/ConnectionType.ts @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * See [[Session.createConnection]] + */ +export enum ConnectionType { + + /** + * WebRTC connection. This is the normal type of Connection for a regular user + * connecting to a session from an application. + */ + WEBRTC = 'WEBRTC', + + /** + * IP camera connection. This is the type of Connection used by IP cameras to + * connect to a session. + */ + IPCAM = 'IPCAM' +} \ No newline at end of file diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index 6979352b..b98a2ee1 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -76,6 +76,7 @@ export class OpenVidu { * Array of active sessions. **This value will remain unchanged since the last time method [[OpenVidu.fetch]] * was called**. Exceptions to this rule are: * + * - Calling [[OpenVidu.createSession]] automatically adds the new Session object to the local collection. * - Calling [[Session.fetch]] updates that specific Session status * - Calling [[Session.close]] automatically removes the Session from the list of active Sessions * - Calling [[Session.forceDisconnect]] automatically updates the inner affected connections for that specific Session diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 10711654..9cb41354 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -25,10 +25,8 @@ import { Recording } from './Recording'; import { RecordingLayout } from './RecordingLayout'; import { RecordingMode } from './RecordingMode'; import { SessionProperties } from './SessionProperties'; -import { Token } from './Token'; import { TokenOptions } from './TokenOptions'; - export class Session { /** @@ -51,6 +49,7 @@ export class Session { * **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**. * Exceptions to this rule are: * + * - Calling [[Session.createConnection]] automatically adds the new Connection object to the local collection. * - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object. * - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object. * - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object. @@ -105,37 +104,12 @@ export class Session { } /** - * @deprecated Use [[Session.createToken]] instead to get a [[Token]] object. + * @deprecated Use [[Session.createConnection]] instead to get a [[Connection]] object. * * @returns A Promise that is resolved to the generated _token_ string if success and rejected with an Error object if not */ public generateToken(tokenOptions?: TokenOptions): Promise { return new Promise((resolve, reject) => { - this.createToken(tokenOptions).then(token => resolve(token.token)).catch(error => reject(error)); - }); - } - - /** - * Gets a new token object associated to Session object configured with - * `tokenOptions`. The token string value to send to the client side - * is available at [[Token.token]] property. - * - * Property [[Token.connectionId]] provides the connection identifier that will be given - * to the user consuming the token. With `connectionId` you can call - * the following methods without having to fetch and search for the actual - * [[Connection]] object: - * - * - Call [[Session.forceDisconnect]] to invalidate the token if no client has used it - * yet or force the connected client to leave the session if it has. - * - Call [[Session.updateConnection]] to update the [[Connection]] options. And this is - * valid for unused tokens, but also for already used tokens, so you can - * dynamically change the user connection options on the fly. - * - * @returns A Promise that is resolved to the generated [[Token]] object if success and rejected with an Error object if not - */ - public createToken(tokenOptions?: TokenOptions): Promise { - return new Promise((resolve, reject) => { - const data = JSON.stringify({ session: this.sessionId, role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null, @@ -156,7 +130,51 @@ export class Session { .then(res => { if (res.status === 200) { // SUCCESS response from openvidu-server. Resolve token - resolve(new Token(res.data)); + resolve(res.data.token); + } else { + // ERROR response from openvidu-server. Resolve HTTP status + reject(new Error(res.status.toString())); + } + }).catch(error => { + this.handleError(error, reject); + }); + }); + } + + /** + * Creates a new Connection object associated to Session object and configured with + * `connectionOptions`. Each user connecting to the Session requires a Connection. + * The token string value to send to the client side is available at [[Connection.token]]. + * + * @returns A Promise that is resolved to the generated [[Connection]] object if success and rejected with an Error object if not + */ + public createConnection(connectionOptions?: ConnectionOptions): Promise { + return new Promise((resolve, reject) => { + const data = JSON.stringify({ + role: (!!connectionOptions && !!connectionOptions.role) ? connectionOptions.role : null, + data: (!!connectionOptions && !!connectionOptions.data) ? connectionOptions.data : null, + record: !!connectionOptions ? connectionOptions.record : null, + kurentoOptions: (!!connectionOptions && !!connectionOptions.kurentoOptions) ? connectionOptions.kurentoOptions : null + }); + axios.post( + this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection', + data, + { + headers: { + 'Authorization': this.ov.basicAuth, + 'Content-Type': 'application/json' + } + } + ) + .then(res => { + if (res.status === 200) { + // SUCCESS response from openvidu-server. Store and resolve Connection + const connection = new Connection(res.data); + this.connections.push(connection); + if (connection.status === 'active') { + this.activeConnections.push(connection); + } + resolve(new Connection(res.data)); } else { // ERROR response from openvidu-server. Resolve HTTP status reject(new Error(res.status.toString())); @@ -240,12 +258,18 @@ export class Session { } /** - * Removes a Connection from the Session. + * Removes the Connection from the Session. This can translate into a forced eviction of a user from the Session if the + * Connection had status `active` or into a token invalidation if no user had taken the Connection yet (status `pending`). + * + * In the first case, OpenVidu Browser will trigger the proper events in the client-side (`streamDestroyed`, `connectionDestroyed`, + * `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`. + * + * In the second case, the token of the Connection will be invalidated and no user will be able to connect to the session with it. * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]]] to see the changes consequence of the execution of this method applied in the local objects. * - * @param connection The Connection object to disconnect from the session, or its `connectionId` property + * @param connection The Connection object to remove from the session, or its `connectionId` property * * @returns A Promise that is resolved if the Connection was successfully removed from the Session and rejected with an Error object if not */ @@ -308,7 +332,7 @@ export class Session { } /** - * Forces some user to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it). + * Forces some Connection to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it). * OpenVidu Browser will trigger the proper events on the client-side (`streamDestroyed`) with reason set to `"forceUnpublishByServer"`. * * You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property). @@ -317,6 +341,8 @@ export class Session { * This method automatically updates the properties of the local affected objects. This means that there is no need to call * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * + * @param publisher The Publisher object to unpublish, or its `streamId` property + * * @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not */ public forceUnpublish(publisher: string | Publisher): Promise { diff --git a/openvidu-node-client/src/Token.ts b/openvidu-node-client/src/Token.ts deleted file mode 100644 index bd9119d1..00000000 --- a/openvidu-node-client/src/Token.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -import { TokenOptions } from './TokenOptions'; - -export class Token { - - /** - * The token string value that must be sent to clients. They need to use it to connect to the session. - */ - token: string; - - /** - * The connection identifier that will be associated to the user - * consuming this token. This means that the future [[Connection]] object created with - * this token will have as [[Connection.connectionId]] this same value. - * - * With `connectionId` you can call the following methods without - * having to fetch and search for the actual [[Connection]] object: - * - * - Call [[Session.forceDisconnect]] to invalidate the token if no client has used it - * yet or force the connected client to leave the session if it has. - * - Call [[Session.updateConnection]] to update the [[Connection]] options. And this is - * valid for unused tokens, but also for already used tokens, so you can - * dynamically change the connection options on the fly. - */ - connectionId: string; - - /** - * The [[TokenOptions]] assigned to this token. - */ - tokenOptions: TokenOptions; - - /** - * @hidden - */ - constructor(json) { - this.token = json.token; - this.connectionId = json.connectionId; - let possibleKurentoOptions; - if (!!json.kurentoOptions) { - possibleKurentoOptions = {}; - if (json.kurentoOptions.videoMaxRecvBandwidth != null) { - possibleKurentoOptions['videoMaxRecvBandwidth'] = json.kurentoOptions.videoMaxRecvBandwidth; - } - if (json.kurentoOptions.videoMinRecvBandwidth != null) { - possibleKurentoOptions['videoMinRecvBandwidth'] = json.kurentoOptions.videoMinRecvBandwidth; - } - if (json.kurentoOptions.videoMaxSendBandwidth != null) { - possibleKurentoOptions['videoMaxSendBandwidth'] = json.kurentoOptions.videoMaxSendBandwidth; - } - if (json.kurentoOptions.videoMinSendBandwidth != null) { - possibleKurentoOptions['videoMinSendBandwidth'] = json.kurentoOptions.videoMinSendBandwidth; - } - if (json.kurentoOptions.allowedFilters != null) { - possibleKurentoOptions['allowedFilters'] = json.kurentoOptions.allowedFilters; - } - } - this.tokenOptions = { - role: json.role, - data: json.data, - record: json.record, - kurentoOptions: possibleKurentoOptions - }; - } - -} \ No newline at end of file diff --git a/openvidu-node-client/src/TokenOptions.ts b/openvidu-node-client/src/TokenOptions.ts index 0dacc6ed..cd4d947a 100644 --- a/openvidu-node-client/src/TokenOptions.ts +++ b/openvidu-node-client/src/TokenOptions.ts @@ -18,7 +18,7 @@ import { OpenViduRole } from './OpenViduRole'; /** - * See [[Session.generateToken]] + * @deprecated Use [[ConnectionOptions]] instead */ export interface TokenOptions { diff --git a/openvidu-node-client/src/index.ts b/openvidu-node-client/src/index.ts index e3b5a359..a0887a7c 100644 --- a/openvidu-node-client/src/index.ts +++ b/openvidu-node-client/src/index.ts @@ -4,7 +4,7 @@ export * from './Session'; export * from './SessionProperties'; export * from './TokenOptions'; export * from './ConnectionOptions'; -export * from './Token'; +export * from './ConnectionType'; export * from './MediaMode'; export * from './RecordingLayout'; export * from './RecordingMode'; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 4acc2671..20c62e00 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -22,7 +22,6 @@ import java.util.concurrent.locks.ReentrantLock; import com.google.gson.JsonObject; -import io.openvidu.java.client.ConnectionType; import io.openvidu.server.kurento.endpoint.EndpointType; import io.openvidu.server.utils.GeoLocation; @@ -44,7 +43,6 @@ public class Participant { active } - protected ConnectionType type; // WEBRTC, IPCAM protected String finalUserId; // ID to match this connection with a final user (HttpSession id) protected String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id) protected String participantPublicId; // ID to identify the user on clients @@ -52,7 +50,6 @@ public class Participant { protected ParticipantStatus status; // Status of the connection protected Long activeAt; // Timestamp when this connection entered status "active" protected String clientMetadata = ""; // Metadata provided on client side - protected String serverMetadata = ""; // Metadata provided on server side protected Token token; // Token associated to this participant protected GeoLocation location; // Location of the participant protected String platform; // Platform used by the participant to connect to the session @@ -78,10 +75,9 @@ public class Participant { */ public Lock singleRecordingLock = new ReentrantLock(); - public Participant(ConnectionType type, String finalUserId, String participantPrivatetId, - String participantPublicId, String sessionId, Token token, String clientMetadata, GeoLocation location, - String platform, EndpointType endpointType, Long activeAt) { - this.type = type; + public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId, + Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType, + Long activeAt) { this.finalUserId = finalUserId; this.participantPrivatetId = participantPrivatetId; this.participantPublicId = participantPublicId; @@ -96,18 +92,11 @@ public class Participant { if (clientMetadata != null) { this.clientMetadata = clientMetadata; } - if (!token.getServerMetadata().isEmpty()) { - this.serverMetadata = token.getServerMetadata(); - } this.location = location; this.platform = platform; this.endpointType = endpointType; } - public ConnectionType getType() { - return type; - } - public String getFinalUserId() { return finalUserId; } @@ -145,11 +134,7 @@ public class Participant { } public String getServerMetadata() { - return serverMetadata; - } - - public void setServerMetadata(String serverMetadata) { - this.serverMetadata = serverMetadata; + return this.token.getServerMetadata(); } public Token getToken() { @@ -234,16 +219,16 @@ public class Participant { public String getFullMetadata() { String fullMetadata; - if ((!this.clientMetadata.isEmpty()) && (!this.serverMetadata.isEmpty())) { - fullMetadata = this.clientMetadata + METADATA_SEPARATOR + this.serverMetadata; + if ((!this.clientMetadata.isEmpty()) && (!this.token.getServerMetadata().isEmpty())) { + fullMetadata = this.clientMetadata + METADATA_SEPARATOR + this.token.getServerMetadata(); } else { - fullMetadata = this.clientMetadata + this.serverMetadata; + fullMetadata = this.clientMetadata + this.token.getServerMetadata(); } return fullMetadata; } public void deleteIpcamProperties() { - this.clientMetadata = ""; + this.clientMetadata = null; this.token.setToken(null); } @@ -305,9 +290,9 @@ public class Participant { public JsonObject toJson() { JsonObject json = new JsonObject(); + // COMMON json.addProperty("id", this.participantPublicId); json.addProperty("object", "connection"); - json.addProperty("type", this.type.name()); json.addProperty("status", this.status.name()); json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id" json.addProperty("sessionId", this.sessionId); @@ -317,10 +302,14 @@ public class Participant { json.addProperty("platform", this.platform); if (this.token.getToken() != null) { json.addProperty("token", this.token.getToken()); + } else { + json.add("token", null); } - json.addProperty("role", this.token.getRole().name()); - json.addProperty("serverData", this.serverMetadata); - json.addProperty("record", this.token.record()); + // Add all ConnectionOptions + JsonObject connectionOptionsJson = this.token.getConnectionOptionsWithFinalJsonFormat(); + connectionOptionsJson.entrySet().forEach(entry -> { + json.add(entry.getKey(), entry.getValue()); + }); json.addProperty("clientData", this.clientMetadata); return json; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index e51dd190..9ac14df5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -45,14 +45,15 @@ import com.google.gson.JsonSyntaxException; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.java.client.ConnectionType; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.SessionProperties; import io.openvidu.server.cdr.CDREventRecording; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.coturn.CoturnCredentialsService; -import io.openvidu.server.kurento.core.KurentoTokenOptions; import io.openvidu.server.kurento.endpoint.EndpointType; import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.utils.FormatChecker; @@ -160,8 +161,8 @@ public abstract class SessionManager { public abstract void removeFilterEventListener(Session session, Participant subscriber, String streamId, String eventType); - public abstract Participant publishIpcam(Session session, MediaOptions mediaOptions, String serverMetadata) - throws Exception; + public abstract Participant publishIpcam(Session session, MediaOptions mediaOptions, + ConnectionOptions connectionOptions) throws Exception; public abstract void reconnectStream(Participant participant, String streamId, String sdpOffer, Integer transactionId); @@ -301,22 +302,22 @@ public abstract class SessionManager { } public Token newToken(Session session, OpenViduRole role, String serverMetadata, boolean record, - KurentoTokenOptions kurentoTokenOptions) throws Exception { + KurentoOptions kurentoOptions) throws Exception { if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) { log.error("Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); } - Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), role, serverMetadata, record, - kurentoTokenOptions); + Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata, + record, role, kurentoOptions); session.storeToken(tokenObj); session.showTokens("Token created"); return tokenObj; } - public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception { - Token tokenObj = new Token(token, session.getSessionId(), OpenViduRole.PUBLISHER, - serverMetadata != null ? serverMetadata : "", true, - this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null); + public Token newTokenForInsecureUser(Session session, String token, ConnectionOptions connectionOptions) + throws Exception { + Token tokenObj = new Token(token, session.getSessionId(), connectionOptions, + this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null); session.storeToken(tokenObj); session.showTokens("Token created for insecure user"); return tokenObj; @@ -364,9 +365,8 @@ public abstract class SessionManager { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(ConnectionType.WEBRTC, finalUserId, participantPrivatetId, - token.getConnectionId(), sessionId, token, clientMetadata, location, platform, - EndpointType.WEBRTC_ENDPOINT, null); + Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnectionId(), sessionId, + token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p); @@ -386,9 +386,8 @@ public abstract class SessionManager { public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token, String clientMetadata) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(ConnectionType.WEBRTC, null, participantPrivatetId, - ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, sessionId, token, clientMetadata, null, null, - EndpointType.WEBRTC_ENDPOINT, null); + Participant p = new Participant(null, participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, + sessionId, token, clientMetadata, null, null, EndpointType.WEBRTC_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId) .put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p); return p; @@ -400,8 +399,8 @@ public abstract class SessionManager { public Participant newIpcamParticipant(String sessionId, String ipcamId, Token token, GeoLocation location, String platform) { if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) { - Participant p = new Participant(ConnectionType.IPCAM, ipcamId, ipcamId, ipcamId, sessionId, token, null, - location, platform, EndpointType.PLAYER_ENDPOINT, null); + Participant p = new Participant(ipcamId, ipcamId, ipcamId, sessionId, token, null, location, platform, + EndpointType.PLAYER_ENDPOINT, null); this.sessionidParticipantpublicidParticipant.get(sessionId).put(ipcamId, p); return p; } else { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index b0fe7d30..ebb19202 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -21,95 +21,113 @@ import org.apache.commons.lang3.RandomStringUtils; import com.google.gson.JsonObject; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.java.client.ConnectionType; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.core.Participant.ParticipantStatus; import io.openvidu.server.coturn.TurnCredentials; -import io.openvidu.server.kurento.core.KurentoTokenOptions; public class Token { private String token; private String sessionId; private Long createdAt; - private OpenViduRole role; - private String serverMetadata = ""; - private boolean record; + private ConnectionOptions connectionOptions; private TurnCredentials turnCredentials; - private KurentoTokenOptions kurentoTokenOptions; private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); - public Token(String token, String sessionId, OpenViduRole role, String serverMetadata, boolean record, - TurnCredentials turnCredentials, KurentoTokenOptions kurentoTokenOptions) { + public Token(String token, String sessionId, ConnectionOptions connectionOptions, TurnCredentials turnCredentials) { this.token = token; this.sessionId = sessionId; this.createdAt = System.currentTimeMillis(); - this.role = role; - this.serverMetadata = serverMetadata; - this.record = record; + this.connectionOptions = connectionOptions; this.turnCredentials = turnCredentials; - this.kurentoTokenOptions = kurentoTokenOptions; + } + + public ConnectionType getType() { + return this.connectionOptions.getType(); } public String getToken() { return token; } - public void setToken(String token) { - this.token = token; + public void setToken(String newToken) { + this.token = newToken; } public Long getCreatedAt() { return this.createdAt; } - public OpenViduRole getRole() { - return role; - } - public String getServerMetadata() { - return serverMetadata; + return this.connectionOptions.getData(); } public boolean record() { - return record; + return this.connectionOptions.record(); + } + + public void setRecord(boolean newRecord) { + this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(), newRecord, + connectionOptions.getRole(), connectionOptions.getKurentoOptions(), connectionOptions.getRtspUri(), + connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(), + connectionOptions.getNetworkCache()); + } + + public OpenViduRole getRole() { + return this.connectionOptions.getRole(); + } + + public void setRole(OpenViduRole newRole) { + this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(), + connectionOptions.record(), newRole, connectionOptions.getKurentoOptions(), + connectionOptions.getRtspUri(), connectionOptions.adaptativeBitrate(), + connectionOptions.onlyPlayWithSubscribers(), connectionOptions.getNetworkCache()); + } + + public KurentoOptions getKurentoOptions() { + return this.connectionOptions.getKurentoOptions(); + } + + public String getRtspUri() { + return this.connectionOptions.getRtspUri(); + } + + public Boolean adaptativeBitrate() { + return this.connectionOptions.adaptativeBitrate(); + } + + public Boolean onlyPlayWithSubscribers() { + return this.connectionOptions.onlyPlayWithSubscribers(); + } + + public Integer getNetworkCache() { + return this.connectionOptions.getNetworkCache(); } public TurnCredentials getTurnCredentials() { return turnCredentials; } - public KurentoTokenOptions getKurentoTokenOptions() { - return kurentoTokenOptions; - } - public String getConnectionId() { return connectionId; } - public void setRole(OpenViduRole role) { - this.role = role; - } - - public void setRecord(boolean record) { - this.record = record; - } - public JsonObject toJson() { JsonObject json = new JsonObject(); json.addProperty("id", this.getToken()); - json.addProperty("object", "token"); json.addProperty("token", this.getToken()); + json.addProperty("createdAt", this.getCreatedAt()); json.addProperty("connectionId", this.getConnectionId()); - json.addProperty("createdAt", this.createdAt); json.addProperty("session", this.sessionId); - json.addProperty("role", this.getRole().toString()); json.addProperty("data", this.getServerMetadata()); - json.addProperty("record", this.record()); - if (this.getKurentoTokenOptions() != null) { - json.add("kurentoOptions", this.getKurentoTokenOptions().toJson()); + json.addProperty("role", this.getRole().toString()); + if (this.getKurentoOptions() != null) { + json.add("kurentoOptions", this.getKurentoOptions().toJson()); } return json; } @@ -118,28 +136,73 @@ public class Token { JsonObject json = new JsonObject(); json.addProperty("id", this.getConnectionId()); json.addProperty("object", "connection"); - json.addProperty("type", ConnectionType.WEBRTC.name()); json.addProperty("status", ParticipantStatus.pending.name()); json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id json.addProperty("sessionId", this.sessionId); json.addProperty("createdAt", this.createdAt); + + // Add all ConnectionOptions + JsonObject connectionOptionsJson = this.getConnectionOptionsWithFinalJsonFormat(); + connectionOptionsJson.entrySet().forEach(entry -> { + json.add(entry.getKey(), entry.getValue()); + }); + + json.addProperty("token", this.getToken()); json.add("activeAt", null); json.add("location", null); json.add("platform", null); - json.addProperty("token", this.getToken()); - json.addProperty("role", this.getRole().toString()); - json.addProperty("serverData", this.getServerMetadata()); - json.addProperty("record", this.record()); json.add("clientData", null); json.add("publishers", null); json.add("subscribers", null); return json; } + protected JsonObject getConnectionOptionsWithFinalJsonFormat() { + JsonObject json = this.connectionOptions.toJson(this.sessionId); + json.remove("session"); + json.addProperty("serverData", json.get("data").getAsString()); + json.remove("data"); + return json; + } + + private void updateConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role, + KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers, + Integer networkCache) { + ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + if (type != null) { + builder.type(type); + } + if (data != null) { + builder.data(data); + } + if (record != null) { + builder.record(record); + } + if (role != null) { + builder.role(role); + } + if (kurentoOptions != null) { + builder.kurentoOptions(kurentoOptions); + } + if (rtspUri != null) { + builder.rtspUri(rtspUri); + } + if (adaptativeBitrate != null) { + builder.adaptativeBitrate(adaptativeBitrate); + } + if (onlyPlayWithSubscribers != null) { + builder.onlyPlayWithSubscribers(onlyPlayWithSubscribers); + } + if (networkCache != null) { + builder.networkCache(networkCache); + } + this.connectionOptions = builder.build(); + } + @Override public String toString() { - if (this.role != null) - return this.role.name(); + if (this.connectionOptions.getRole() != null) + return this.connectionOptions.getRole().name(); else return this.token; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 0c5f9b84..ed5b6966 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -20,13 +20,15 @@ package io.openvidu.server.core; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; +import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionType; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.OpenViduServer; import io.openvidu.server.config.OpenviduBuildInfo; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.coturn.CoturnCredentialsService; import io.openvidu.server.coturn.TurnCredentials; -import io.openvidu.server.kurento.core.KurentoTokenOptions; public class TokenGenerator { @@ -39,8 +41,8 @@ public class TokenGenerator { @Autowired protected OpenviduBuildInfo openviduBuildConfig; - public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, boolean record, - KurentoTokenOptions kurentoTokenOptions) throws Exception { + public Token generateToken(String sessionId, String serverMetadata, boolean record, OpenViduRole role, + KurentoOptions kurentoOptions) throws Exception { String token = OpenViduServer.wsUrl; token += "?sessionId=" + sessionId; token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() @@ -56,6 +58,8 @@ public class TokenGenerator { token += "&turnCredential=" + turnCredentials.getCredential(); } } - return new Token(token, sessionId, role, serverMetadata, record, turnCredentials, kurentoTokenOptions); + ConnectionOptions connectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC) + .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); + return new Token(token, sessionId, connectionOptions, turnCredentials); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java index 6af8375d..306e5034 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoParticipant.java @@ -77,7 +77,7 @@ public class KurentoParticipant extends Participant { public KurentoParticipant(Participant participant, KurentoSession kurentoSession, KurentoParticipantEndpointConfig endpointConfig, OpenviduConfig openviduConfig, RecordingManager recordingManager) { - super(participant.getType(), participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(), + super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(), kurentoSession.getSessionId(), participant.getToken(), participant.getClientMetadata(), participant.getLocation(), participant.getPlatform(), participant.getEndpointType(), participant.getActiveAt()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 8823a2db..c9ba06a5 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -48,6 +48,8 @@ import com.google.gson.JsonObject; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.Recording; import io.openvidu.java.client.RecordingLayout; @@ -387,7 +389,7 @@ public class KurentoSessionManager extends SessionManager { * kurentoParticipant.getPublisher().apply(elem); } */ - KurentoTokenOptions kurentoTokenOptions = participant.getToken().getKurentoTokenOptions(); + KurentoOptions kurentoTokenOptions = participant.getToken().getKurentoOptions(); if (kurentoOptions.getFilter() != null && kurentoTokenOptions != null) { if (kurentoTokenOptions.isFilterAllowed(kurentoOptions.getFilter().getType())) { this.applyFilterInPublisher(kParticipant, kurentoOptions.getFilter()); @@ -990,7 +992,7 @@ public class KurentoSessionManager extends SessionManager { @Override /* Protected by Session.closingLock.readLock */ - public Participant publishIpcam(Session session, MediaOptions mediaOptions, String serverMetadata) + public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionOptions connectionOptions) throws Exception { final String sessionId = session.getSessionId(); final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions; @@ -1032,7 +1034,8 @@ public class KurentoSessionManager extends SessionManager { this.newInsecureParticipant(rtspConnectionId); String token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - this.newTokenForInsecureUser(session, token, serverMetadata); + + this.newTokenForInsecureUser(session, token, connectionOptions); final Token tokenObj = session.consumeToken(token); Participant ipcamParticipant = this.newIpcamParticipant(sessionId, rtspConnectionId, tokenObj, location, @@ -1109,9 +1112,10 @@ public class KurentoSessionManager extends SessionManager { Session session = this.getSession(sessionId); return ((KurentoSession) session).getParticipantPrivateIdFromStreamId(streamId); } - + @Override - public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, Boolean videoActive, Boolean audioActive) { + public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, + Boolean videoActive, Boolean audioActive) { sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java deleted file mode 100644 index a7b21da8..00000000 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoTokenOptions.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package io.openvidu.server.kurento.core; - -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; - -public class KurentoTokenOptions { - - private Integer videoMaxRecvBandwidth; - private Integer videoMinRecvBandwidth; - private Integer videoMaxSendBandwidth; - private Integer videoMinSendBandwidth; - private Map allowedFilters = new ConcurrentHashMap<>(); - - public KurentoTokenOptions(JsonObject options) { - if (options.has("videoMaxRecvBandwidth")) { - this.videoMaxRecvBandwidth = options.get("videoMaxRecvBandwidth").getAsInt(); - } - if (options.has("videoMinRecvBandwidth")) { - this.videoMinRecvBandwidth = options.get("videoMinRecvBandwidth").getAsInt(); - } - if (options.has("videoMaxSendBandwidth")) { - this.videoMaxSendBandwidth = options.get("videoMaxSendBandwidth").getAsInt(); - } - if (options.has("videoMinSendBandwidth")) { - this.videoMinSendBandwidth = options.get("videoMinSendBandwidth").getAsInt(); - } - if (options.has("allowedFilters")) { - JsonArray filters = options.get("allowedFilters").getAsJsonArray(); - Iterator it = filters.iterator(); - while (it.hasNext()) { - this.allowedFilters.put(it.next().getAsString(), true); - } - } - } - - public Integer getVideoMaxRecvBandwidth() { - return videoMaxRecvBandwidth; - } - - public Integer getVideoMinRecvBandwidth() { - return videoMinRecvBandwidth; - } - - public Integer getVideoMaxSendBandwidth() { - return videoMaxSendBandwidth; - } - - public Integer getVideoMinSendBandwidth() { - return videoMinSendBandwidth; - } - - public String[] getAllowedFilters() { - return allowedFilters.keySet().stream().toArray(String[]::new); - } - - public boolean isFilterAllowed(String filterType) { - return this.allowedFilters.containsKey(filterType); - } - - public JsonObject toJson() { - JsonObject json = new JsonObject(); - if (this.getVideoMaxRecvBandwidth() != null) { - json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth()); - } - if (this.getVideoMinRecvBandwidth() != null) { - json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth()); - } - if (this.getVideoMaxSendBandwidth() != null) { - json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth()); - } - if (this.getVideoMinSendBandwidth() != null) { - json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth()); - } - if (this.getAllowedFilters().length > 0) { - JsonArray filtersJson = new JsonArray(); - String[] filters = this.getAllowedFilters(); - for (String filter : filters) { - filtersJson.add(filter); - } - json.add("allowedFilters", filtersJson); - } - return json; - } - -} diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java index 77b216f2..8c68e41a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/endpoint/MediaEndpoint.java @@ -53,11 +53,11 @@ import com.google.gson.JsonObject; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.core.Participant; import io.openvidu.server.kurento.core.KurentoMediaOptions; import io.openvidu.server.kurento.core.KurentoParticipant; -import io.openvidu.server.kurento.core.KurentoTokenOptions; /** * {@link Endpoint} wrapper. Can be based on WebRtcEndpoint (that supports @@ -128,7 +128,7 @@ public abstract class MediaEndpoint { this.openviduConfig = openviduConfig; - KurentoTokenOptions kurentoTokenOptions = this.owner.getToken().getKurentoTokenOptions(); + KurentoOptions kurentoTokenOptions = this.owner.getToken().getKurentoOptions(); if (kurentoTokenOptions != null) { this.maxRecvKbps = kurentoTokenOptions.getVideoMaxRecvBandwidth() != null ? kurentoTokenOptions.getVideoMaxRecvBandwidth() diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java index 655ba4a9..fe552fad 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecorderEndpointWrapper.java @@ -64,7 +64,9 @@ public class RecorderEndpointWrapper { this.name = StringUtils.removeEnd(nameAux, SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION); this.connectionId = json.get("connectionId").getAsString(); this.streamId = json.get("streamId").getAsString(); - this.clientData = json.get("clientData").getAsString(); + this.clientData = (json.has("clientData") && !json.get("clientData").isJsonNull()) + ? json.get("clientData").getAsString() + : null; this.serverData = json.get("serverData").getAsString(); this.startTime = json.get("startTime").getAsLong(); this.endTime = json.get("endTime").getAsLong(); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 4b7dea45..7f981f57 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -20,7 +20,6 @@ package io.openvidu.server.rest; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; @@ -45,12 +44,15 @@ import org.springframework.web.bind.annotation.RestController; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.openvidu.client.OpenViduException; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.java.client.ConnectionType; +import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording.OutputMode; @@ -66,7 +68,6 @@ import io.openvidu.server.core.Session; import io.openvidu.server.core.SessionManager; import io.openvidu.server.core.Token; import io.openvidu.server.kurento.core.KurentoMediaOptions; -import io.openvidu.server.kurento.core.KurentoTokenOptions; import io.openvidu.server.recording.Recording; import io.openvidu.server.recording.service.RecordingManager; import io.openvidu.server.utils.RecordingUtils; @@ -273,45 +274,29 @@ public class SessionRestController { public ResponseEntity initializeConnection(@PathVariable("sessionId") String sessionId, @RequestBody Map params) { - log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString()); + log.info("REST API: POST {} {}", RequestMappings.API + "/sessions/" + sessionId + "/connection", + params.toString()); Session session = this.sessionManager.getSessionWithNotActive(sessionId); if (session == null) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - String typeString; - String data; - Boolean record; + ConnectionOptions connectionOptions; try { - typeString = (String) params.get("type"); - data = (String) params.get("data"); - record = (Boolean) params.get("record"); - } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in parameter \"type\"", - "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + connectionOptions = getConnectionOptionsFromParams(params); + } catch (Exception e) { + return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", + HttpStatus.BAD_REQUEST); } - - ConnectionType type; - try { - if (typeString != null) { - type = ConnectionType.valueOf(typeString); - } else { - type = ConnectionType.WEBRTC; - } - } catch (IllegalArgumentException e) { - return this.generateErrorResponse("Parameter type " + params.get("typeString") + " is not defined", - RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); - } - - switch (type) { + switch (connectionOptions.getType()) { case WEBRTC: - return this.newWebrtcConnection(session, data, record, params); + return this.newWebrtcConnection(session, connectionOptions); case IPCAM: - return this.newIpcamConnection(session, data, record, params); + return this.newIpcamConnection(session, connectionOptions); default: - return this.generateErrorResponse("Wrong type " + typeString, - RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); + return this.generateErrorResponse("Wrong type parameter", "/sessions/" + sessionId + "/connection", + HttpStatus.BAD_REQUEST); } } @@ -654,12 +639,8 @@ public class SessionRestController { log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString()); String sessionId; - String metadata; - Boolean record; try { sessionId = (String) params.get("session"); - metadata = (String) params.get("data"); - record = (Boolean) params.get("record"); } catch (ClassCastException e) { return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST); } @@ -675,10 +656,15 @@ public class SessionRestController { if (session == null) { return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); } - Map map = new HashMap<>(); - params.entrySet().forEach(entry -> map.put((String) entry.getKey(), entry.getValue())); - map.put("type", "WEBRTC"); - ResponseEntity entity = this.newWebrtcConnection(session, metadata, record, params); + + ConnectionOptions connectionOptions; + try { + connectionOptions = getConnectionOptionsFromParams(params); + } catch (Exception e) { + return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", + HttpStatus.BAD_REQUEST); + } + ResponseEntity entity = this.newWebrtcConnection(session, connectionOptions); JsonObject jsonResponse = JsonParser.parseString(entity.getBody().toString()).getAsJsonObject(); if (jsonResponse.has("error")) { @@ -793,57 +779,15 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.OK); } - protected ResponseEntity newWebrtcConnection(Session session, String serverData, Boolean record, - Map params) { + protected ResponseEntity newWebrtcConnection(Session session, ConnectionOptions connectionOptions) { - final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection"; - - String roleString = null; - try { - roleString = (String) params.get("role"); - } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST); - } - - OpenViduRole role = null; - try { - if (roleString != null) { - role = OpenViduRole.valueOf(roleString); - } else { - role = OpenViduRole.PUBLISHER; - } - } catch (IllegalArgumentException e) { - return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", REQUEST_PATH, - HttpStatus.BAD_REQUEST); - } - - JsonObject kurentoOptions = null; - if (params.get("kurentoOptions") != null) { - try { - kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject(); - } catch (Exception e) { - return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object", - REQUEST_PATH, HttpStatus.BAD_REQUEST); - } - } - - KurentoTokenOptions kurentoTokenOptions = null; - if (kurentoOptions != null) { - try { - kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions); - } catch (Exception e) { - return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", REQUEST_PATH, - HttpStatus.BAD_REQUEST); - } - } - - serverData = (serverData != null) ? serverData : ""; - record = (record != null) ? record : true; + final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection"; // While closing a session tokens can't be generated if (session.closingLock.readLock().tryLock()) { try { - Token token = sessionManager.newToken(session, role, serverData, record, kurentoTokenOptions); + Token token = sessionManager.newToken(session, connectionOptions.getRole(), connectionOptions.getData(), + connectionOptions.record(), connectionOptions.getKurentoOptions()); return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (Exception e) { @@ -861,34 +805,9 @@ public class SessionRestController { } } - protected ResponseEntity newIpcamConnection(Session session, String serverData, Boolean record, - Map params) { + protected ResponseEntity newIpcamConnection(Session session, ConnectionOptions connectionOptions) { - final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection"; - - String rtspUri; - Boolean adaptativeBitrate; - Boolean onlyPlayWithSubscribers; - Integer networkCache; - try { - rtspUri = (String) params.get("rtspUri"); - adaptativeBitrate = (Boolean) params.get("adaptativeBitrate"); - onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers"); - networkCache = (Integer) params.get("networkCache"); - } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST); - } - - if (rtspUri == null) { - return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", REQUEST_PATH, - HttpStatus.BAD_REQUEST); - } - - adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true; - onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true; - networkCache = networkCache != null ? networkCache : 2000; - serverData = serverData != null ? serverData : ""; - record = (record != null) ? record : true; + final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection"; boolean hasAudio = true; boolean hasVideo = true; @@ -898,8 +817,9 @@ public class SessionRestController { Integer frameRate = null; String videoDimensions = null; KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive, - videoActive, typeOfVideo, frameRate, videoDimensions, null, false, rtspUri, adaptativeBitrate, - onlyPlayWithSubscribers, networkCache); + videoActive, typeOfVideo, frameRate, videoDimensions, null, false, connectionOptions.getRtspUri(), + connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(), + connectionOptions.getNetworkCache()); // While closing a session IP cameras can't be published if (session.closingLock.readLock().tryLock()) { @@ -907,7 +827,8 @@ public class SessionRestController { if (session.isClosed()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, serverData); + Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, + connectionOptions); return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (MalformedURLException e) { @@ -936,6 +857,125 @@ public class SessionRestController { return token; } + protected ConnectionOptions getConnectionOptionsFromParams(Map params) throws Exception { + + ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + + String typeString; + String data; + Boolean record; + try { + typeString = (String) params.get("type"); + data = (String) params.get("data"); + record = (Boolean) params.get("record"); + } catch (ClassCastException e) { + throw new Exception("Type error in some parameter: " + e.getMessage()); + } + + ConnectionType type; + try { + if (typeString != null) { + type = ConnectionType.valueOf(typeString); + } else { + type = ConnectionType.WEBRTC; + } + } catch (IllegalArgumentException e) { + throw new Exception("Parameter 'type' " + typeString + " is not defined"); + } + data = data != null ? data : ""; + record = record != null ? record : true; + + // Build COMMON options + builder.type(type).data(data).record(record); + + OpenViduRole role = null; + KurentoOptions kurentoOptions = null; + + if (ConnectionType.WEBRTC.equals(type)) { + String roleString; + try { + roleString = (String) params.get("role"); + } catch (ClassCastException e) { + throw new Exception("Type error in parameter 'role': " + e.getMessage()); + } + try { + if (roleString != null) { + role = OpenViduRole.valueOf(roleString); + } else { + role = OpenViduRole.PUBLISHER; + } + } catch (IllegalArgumentException e) { + throw new Exception("Parameter role " + params.get("role") + " is not defined"); + } + JsonObject kurentoOptionsJson = null; + if (params.get("kurentoOptions") != null) { + try { + kurentoOptionsJson = JsonParser.parseString(params.get("kurentoOptions").toString()) + .getAsJsonObject(); + } catch (Exception e) { + throw new Exception("Error in parameter 'kurentoOptions'. It is not a valid JSON object"); + } + } + if (kurentoOptionsJson != null) { + try { + KurentoOptions.Builder builder2 = new KurentoOptions.Builder(); + if (kurentoOptionsJson.has("videoMaxRecvBandwidth")) { + builder2.videoMaxRecvBandwidth(kurentoOptionsJson.get("videoMaxRecvBandwidth").getAsInt()); + } + if (kurentoOptionsJson.has("videoMinRecvBandwidth")) { + builder2.videoMinRecvBandwidth(kurentoOptionsJson.get("videoMinRecvBandwidth").getAsInt()); + } + if (kurentoOptionsJson.has("videoMaxSendBandwidth")) { + builder2.videoMaxSendBandwidth(kurentoOptionsJson.get("videoMaxSendBandwidth").getAsInt()); + } + if (kurentoOptionsJson.has("videoMinSendBandwidth")) { + builder2.videoMinSendBandwidth(kurentoOptionsJson.get("videoMinSendBandwidth").getAsInt()); + } + if (kurentoOptionsJson.has("allowedFilters")) { + JsonArray filters = kurentoOptionsJson.get("allowedFilters").getAsJsonArray(); + String[] arrayOfFilters = new String[filters.size()]; + Iterator it = filters.iterator(); + int index = 0; + while (it.hasNext()) { + arrayOfFilters[index] = it.next().getAsString(); + index++; + } + builder2.allowedFilters(arrayOfFilters); + } + kurentoOptions = builder2.build(); + } catch (Exception e) { + throw new Exception("Type error in some parameter of 'kurentoOptions': " + e.getMessage()); + } + } + + // Build WEBRTC options + builder.role(role).kurentoOptions(kurentoOptions); + + } else if (ConnectionType.IPCAM.equals(type)) { + String rtspUri; + Boolean adaptativeBitrate; + Boolean onlyPlayWithSubscribers; + Integer networkCache; + try { + rtspUri = (String) params.get("rtspUri"); + adaptativeBitrate = (Boolean) params.get("adaptativeBitrate"); + onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers"); + networkCache = (Integer) params.get("networkCache"); + } catch (ClassCastException e) { + throw new Exception("Type error in some parameter: " + e.getMessage()); + } + adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true; + onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true; + networkCache = networkCache != null ? networkCache : 2000; + + // Build IPCAM options + builder.rtspUri(rtspUri).adaptativeBitrate(adaptativeBitrate) + .onlyPlayWithSubscribers(onlyPlayWithSubscribers).networkCache(networkCache).build(); + } + + return builder.build(); + } + protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { JsonObject responseJson = new JsonObject(); responseJson.addProperty("timestamp", System.currentTimeMillis()); diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index 3d627340..c50ca993 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -45,6 +45,7 @@ import com.google.gson.JsonSyntaxException; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.core.EndReason; import io.openvidu.server.core.IdentifierPrefixes; @@ -248,7 +249,7 @@ public class RpcHandler extends DefaultJsonRpcHandler { token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); try { - sessionManager.newTokenForInsecureUser(session, token, null); + sessionManager.newTokenForInsecureUser(session, token, new ConnectionOptions.Builder().build()); } catch (Exception e) { throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, "Unable to create token for session " + sessionId + ": " + e.getMessage()); @@ -492,7 +493,7 @@ public class RpcHandler extends DefaultJsonRpcHandler { // user's stream) or if the user is the owner of the stream and has a token // configured with this specific filter if (isModerator || (this.userIsStreamOwner(rpcConnection.getSessionId(), participant, streamId) - && participant.getToken().getKurentoTokenOptions().isFilterAllowed(filterType))) { + && participant.getToken().getKurentoOptions().isFilterAllowed(filterType))) { JsonObject filterOptions; try { filterOptions = JsonParser.parseString(getStringParam(request, ProtocolElements.FILTER_OPTIONS_PARAM)) diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 125c1ea3..ddb56819 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -36,7 +36,7 @@ import org.springframework.test.context.web.WebAppConfiguration; import com.google.gson.Gson; import com.google.gson.JsonObject; -import io.openvidu.java.client.OpenViduRole; +import io.openvidu.java.client.ConnectionOptions; import io.openvidu.server.core.Participant; import io.openvidu.server.core.SessionManager; import io.openvidu.server.core.Token; @@ -115,7 +115,8 @@ public class SessionGarbageCollectorIntegrationTest { } private void joinParticipant(String sessionId, String token) { - Token t = new Token(token, sessionId, OpenViduRole.PUBLISHER, "SERVER_METADATA", true, null, null); + ConnectionOptions connectionOptions = new ConnectionOptions.Builder().data("SERVER_METADATA").build(); + Token t = new Token(token, sessionId, connectionOptions, null); String uuid = UUID.randomUUID().toString(); String participantPrivateId = "PARTICIPANT_PRIVATE_ID_" + uuid; String finalUserId = "FINAL_USER_ID_" + uuid; diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java index 4c09af54..6daa0339 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/CustomHttpClient.java @@ -110,7 +110,7 @@ public class CustomHttpClient { public JsonObject rest(HttpMethod method, String path, String body, int status, boolean matchKeys, boolean matchValues, boolean matchArrays, String jsonReturnedValue) throws Exception { JsonObject jsonExpected = null; - jsonReturnedValue.replaceAll("'", "\""); + jsonReturnedValue = jsonReturnedValue.replaceAll("'", "\""); try { jsonExpected = JsonParser.parseString(jsonReturnedValue).getAsJsonObject(); } catch (JsonSyntaxException e1) { @@ -171,7 +171,8 @@ public class CustomHttpClient { public static void checkSameType(JsonElement expected, JsonElement actual, String key, boolean checkAlsoSameValue) throws Exception { if (!expected.getClass().equals(actual.getClass())) { - throw new Exception("Expected JSON element has not the same class as the actual JSON element. Expected: " + throw new Exception("Expected JSON element \"" + key + + "\" has not the same class as the actual JSON element. Expected: " + expected.getClass().getSimpleName() + ". Actual: " + actual.getClass().getSimpleName()); } if (expected.isJsonNull()) { diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java index 028209be..0127d9d5 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java @@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import io.github.bonigarcia.wdm.WebDriverManager; @@ -63,6 +64,12 @@ import io.openvidu.test.browsers.utils.Unzipper; public class AbstractOpenViduTestAppE2eTest { + final protected String DEFAULT_JSON_SESSION = "{'id':'STR','object':'session','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; + final protected String DEFAULT_JSON_PENDING_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'pending','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':null,'location':null,'platform':null,'token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':null,'publishers':null,'subscribers':null}"; + final protected String DEFAULT_JSON_ACTIVE_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':'STR','publishers':[],'subscribers':[]}"; + final protected String DEFAULT_JSON_IPCAM_CONNECTION = "{'id':'STR','object':'connection','type':'IPCAM','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'IPCAM','token':null,'serverData':'STR','record':true,'role':null,'kurentoOptions':null,'rtspUri':'STR','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':2000,'clientData':null,'publishers':[],'subscribers':[]}"; + final protected String DEFAULT_JSON_TOKEN = "{'id':'STR','token':'STR','connectionId':'STR','createdAt':0,'session':'STR','role':'STR','data':'STR','kurentoOptions':{}}"; + protected static String OPENVIDU_SECRET = "MY_SECRET"; protected static String OPENVIDU_URL = "https://localhost:4443/"; protected static String APP_URL = "http://localhost:4200/"; @@ -546,4 +553,17 @@ public class AbstractOpenViduTestAppE2eTest { + " | awk '{print $1 }' | xargs -I {} docker rm -f {}"); } + protected String mergeJson(String json, String newProperties, String[] removeProperties) { + JsonObject jsonObj = JsonParser.parseString(json.replaceAll("'", "\"")).getAsJsonObject(); + JsonObject newJsonObj = JsonParser.parseString(newProperties.replaceAll("'", "\"")).getAsJsonObject(); + newJsonObj.entrySet().forEach(entry -> { + jsonObj.remove(entry.getKey()); + jsonObj.add(entry.getKey(), entry.getValue()); + }); + for (String prop : removeProperties) { + jsonObj.remove(prop); + } + return jsonObj.toString().replaceAll("\"", "'"); + } + } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index f075ec1b..43b4da49 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -31,7 +31,6 @@ import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; import io.openvidu.java.client.Session; -import io.openvidu.java.client.Token; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; @@ -212,19 +211,19 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'" - + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" - + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); + mergeJson(DEFAULT_JSON_PENDING_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','serverData':'','record':false,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}", + new String[0])); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, true, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'" - + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':" - + createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}"); + mergeJson(DEFAULT_JSON_PENDING_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','serverData':'','token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}", + new String[0])); // Test with openvidu-java-client OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET); @@ -275,6 +274,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertTrue("Session object should have changed", session.fetch()); connection = session.getActiveConnections().get(0); + final Long activeAt = connection.activeAt(); + Assert.assertTrue("activeAt should be greater than createdAt in Connection object", activeAt > createdAt); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); @@ -284,29 +285,37 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" - + tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); + mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':false,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + + activeAt + ",'serverData':''}", + new String[] { "location", "platform", "clientData" })); // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'record':true}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" - + tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); + mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'MODERATOR','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + + activeAt + ",'serverData':''}", + new String[] { "location", "platform", "clientData" })); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" - + tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); + mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'SUBSCRIBER','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + + activeAt + ",'serverData':''}", + new String[] { "location", "platform", "clientData" })); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, - "{'id':'" + tokenConnectionId - + "','object':'connection','type':'WEBRTC','status':'active','connectionId':'" - + tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token - + "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}"); + mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, + "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + + "','role':'PUBLISHER','record':true,'token':'" + token + + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + + activeAt + ",'serverData':''}", + new String[] { "location", "platform", "clientData" })); // Test with openvidu-node-client user.getDriver().findElement(By.id("session-api-btn-0")).click(); @@ -341,7 +350,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); - Assert.assertTrue("Wrong record in Connection object", connection.record()); + Assert.assertFalse("Wrong record in Connection object", connection.record()); Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); connection = session.updateConnection(tokenConnectionId, new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); @@ -397,9 +406,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { void openViduJavaClientProTest() throws Exception { Session session = OV.createSession(); Assert.assertFalse(session.fetch()); - Token token = session.createToken(); - Assert.assertTrue(session.fetch()); - Connection connection = session.getConnection(token.getConnectionId()); + Connection connection = session.createConnection(); + Assert.assertFalse(session.fetch()); Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertTrue("Wrong record property", connection.record()); session.updateConnection(connection.getConnectionId(), diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 7316d1f6..c5cf2af8 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -48,11 +48,14 @@ import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.mashape.unirest.http.HttpMethod; import io.openvidu.java.client.Connection; +import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.OpenVidu; @@ -66,8 +69,6 @@ import io.openvidu.java.client.RecordingMode; import io.openvidu.java.client.RecordingProperties; import io.openvidu.java.client.Session; import io.openvidu.java.client.SessionProperties; -import io.openvidu.java.client.Token; -import io.openvidu.java.client.TokenOptions; import io.openvidu.test.browsers.FirefoxUser; import io.openvidu.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler; @@ -84,10 +85,6 @@ import io.openvidu.test.browsers.utils.webhook.CustomWebhook; @ExtendWith(SpringExtension.class) public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { - final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}"; - final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','createdAt':0,'role':'STR','data':'STR','record':true}"; - final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','type':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}"; - @BeforeAll() protected static void setupAll() { checkFfmpegInstallation(); @@ -2141,27 +2138,19 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { KurentoOptions kurentoOptions = new KurentoOptions.Builder().videoMaxRecvBandwidth(250) .allowedFilters(new String[] { "GStreamerFilter" }).build(); - TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR) + ConnectionOptions moderatorConnectionOptions = new ConnectionOptions.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - Token tokenModerator = session.createToken(tokenOptionsModerator); - String tokenModeratorString = tokenModerator.getToken(); - String connectionIdModerator = tokenModerator.getConnectionId(); + Connection connectionModerator = session.createConnection(moderatorConnectionOptions); - TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER) - .data(serverDataSubscriber).build(); - Token tokenSubscriber = session.createToken(tokenOptionsSubscriber); - String tokenSubscriberString = tokenSubscriber.getToken(); - String connectionIdSubscriber = tokenSubscriber.getConnectionId(); + ConnectionOptions subscriberConnectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC) + .role(OpenViduRole.SUBSCRIBER).data(serverDataSubscriber).build(); + Connection connectionSubscriber = session.createConnection(subscriberConnectionOptions); - Assert.assertTrue("Session.fetch() should return true if new pending connections", session.fetch()); + Assert.assertFalse("Session.fetch() should return false after Session.createConnection", session.fetch()); Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch()); Assert.assertEquals("Wrong number of active connections", 0, session.getActiveConnections().size()); Assert.assertEquals("Wrong number of connections", 2, session.getConnections().size()); - Connection connectionModerator = session.getConnection(connectionIdModerator); - Connection connectionSubscriber = session.getConnection(connectionIdSubscriber); - Assert.assertEquals("Wrong connectionId property", connectionIdModerator, - connectionModerator.getConnectionId()); Assert.assertEquals("Wrong status property", "pending", connectionModerator.getStatus()); Assert.assertEquals("Wrong role property", OpenViduRole.MODERATOR, connectionModerator.getRole()); Assert.assertTrue("Wrong record property", connectionModerator.record()); @@ -2183,7 +2172,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenModeratorString); + tokeInput.sendKeys(connectionModerator.getToken()); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2198,7 +2187,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(tokenSubscriberString); + tokeInput.sendKeys(connectionSubscriber.getToken()); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); @@ -2514,8 +2503,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { } pub = connectionModerator.getPublishers().get(0); - // TODO: test delete unused Token, update unused Token and update ongoing - // Connection + // TODO: test delete unused Connection session.forceUnpublish(pub); user.getEventManager().waitUntilEventReaches("streamDestroyed", 6); @@ -2528,6 +2516,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong number of Subscribers", 0, con.getSubscribers().size()); }); + // Delete active Connection session.forceDisconnect(connectionModerator); user.getEventManager().waitUntilEventReaches("sessionDisconnected", 1); user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1); @@ -2541,6 +2530,33 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertFalse("Session.fetch() should return true", OV.fetch()); + // Delete pending Connection + session = OV.createSession(); + Connection con = session.createConnection(); + Assert.assertEquals("Wrong number of Connections", 1, session.getConnections().size()); + Assert.assertEquals("Wrong number of active Connections", 0, session.getActiveConnections().size()); + Assert.assertFalse(session.fetch()); + session.forceDisconnect(con); + Assert.assertEquals("Wrong number of Connections", 0, session.getConnections().size()); + Assert.assertEquals("Wrong number of active Connections", 0, session.getActiveConnections().size()); + Assert.assertFalse(session.fetch()); + + // Test IPCAM + final String rtsp = "rtsp://dummyurl.com"; + Connection ipcamera = session.createConnection(new ConnectionOptions.Builder().type(ConnectionType.IPCAM) + .rtspUri(rtsp).adaptativeBitrate(false).onlyPlayWithSubscribers(false).networkCache(50).build()); + Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch()); + Assert.assertFalse("Session.fetch() should return false", session.fetch()); + Assert.assertEquals("Wrong number of active connections", 1, session.getActiveConnections().size()); + Assert.assertEquals("Wrong number of connections", 1, session.getConnections().size()); + ipcamera = session.getConnection(ipcamera.getConnectionId()); + Assert.assertEquals("Wrong type property of Connection object", "IPCAM", ipcamera.getType().name()); + Assert.assertNull("Property role of an IPCAM connection should be null", ipcamera.getRole()); + Assert.assertEquals("Wrong property rtspUri", rtsp, ipcamera.getRtspUri()); + Assert.assertFalse("Wrong property adaptativeBitrate", ipcamera.adaptativeBitrate()); + Assert.assertFalse("Wrong property onlyPlayWithSubscribers", ipcamera.onlyPlayWithSubscribers()); + Assert.assertEquals("Wrong property networkCache", 50, ipcamera.getNetworkCache()); + gracefullyLeaveParticipants(2); } @@ -2626,31 +2642,61 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // 200 body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'videoMaxSendBandwidth':777,'allowedFilters': ['GStreamerFilter']}}"; res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, - "{'id':'STR','object':'STR','connectionId':'STR','session':'STR','createdAt':0,'role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}"); + mergeJson(DEFAULT_JSON_TOKEN, + "{'kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}", new String[0])); final String token1 = res.get("token").getAsString(); - final String connectionId1 = res.get("connectionId").getAsString(); - final long createdAt1 = res.get("createdAt").getAsLong(); Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'", res.get("id").getAsString(), token1); Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString()); + res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, + HttpStatus.SC_OK, true, true, false, "{'numberOfElements':1,'content':[]}"); + JsonObject connection1 = res.getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject(); + final String connectionId1 = connection1.get("id").getAsString(); + final long createdAt1 = connection1.get("createdAt").getAsLong(); + /** POST /openvidu/api/sessions/CUSTOM_SESSION_ID/connection **/ + // 400 + body = "{'type':false}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_BAD_REQUEST); + body = "{'type':'NOT_EXISTS'}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_BAD_REQUEST); + body = "{'type':'WEBRTC','role':123}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_BAD_REQUEST); + body = "{'type':'WEBRTC','role':123}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_BAD_REQUEST); + body = "{'type':'WEBRTC','role':'MODERATOR','data':true}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_BAD_REQUEST); + // 200 + String kurentoOpts = "'kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['GStreamerFilter']}"; + body = "{'type':'WEBRTC','role':'MODERATOR','data':'SERVER_DATA'," + kurentoOpts + "}"; + res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_OK, true, false, true, + mergeJson(DEFAULT_JSON_PENDING_CONNECTION, "{" + kurentoOpts + "}", new String[0])); + restClient.rest(HttpMethod.DELETE, + "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + res.get("id").getAsString(), + HttpStatus.SC_NO_CONTENT); // Default values - body = "{'session': 'CUSTOM_SESSION_ID'}"; - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, - DEFAULT_JSON_TOKEN); - final String token2 = res.get("id").getAsString(); - final String connectionId2 = res.get("connectionId").getAsString(); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", "{}", + HttpStatus.SC_OK); + final String token2 = res.get("token").getAsString(); + final String connectionId2 = res.get("id").getAsString(); /** GET /openvidu/api/sessions/ID/connection (with pending connections) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, true, true, false, "{'numberOfElements':2,'content':[]}"); restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null, HttpStatus.SC_OK, true, true, true, - "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 - + "','object':'connection','type':'WEBRTC','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'" - + token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':" - + createdAt1 - + ",'activeAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}"); + mergeJson(DEFAULT_JSON_PENDING_CONNECTION, + "{'id':'" + connectionId1 + "','connectionId':'" + connectionId1 + + "','sessionId':'CUSTOM_SESSION_ID','token':'" + token1 + + "','serverData':'SERVER_DATA','role':'MODERATOR'," + kurentoOpts + ",'createdAt':" + + createdAt1 + "}", + new String[0])); /** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/ body = "{}"; @@ -2864,14 +2910,14 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { **/ body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); - body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}"; - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, - DEFAULT_JSON_TOKEN); - final String tokenAConnectionId = res.get("connectionId").getAsString(); + body = "{'type': 'WEBRTC', 'role': 'SUBSCRIBER'}"; + res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_PENDING_CONNECTION); + final String connectionIdA = res.get("id").getAsString(); final String tokenA = res.get("token").getAsString(); - res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true, - DEFAULT_JSON_TOKEN); - final String tokenBConnectionId = res.get("connectionId").getAsString(); + res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_PENDING_CONNECTION); + final String connectionIdB = res.get("connectionId").getAsString(); final String tokenB = res.get("token").getAsString(); user.getDriver().findElement(By.id("one2one-btn")).click(); @@ -2895,7 +2941,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); // Invalidate token - restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId, + restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionIdA, HttpStatus.SC_NO_CONTENT); // User should pop up invalid token @@ -2918,7 +2964,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getEventManager().waitUntilEventReaches("connectionCreated", 1); // connectionId should be equal to the one brought by the token - Assert.assertEquals("Wrong connectionId", tokenBConnectionId, + Assert.assertEquals("Wrong connectionId", connectionIdB, restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK) .get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject() .get("connectionId").getAsString()); @@ -3286,7 +3332,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Publish IP camera. Dummy URL because no user will subscribe to it [200] String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; JsonObject response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection", - ipCamBody, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); + ipCamBody, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION); CustomWebhook.waitForEvent("sessionCreated", 1); CustomWebhook.waitForEvent("participantJoined", 1); @@ -3294,7 +3340,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong serverData property", "MY_IP_CAMERA", response.get("serverData").getAsString()); Assert.assertEquals("Wrong platform property", "IPCAM", response.get("platform").getAsString()); - Assert.assertEquals("Wrong role property", "PUBLISHER", response.get("role").getAsString()); + Assert.assertEquals("Wrong role property", JsonNull.INSTANCE, response.get("role")); Assert.assertEquals("Wrong type property", "IPCAM", response.get("type").getAsString()); Assert.assertEquals("Wrong number of publishers in IPCAM participant", 1, @@ -3384,7 +3430,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, - HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION); user.getEventManager().waitUntilEventReaches("connectionCreated", 2); user.getEventManager().waitUntilEventReaches("streamCreated", 2); @@ -3411,7 +3457,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Publish again the IPCAM response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody, - HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION); + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION); user.getEventManager().waitUntilEventReaches("connectionCreated", 3); user.getEventManager().waitUntilEventReaches("streamCreated", 3); user.getEventManager().waitUntilEventReaches("streamPlaying", 3); @@ -3523,9 +3569,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { checkNodeFetchChanged(true, true); checkNodeFetchChanged(true, false); - Token token = session.createToken(); - // TODO: when using createConnection this below should be false! - Assert.assertTrue("Java fetch should be true", session.fetch()); + Connection connection = session.createConnection(); + Assert.assertFalse("Java fetch should be false", session.fetch()); Assert.assertFalse("Java fetch should be false", OV.fetch()); checkNodeFetchChanged(true, true); checkNodeFetchChanged(true, false); @@ -3550,7 +3595,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Thread.sleep(1000); WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input")); tokeInput.clear(); - tokeInput.sendKeys(token.getToken()); + tokeInput.sendKeys(connection.getToken()); user.getDriver().findElement(By.id("save-btn")).click(); Thread.sleep(1000); user.getDriver().findElement(By.className("join-btn")).click(); From fb393554cb3fa72c310efd33dd6f26df663afa9c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 20 Oct 2020 22:22:09 +0200 Subject: [PATCH 163/435] openvidu-node-client: fix imports --- openvidu-node-client/src/Connection.ts | 2 +- openvidu-node-client/src/ConnectionOptions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 44be496b..020fff07 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -17,7 +17,7 @@ import { Publisher } from './Publisher'; import { ConnectionOptions } from './ConnectionOptions'; -import { OpenViduRole } from 'OpenViduRole'; +import { OpenViduRole } from './OpenViduRole'; /** * See [[Session.connections]] diff --git a/openvidu-node-client/src/ConnectionOptions.ts b/openvidu-node-client/src/ConnectionOptions.ts index 222bc2ec..cc8000a9 100644 --- a/openvidu-node-client/src/ConnectionOptions.ts +++ b/openvidu-node-client/src/ConnectionOptions.ts @@ -15,7 +15,7 @@ * */ -import { ConnectionType } from 'ConnectionType'; +import { ConnectionType } from './ConnectionType'; import { OpenViduRole } from './OpenViduRole'; export interface ConnectionOptions { From 93c86d3efbb7fcffef4f0aa6aeac4948d899574c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 20 Oct 2020 22:23:08 +0200 Subject: [PATCH 164/435] openvidu-testapp: updated to new createConnection API --- .../session-api-dialog.component.html | 4 ++-- .../session-api-dialog.component.ts | 8 ++++---- .../session-properties-dialog.component.html | 14 +++++++------- .../session-properties-dialog.component.ts | 12 ++++++------ .../openvidu-instance.component.ts | 18 +++++++++--------- .../test-apirest/test-apirest.component.ts | 2 +- .../src/app/services/openvidu-rest.service.ts | 2 +- 7 files changed, 30 insertions(+), 30 deletions(-) diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html index a7ef54ed..1d25dcbb 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html @@ -17,10 +17,10 @@
        - Record + Record - + {{ enumerator }} diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts index 2fffa7fd..f1e33974 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout, TokenOptions, OpenViduRole } from 'openvidu-node-client'; +import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout, ConnectionOptions, OpenViduRole } from 'openvidu-node-client'; @Component({ selector: 'app-session-api-dialog', @@ -26,7 +26,7 @@ export class SessionApiDialogComponent { recPropertiesIcon = 'add_circle'; showRecProperties = false; - tokenOptions: TokenOptions = { + connectionOptions: ConnectionOptions = { record: true, role: OpenViduRole.PUBLISHER }; @@ -174,9 +174,9 @@ export class SessionApiDialogComponent { updateConnection() { console.log('Updating connection'); - this.session.updateConnection(this.connectionId, this.tokenOptions) + this.session.updateConnection(this.connectionId, this.connectionOptions) .then(modifiedConnection => { - this.response = 'Connection updated: ' + JSON.stringify({ role: modifiedConnection.role, record: modifiedConnection.record }); + this.response = 'Connection updated: ' + JSON.stringify({ role: modifiedConnection.connectionOptions.role, record: modifiedConnection.connectionOptions.record }); }) .catch(error => { this.response = 'Error [' + error.message + ']'; diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index 98f49ec0..9efe933d 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -68,7 +68,7 @@
        - + SUB PUB MOD @@ -79,19 +79,19 @@
        + [(ngModel)]="connectionOptions.kurentoOptions.videoMaxRecvBandwidth"> + [(ngModel)]="connectionOptions.kurentoOptions.videoMinRecvBandwidth"> + [(ngModel)]="connectionOptions.kurentoOptions.videoMaxSendBandwidth"> + [(ngModel)]="connectionOptions.kurentoOptions.videoMinSendBandwidth">
        - Record + Record
        @@ -132,6 +132,6 @@ + [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, customToken: customToken, forcePublishing: forcePublishing, connectionOptions: generateConnectionOptions()}">SAVE
        diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts index e58d9496..c705c10f 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { SessionProperties, MediaMode, Recording, RecordingMode, RecordingLayout, TokenOptions } from 'openvidu-node-client'; +import { SessionProperties, MediaMode, Recording, RecordingMode, RecordingLayout, ConnectionOptions } from 'openvidu-node-client'; @Component({ selector: 'app-session-properties-dialog', @@ -15,7 +15,7 @@ export class SessionPropertiesDialogComponent { manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; forcePublishing: boolean = false; - tokenOptions: TokenOptions; + connectionOptions: ConnectionOptions; filterName = 'GStreamerFilter'; filters: string[] = []; @@ -32,16 +32,16 @@ export class SessionPropertiesDialogComponent { this.manualTurnConf = data.manualTurnConf; this.customToken = data.customToken; this.forcePublishing = data.forcePublishing; - this.tokenOptions = data.tokenOptions; + this.connectionOptions = data.connectionOptions; } enumToArray(enumerator: any) { return Object.keys(enumerator); } - generateTokenOptions(): TokenOptions { - this.tokenOptions.kurentoOptions.allowedFilters = this.filters; - return this.tokenOptions; + generateConnectionOptions(): ConnectionOptions { + this.connectionOptions.kurentoOptions.allowedFilters = this.filters; + return this.connectionOptions; } } diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 74c9aea9..d5dd064d 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -15,11 +15,11 @@ import { MediaMode, RecordingMode, RecordingLayout, - TokenOptions, + Connection, + ConnectionOptions, OpenViduRole, RecordingProperties, Recording, - Token } from 'openvidu-node-client'; import { MatDialog, MAT_CHECKBOX_CLICK_ACTION } from '@angular/material'; import { ExtensionDialogComponent } from '../dialogs/extension-dialog/extension-dialog.component'; @@ -129,7 +129,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; forcePublishing: boolean; - tokenOptions: TokenOptions = { + connectionOptions: ConnectionOptions = { role: OpenViduRole.PUBLISHER, record: true, kurentoOptions: { @@ -199,8 +199,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { if (!!this.customToken) { this.joinSessionShared(this.customToken); } else { - const token: Token = await this.getToken(); - this.joinSessionShared(token.token); + const connection: Connection = await this.createConnection(); + this.joinSessionShared(connection.token); } } @@ -566,7 +566,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { manualTurnConf: this.manualTurnConf, customToken: this.customToken, forcePublishing: this.forcePublishing, - tokenOptions: this.tokenOptions, + connectionOptions: this.connectionOptions, }, width: '450px' }); @@ -581,7 +581,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.manualTurnConf = result.manualTurnConf; this.customToken = result.customToken; this.forcePublishing = result.forcePublishing; - this.tokenOptions = result.tokenOptions; + this.connectionOptions = result.connectionOptions; } document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused'); }); @@ -692,8 +692,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.sessionAPI = await this.OV_NodeClient.createSession(this.sessionProperties); } - async getToken(): Promise { - return this.sessionAPI.createToken(this.tokenOptions); + async createConnection(): Promise { + return this.sessionAPI.createConnection(this.connectionOptions); } updateEventFromChild(event: OpenViduEvent) { diff --git a/openvidu-testapp/src/app/components/test-apirest/test-apirest.component.ts b/openvidu-testapp/src/app/components/test-apirest/test-apirest.component.ts index b1db644c..d68deb9d 100644 --- a/openvidu-testapp/src/app/components/test-apirest/test-apirest.component.ts +++ b/openvidu-testapp/src/app/components/test-apirest/test-apirest.component.ts @@ -91,7 +91,7 @@ export class TestApirestComponent implements OnInit, OnDestroy { getToken() { const sessionId = this.data[this.selectedRadioIndex][0]; - this.openviduRestService.getToken(this.openviduUrl, this.openviduSecret, sessionId, this.selectedRole, this.serverData) + this.openviduRestService.getToken(sessionId, this.selectedRole, this.serverData) .then((token) => { this.updateData(); }) diff --git a/openvidu-testapp/src/app/services/openvidu-rest.service.ts b/openvidu-testapp/src/app/services/openvidu-rest.service.ts index 50bf7d54..12668741 100644 --- a/openvidu-testapp/src/app/services/openvidu-rest.service.ts +++ b/openvidu-testapp/src/app/services/openvidu-rest.service.ts @@ -29,7 +29,7 @@ export class OpenviduRestService { }); } - getToken(openviduURL: string, openviduSecret: string, sessionId: string, role: string, serverData: string): Promise { + getToken(sessionId: string, role: string, serverData: string): Promise { const session: SessionAPI = this.sessionIdSession.get(sessionId); const OVRole: OpenViduRoleAPI = OpenViduRoleAPI[role]; From b3cc4f296a56f72c7b0e09aaeaba0ff234ff7a06 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 20 Oct 2020 22:41:47 +0200 Subject: [PATCH 165/435] openvidu-node-client: fix Connection comparison --- openvidu-node-client/src/Connection.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 020fff07..4684f4e3 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -213,7 +213,6 @@ export class Connection { this.connectionOptions.data === other.connectionOptions.data && this.connectionOptions.record === other.connectionOptions.record && this.connectionOptions.role === other.connectionOptions.role && - this.connectionOptions.kurentoOptions === other.connectionOptions.kurentoOptions && this.connectionOptions.rtspUri === other.connectionOptions.rtspUri && this.connectionOptions.adaptativeBitrate === other.connectionOptions.adaptativeBitrate && this.connectionOptions.onlyPlayWithSubscribers === other.connectionOptions.onlyPlayWithSubscribers && @@ -224,6 +223,13 @@ export class Connection { this.clientData === other.clientData && this.subscribers.length === other.subscribers.length && this.publishers.length === other.publishers.length); + if (equals) { + if (this.connectionOptions.kurentoOptions != null) { + equals = JSON.stringify(this.connectionOptions.kurentoOptions) === JSON.stringify(other.connectionOptions.kurentoOptions); + } else { + equals = (this.connectionOptions.kurentoOptions === other.connectionOptions.kurentoOptions); + } + } if (equals) { equals = JSON.stringify(this.subscribers) === JSON.stringify(other.subscribers); if (equals) { From 83648d56cdc02852b3df4512a6903488c0079069 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 20 Oct 2020 22:54:54 +0200 Subject: [PATCH 166/435] openvidu-node-client: sort Connection.subscribers array before comparison --- openvidu-node-client/src/Connection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 4684f4e3..513529c0 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -231,7 +231,7 @@ export class Connection { } } if (equals) { - equals = JSON.stringify(this.subscribers) === JSON.stringify(other.subscribers); + equals = JSON.stringify(this.subscribers.sort()) === JSON.stringify(other.subscribers.sort()); if (equals) { let i = 0; while (equals && i < this.publishers.length) { From 2bf1b2cccb248f3c25d2ccb3c0260d0b1f638565 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 21 Oct 2020 11:48:38 +0200 Subject: [PATCH 167/435] openvidu-test-e2e: test Node client Session.createConnection --- .../test/e2e/OpenViduTestAppE2eTest.java | 23 +++++++++++++++++++ .../session-api-dialog.component.html | 5 ++-- .../session-api-dialog.component.ts | 11 +++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index c5cf2af8..160e9b7c 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -3614,6 +3614,29 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { checkNodeFetchChanged(true, false); checkNodeFetchChanged(true, false); + // Create and delete connection with openvidu-node-client + final String successMessage = "Connection created: "; + user.getDriver().findElement(By.id("crate-connection-api-btn")).click(); + user.getWaiter() + .until(ExpectedConditions.attributeContains(By.id("api-response-text-area"), "value", successMessage)); + String value = user.getDriver().findElement(By.id("api-response-text-area")).getAttribute("value"); + String connectionId = value.substring(value.lastIndexOf(successMessage) + successMessage.length()); + Assert.assertTrue("Java fetch should be true", session.fetch()); + Assert.assertFalse("Java fetch should be false", OV.fetch()); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + user.getDriver().findElement(By.id("connection-id-field")).clear(); + user.getDriver().findElement(By.id("connection-id-field")).sendKeys(connectionId); + user.getDriver().findElement(By.id("force-disconnect-api-btn")).click(); + user.getWaiter() + .until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "User disconnected")); + Assert.assertTrue("Java fetch should be true", OV.fetch()); + Assert.assertFalse("Java fetch should be false", session.fetch()); + checkNodeFetchChanged(false, false); + checkNodeFetchChanged(true, false); + checkNodeFetchChanged(false, false); + // RECORD user.getDriver().findElement(By.id("rec-properties-btn")).click(); user.getDriver().findElement(By.id("rec-hasvideo-checkbox")).click(); diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html index 1d25dcbb..60c9ed16 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html @@ -28,10 +28,11 @@
        - + + diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts index f1e33974..a670a596 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts @@ -172,6 +172,17 @@ export class SessionApiDialogComponent { }); } + createConnection() { + console.log('Creating connection'); + this.session.createConnection(this.connectionOptions) + .then(connection => { + this.response = 'Connection created: ' + connection.connectionId; + }) + .catch(error => { + this.response = 'Error [' + error.message + ']'; + }); + } + updateConnection() { console.log('Updating connection'); this.session.updateConnection(this.connectionId, this.connectionOptions) From ab9725bd451e85fc188f95ed12bb2c20eb87112a Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 21 Oct 2020 12:32:54 +0200 Subject: [PATCH 168/435] openvidu-server: Change propertiesSource to protected to be accessible from openvidu-pro config --- .../src/main/java/io/openvidu/server/config/OpenviduConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java index 165d3cd6..31cd4e72 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java +++ b/openvidu-server/src/main/java/io/openvidu/server/config/OpenviduConfig.java @@ -104,7 +104,7 @@ public class OpenviduConfig { private List userConfigProps; - private Map propertiesSource; + protected Map propertiesSource; @Autowired protected Environment env; From c5ae79b3a992fa8f1b29d7e87066abe8df7ee990 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 21 Oct 2020 22:19:01 +0200 Subject: [PATCH 169/435] Rename ConnectionOptions to ConnectionProperties --- .../io/openvidu/java/client/Connection.java | 66 +++++++++---------- ...Options.java => ConnectionProperties.java} | 38 +++++------ .../java/io/openvidu/java/client/Session.java | 50 +++++++------- .../io/openvidu/java/client/TokenOptions.java | 8 +-- openvidu-node-client/src/Connection.ts | 64 +++++++++--------- ...tionOptions.ts => ConnectionProperties.ts} | 6 +- openvidu-node-client/src/Session.ts | 28 ++++---- openvidu-node-client/src/TokenOptions.ts | 2 +- openvidu-node-client/src/index.ts | 2 +- .../io/openvidu/server/core/Participant.java | 25 ++++--- .../openvidu/server/core/SessionManager.java | 8 +-- .../java/io/openvidu/server/core/Token.java | 62 ++++++++--------- .../openvidu/server/core/TokenGenerator.java | 6 +- .../kurento/core/KurentoSessionManager.java | 6 +- .../server/rest/SessionRestController.java | 39 +++++------ .../io/openvidu/server/rpc/RpcHandler.java | 4 +- ...essionGarbageCollectorIntegrationTest.java | 6 +- .../test/e2e/OpenViduProTestAppE2eTest.java | 16 ++--- .../test/e2e/OpenViduTestAppE2eTest.java | 12 ++-- .../session-api-dialog.component.html | 4 +- .../session-api-dialog.component.ts | 10 +-- .../session-properties-dialog.component.html | 14 ++-- .../session-properties-dialog.component.ts | 12 ++-- .../openvidu-instance.component.ts | 10 +-- 24 files changed, 254 insertions(+), 244 deletions(-) rename openvidu-java-client/src/main/java/io/openvidu/java/client/{ConnectionOptions.java => ConnectionProperties.java} (88%) rename openvidu-node-client/src/{ConnectionOptions.ts => ConnectionProperties.ts} (97%) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index 600ef600..ca51e7f5 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -39,7 +39,7 @@ public class Connection { private String location; private String platform; private String clientData; - private ConnectionOptions connectionOptions; + private ConnectionProperties connectionProperties; private String token; protected Map publishers = new ConcurrentHashMap<>(); @@ -95,7 +95,7 @@ public class Connection { * Returns the type of Connection. */ public ConnectionType getType() { - return this.connectionOptions.getType(); + return this.connectionProperties.getType(); } /** @@ -104,7 +104,7 @@ public class Connection { * when calling {@link io.openvidu.java.client.Session#generateToken()} */ public String getServerData() { - return this.connectionOptions.getData(); + return this.connectionProperties.getData(); } /** @@ -114,7 +114,7 @@ public class Connection { * target="_blank">INDIVIDUAL recording. */ public boolean record() { - return this.connectionOptions.record(); + return this.connectionProperties.record(); } /** @@ -126,7 +126,7 @@ public class Connection { * {@link io.openvidu.java.client.ConnectionType#WEBRTC} */ public OpenViduRole getRole() { - return this.connectionOptions.getRole(); + return this.connectionProperties.getRole(); } /** @@ -138,7 +138,7 @@ public class Connection { * {@link io.openvidu.java.client.ConnectionType#IPCAM} */ public String getRtspUri() { - return this.connectionOptions.getRtspUri(); + return this.connectionProperties.getRtspUri(); } /** @@ -154,7 +154,7 @@ public class Connection { * {@link io.openvidu.java.client.ConnectionType#IPCAM} */ public boolean adaptativeBitrate() { - return this.connectionOptions.adaptativeBitrate(); + return this.connectionProperties.adaptativeBitrate(); } /** @@ -170,7 +170,7 @@ public class Connection { * {@link io.openvidu.java.client.ConnectionType#IPCAM} */ public boolean onlyPlayWithSubscribers() { - return this.connectionOptions.onlyPlayWithSubscribers(); + return this.connectionProperties.onlyPlayWithSubscribers(); } /** @@ -186,7 +186,7 @@ public class Connection { * {@link io.openvidu.java.client.ConnectionType#IPCAM} */ public int getNetworkCache() { - return this.connectionOptions.getNetworkCache(); + return this.connectionProperties.getNetworkCache(); } /** @@ -262,11 +262,11 @@ public class Connection { json.addProperty("clientData", this.getClientData()); json.addProperty("token", this.getToken()); - JsonObject jsonConnectionOptions = this.connectionOptions.toJson(""); - jsonConnectionOptions.remove("session"); - json.addProperty("serverData", jsonConnectionOptions.get("data").getAsString()); - jsonConnectionOptions.remove("data"); - jsonConnectionOptions.entrySet().forEach(entry -> { + JsonObject jsonConnectionProperties = this.connectionProperties.toJson(""); + jsonConnectionProperties.remove("session"); + json.addProperty("serverData", jsonConnectionProperties.get("data").getAsString()); + jsonConnectionProperties.remove("data"); + jsonConnectionProperties.entrySet().forEach(entry -> { json.add(entry.getKey(), entry.getValue()); }); @@ -283,33 +283,33 @@ public class Connection { return json; } - protected void overrideConnectionOptions(ConnectionOptions newConnectionOptions) { - ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + protected void overrideConnectionProperties(ConnectionProperties newConnectionProperties) { + ConnectionProperties.Builder builder = new ConnectionProperties.Builder(); // For now only properties role and record can be updated - if (newConnectionOptions.getRole() != null) { - builder.role(newConnectionOptions.getRole()); + if (newConnectionProperties.getRole() != null) { + builder.role(newConnectionProperties.getRole()); } else { - builder.role(this.connectionOptions.getRole()); + builder.role(this.connectionProperties.getRole()); } - if (newConnectionOptions.record() != null) { - builder.record(newConnectionOptions.record()); + if (newConnectionProperties.record() != null) { + builder.record(newConnectionProperties.record()); } else { - builder.record(this.connectionOptions.record()); + builder.record(this.connectionProperties.record()); } // Keep old configuration in the rest of properties - builder.type(this.connectionOptions.getType()).data(this.connectionOptions.getData()) - .kurentoOptions(this.connectionOptions.getKurentoOptions()) - .rtspUri(this.connectionOptions.getRtspUri()); - if (this.connectionOptions.adaptativeBitrate() != null) { - builder.adaptativeBitrate(this.connectionOptions.adaptativeBitrate()); + builder.type(this.connectionProperties.getType()).data(this.connectionProperties.getData()) + .kurentoOptions(this.connectionProperties.getKurentoOptions()) + .rtspUri(this.connectionProperties.getRtspUri()); + if (this.connectionProperties.adaptativeBitrate() != null) { + builder.adaptativeBitrate(this.connectionProperties.adaptativeBitrate()); } - if (this.connectionOptions.onlyPlayWithSubscribers() != null) { - builder.onlyPlayWithSubscribers(this.connectionOptions.onlyPlayWithSubscribers()); + if (this.connectionProperties.onlyPlayWithSubscribers() != null) { + builder.onlyPlayWithSubscribers(this.connectionProperties.onlyPlayWithSubscribers()); } - if (this.connectionOptions.getNetworkCache() != null) { - builder.networkCache(this.connectionOptions.getNetworkCache()); + if (this.connectionProperties.getNetworkCache() != null) { + builder.networkCache(this.connectionProperties.getNetworkCache()); } - this.connectionOptions = builder.build(); + this.connectionProperties = builder.build(); } protected void setSubscribers(List subscribers) { @@ -412,7 +412,7 @@ public class Connection { Integer networkCache = (json.has("networkCache") && !json.get("networkCache").isJsonNull()) ? json.get("networkCache").getAsInt() : null; - this.connectionOptions = new ConnectionOptions(type, data, record, role, null, rtspUri, adaptativeBitrate, + this.connectionProperties = new ConnectionProperties(type, data, record, role, null, rtspUri, adaptativeBitrate, onlyPlayWithSubscribers, networkCache); return this; diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java similarity index 88% rename from openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java rename to openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java index 8fbaea86..f857d415 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java @@ -5,9 +5,9 @@ import com.google.gson.JsonObject; /** * See - * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)} + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)} */ -public class ConnectionOptions { +public class ConnectionProperties { private ConnectionType type; // COMMON @@ -24,7 +24,7 @@ public class ConnectionOptions { /** * - * Builder for {@link io.openvidu.java.client.ConnectionOptions} + * Builder for {@link io.openvidu.java.client.ConnectionProperties} * */ public static class Builder { @@ -43,10 +43,10 @@ public class ConnectionOptions { private Integer networkCache; /** - * Builder for {@link io.openvidu.java.client.ConnectionOptions}. + * Builder for {@link io.openvidu.java.client.ConnectionProperties}. */ - public ConnectionOptions build() { - return new ConnectionOptions(this.type, this.data, this.record, this.role, this.kurentoOptions, + public ConnectionProperties build() { + return new ConnectionProperties(this.type, this.data, this.record, this.role, this.kurentoOptions, this.rtspUri, this.adaptativeBitrate, this.onlyPlayWithSubscribers, this.networkCache); } @@ -56,24 +56,24 @@ public class ConnectionOptions { * have effect: *
          *
        • {@link io.openvidu.java.client.ConnectionType#WEBRTC}: - * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean) * record}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole) * role}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#kurentoOptions(KurentoOptions) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#kurentoOptions(KurentoOptions) * kurentoOptions}
        • *
        • {@link io.openvidu.java.client.ConnectionType#IPCAM}: - * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean) * record}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#rtspUri(String) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#rtspUri(String) * rtspUri}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#adaptativeBitrate(boolean) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#adaptativeBitrate(boolean) * adaptativeBitrate}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#onlyPlayWithSubscribers(boolean) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#onlyPlayWithSubscribers(boolean) * onlyPlayWithSubscribers}, - * {@link io.openvidu.java.client.ConnectionOptions.Builder#networkCache(int) + * {@link io.openvidu.java.client.ConnectionProperties.Builder#networkCache(int) * networkCache}
        • *
        * If not set by default will be @link @@ -94,7 +94,7 @@ public class ConnectionOptions { *
      • If you have provided no data in your clients when calling method * Session.connect(TOKEN, DATA) (DATA not defined), * then Connection.data will only have this - * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)} + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)} * property.
      • *
      • If you have provided some data when calling * Session.connect(TOKEN, DATA) (DATA defined), then @@ -102,7 +102,7 @@ public class ConnectionOptions { * "CLIENT_DATA%/%SERVER_DATA", being * CLIENT_DATA the second parameter passed in OpenVidu Browser in * method Session.connect and SERVER_DATA this - * {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)} + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String)} * property.
      • *
      */ @@ -219,7 +219,7 @@ public class ConnectionOptions { } } - ConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role, + ConnectionProperties(ConnectionType type, String data, Boolean record, OpenViduRole role, KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers, Integer networkCache) { this.type = type; diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index 9c54f6a7..b45e9e4f 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -105,8 +105,8 @@ public class Session { /** * @deprecated Use - * {@link Session#createConnection(io.openvidu.java.client.ConnectionOptions) - * Session.createConnection(ConnectionOptions)} instead to get a + * {@link Session#createConnection(io.openvidu.java.client.ConnectionProperties) + * Session.createConnection(ConnectionProperties)} instead to get a * {@link io.openvidu.java.client.Connection} object. * * @return The generated token String @@ -155,8 +155,8 @@ public class Session { /** * Same as - * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) - * but with default ConnectionOptions values. + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties) + * but with default ConnectionProperties values. * * @return The generated {@link io.openvidu.java.client.Connection Connection} * object. @@ -166,12 +166,12 @@ public class Session { */ public Connection createConnection() throws OpenViduJavaClientException, OpenViduHttpException { return createConnection( - new ConnectionOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); + new ConnectionProperties.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); } /** * Creates a new Connection object associated to Session object and configured - * with connectionOptions. Each user connecting to the Session + * with connectionProperties. Each user connecting to the Session * requires a Connection. The token string value to send to the client side can * be retrieved with {@link io.openvidu.java.client.Connection#getToken() * Connection.getToken()}. @@ -182,7 +182,7 @@ public class Session { * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ - public Connection createConnection(ConnectionOptions connectionOptions) + public Connection createConnection(ConnectionProperties connectionProperties) throws OpenViduJavaClientException, OpenViduHttpException { if (!this.hasSessionId()) { this.getSessionId(); @@ -193,7 +193,7 @@ public class Session { StringEntity params; try { - params = new StringEntity(connectionOptions.toJson(sessionId).toString()); + params = new StringEntity(connectionProperties.toJson(sessionId).toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } @@ -261,7 +261,7 @@ public class Session { * those values to call * {@link io.openvidu.java.client.Session#forceDisconnect(Connection)}, * {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or - * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)}.
      + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)}.
      *
      * * To update all Session objects owned by OpenVidu object at once, call @@ -338,7 +338,7 @@ public class Session { /** * Same as {@link io.openvidu.java.client.Session#forceDisconnect(Connection) - * forceDisconnect(ConnectionOptions)} but providing the + * forceDisconnect(ConnectionProperties)} but providing the * {@link io.openvidu.java.client.Connection#getConnectionId() connectionId} * instead of the Connection object. * @@ -464,13 +464,13 @@ public class Session { /** * Updates the properties of a Connection with a - * {@link io.openvidu.java.client.ConnectionOptions} object. Only these + * {@link io.openvidu.java.client.ConnectionProperties} object. Only these * properties can be updated: *
        - *
      • {@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole) - * ConnectionOptions.Builder.role(OpenViduRole)}
      • - *
      • {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean) - * ConnectionOptions.Builder.record(boolean)}
      • + *
      • {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole) + * ConnectionProperties.Builder.role(OpenViduRole)}
      • + *
      • {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean) + * ConnectionProperties.Builder.record(boolean)}
      • *
      *
      * @@ -482,7 +482,7 @@ public class Session { * objects. * * @param connectionId The Connection to modify - * @param connectionOptions A ConnectionOptions object with the new values to + * @param connectionProperties A ConnectionProperties object with the new values to * apply * * @return The updated {@link io.openvidu.java.client.Connection Connection} @@ -491,7 +491,7 @@ public class Session { * @throws OpenViduJavaClientException * @throws OpenViduHttpException */ - public Connection updateConnection(String connectionId, ConnectionOptions connectionOptions) + public Connection updateConnection(String connectionId, ConnectionProperties connectionProperties) throws OpenViduJavaClientException, OpenViduHttpException { HttpPatch request = new HttpPatch( @@ -499,7 +499,7 @@ public class Session { StringEntity params; try { - params = new StringEntity(connectionOptions.toJson(this.sessionId).toString()); + params = new StringEntity(connectionProperties.toJson(this.sessionId).toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } @@ -534,7 +534,7 @@ public class Session { return newConnection; } else { // The updated Connection was available in local map - existingConnection.overrideConnectionOptions(connectionOptions); + existingConnection.overrideConnectionProperties(connectionProperties); return existingConnection; } @@ -572,15 +572,15 @@ public class Session { * called. Exceptions to this rule are: *
        *
      • Calling - * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) - * createConnection(ConnectionOptions)} automatically adds the new Connection + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties) + * createConnection(ConnectionProperties)} automatically adds the new Connection * object to the local collection.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} * automatically updates each affected local Connection object.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} * automatically updates each affected local Connection object.
      • *
      • Calling - * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)} + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)} * automatically updates the attributes of the affected local Connection * object.
      • *
      @@ -604,15 +604,15 @@ public class Session { * called. Exceptions to this rule are: *
        *
      • Calling - * {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions) - * createConnection(ConnectionOptions)} automatically adds the new Connection + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties) + * createConnection(ConnectionProperties)} automatically adds the new Connection * object to the local collection.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} * automatically updates each affected local Connection object.
      • *
      • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} * automatically updates each affected local Connection object.
      • *
      • Calling - * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)} + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)} * automatically updates the attributes of the affected local Connection * object.
      • *
      diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java index f450399b..ab3f1ffe 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java @@ -21,8 +21,8 @@ import com.google.gson.JsonNull; import com.google.gson.JsonObject; /** - * @deprecated Use {@link io.openvidu.java.client.ConnectionOptions - * ConnectionOptions} instead + * @deprecated Use {@link io.openvidu.java.client.ConnectionProperties + * ConnectionProperties} instead */ public class TokenOptions { @@ -32,8 +32,8 @@ public class TokenOptions { private KurentoOptions kurentoOptions; /** - * @deprecated Use {@link io.openvidu.java.client.ConnectionOptions.Builder - * ConnectionOptions.Builder} instead + * @deprecated Use {@link io.openvidu.java.client.ConnectionProperties.Builder + * ConnectionProperties.Builder} instead */ public static class Builder { diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 513529c0..3507fe72b 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -16,7 +16,7 @@ */ import { Publisher } from './Publisher'; -import { ConnectionOptions } from './ConnectionOptions'; +import { ConnectionProperties } from './ConnectionProperties'; import { OpenViduRole } from './OpenViduRole'; /** @@ -71,9 +71,9 @@ export class Connection { clientData: string; /** - * The [[ConnectionOptions]] assigned to the Connection + * The [[ConnectionProperties]] assigned to the Connection */ - connectionOptions: ConnectionOptions; + connectionProperties: ConnectionProperties; /** * Token associated to the Connection @@ -93,11 +93,11 @@ export class Connection { subscribers: string[] = []; /** - * @hidden deprecated. Inside ConnectionOptions + * @hidden deprecated. Inside ConnectionProperties */ role?: OpenViduRole; /** - * @hidden deprecated. Inside ConnectionOptions + * @hidden deprecated. Inside ConnectionProperties */ serverData?: string; @@ -121,18 +121,18 @@ export class Connection { this.platform = json.platform; this.clientData = json.clientData; this.token = json.token; - if (this.connectionOptions != null) { - this.connectionOptions.type = json.type; - this.connectionOptions.data = json.data; - this.connectionOptions.record = json.record; - this.connectionOptions.role = json.role; - this.connectionOptions.kurentoOptions = json.kurentoOptions; - this.connectionOptions.rtspUri = json.rtspUri; - this.connectionOptions.adaptativeBitrate = json.adaptativeBitrate; - this.connectionOptions.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers; - this.connectionOptions.networkCache = json.networkCache; + if (this.connectionProperties != null) { + this.connectionProperties.type = json.type; + this.connectionProperties.data = json.data; + this.connectionProperties.record = json.record; + this.connectionProperties.role = json.role; + this.connectionProperties.kurentoOptions = json.kurentoOptions; + this.connectionProperties.rtspUri = json.rtspUri; + this.connectionProperties.adaptativeBitrate = json.adaptativeBitrate; + this.connectionProperties.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers; + this.connectionProperties.networkCache = json.networkCache; } else { - this.connectionOptions = { + this.connectionProperties = { type: json.type, data: json.data, record: json.record, @@ -209,14 +209,14 @@ export class Connection { this.status === other.status && this.createdAt === other.createdAt && this.activeAt === other.activeAt && - this.connectionOptions.type === other.connectionOptions.type && - this.connectionOptions.data === other.connectionOptions.data && - this.connectionOptions.record === other.connectionOptions.record && - this.connectionOptions.role === other.connectionOptions.role && - this.connectionOptions.rtspUri === other.connectionOptions.rtspUri && - this.connectionOptions.adaptativeBitrate === other.connectionOptions.adaptativeBitrate && - this.connectionOptions.onlyPlayWithSubscribers === other.connectionOptions.onlyPlayWithSubscribers && - this.connectionOptions.networkCache === other.connectionOptions.networkCache && + this.connectionProperties.type === other.connectionProperties.type && + this.connectionProperties.data === other.connectionProperties.data && + this.connectionProperties.record === other.connectionProperties.record && + this.connectionProperties.role === other.connectionProperties.role && + this.connectionProperties.rtspUri === other.connectionProperties.rtspUri && + this.connectionProperties.adaptativeBitrate === other.connectionProperties.adaptativeBitrate && + this.connectionProperties.onlyPlayWithSubscribers === other.connectionProperties.onlyPlayWithSubscribers && + this.connectionProperties.networkCache === other.connectionProperties.networkCache && this.token === other.token && this.location === other.location && this.platform === other.platform && @@ -224,10 +224,10 @@ export class Connection { this.subscribers.length === other.subscribers.length && this.publishers.length === other.publishers.length); if (equals) { - if (this.connectionOptions.kurentoOptions != null) { - equals = JSON.stringify(this.connectionOptions.kurentoOptions) === JSON.stringify(other.connectionOptions.kurentoOptions); + if (this.connectionProperties.kurentoOptions != null) { + equals = JSON.stringify(this.connectionProperties.kurentoOptions) === JSON.stringify(other.connectionProperties.kurentoOptions); } else { - equals = (this.connectionOptions.kurentoOptions === other.connectionOptions.kurentoOptions); + equals = (this.connectionProperties.kurentoOptions === other.connectionProperties.kurentoOptions); } } if (equals) { @@ -250,13 +250,13 @@ export class Connection { /** * @hidden */ - overrideConnectionOptions(newConnectionOptions: ConnectionOptions): void { + overrideConnectionProperties(newConnectionProperties: ConnectionProperties): void { // For now only properties record and role - if (newConnectionOptions.record != null) { - this.connectionOptions.record = newConnectionOptions.record; + if (newConnectionProperties.record != null) { + this.connectionProperties.record = newConnectionProperties.record; } - if (newConnectionOptions.role != null) { - this.connectionOptions.role = newConnectionOptions.role; + if (newConnectionProperties.role != null) { + this.connectionProperties.role = newConnectionProperties.role; } } diff --git a/openvidu-node-client/src/ConnectionOptions.ts b/openvidu-node-client/src/ConnectionProperties.ts similarity index 97% rename from openvidu-node-client/src/ConnectionOptions.ts rename to openvidu-node-client/src/ConnectionProperties.ts index cc8000a9..8ba7f518 100644 --- a/openvidu-node-client/src/ConnectionOptions.ts +++ b/openvidu-node-client/src/ConnectionProperties.ts @@ -18,7 +18,7 @@ import { ConnectionType } from './ConnectionType'; import { OpenViduRole } from './OpenViduRole'; -export interface ConnectionOptions { +export interface ConnectionProperties { /** * Type of Connection. The [[ConnectionType]] dictates what properties will have effect: @@ -32,9 +32,9 @@ export interface ConnectionOptions { /** * Secure (server-side) data associated to this Connection. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object. - * - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[ConnectionOptions.data]] property. + * - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[ConnectionProperties.data]] property. * - If you have provided some data when calling `Session.connect(TOKEN, DATA)` (`DATA` defined), then `Connection.data` will have the following structure: `"CLIENT_DATA%/%SERVER_DATA"`, being `CLIENT_DATA` the second - * parameter passed in OpenVidu Browser in method `Session.connect` and `SERVER_DATA` this [[ConnectionOptions.data]] property. + * parameter passed in OpenVidu Browser in method `Session.connect` and `SERVER_DATA` this [[ConnectionProperties.data]] property. */ data?: string; diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 9cb41354..f1333182 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -17,7 +17,7 @@ import axios, { AxiosError } from 'axios'; import { Connection } from './Connection'; -import { ConnectionOptions } from './ConnectionOptions'; +import { ConnectionProperties } from './ConnectionProperties'; import { MediaMode } from './MediaMode'; import { OpenVidu } from './OpenVidu'; import { Publisher } from './Publisher'; @@ -143,18 +143,18 @@ export class Session { /** * Creates a new Connection object associated to Session object and configured with - * `connectionOptions`. Each user connecting to the Session requires a Connection. + * `connectionProperties`. Each user connecting to the Session requires a Connection. * The token string value to send to the client side is available at [[Connection.token]]. * * @returns A Promise that is resolved to the generated [[Connection]] object if success and rejected with an Error object if not */ - public createConnection(connectionOptions?: ConnectionOptions): Promise { + public createConnection(connectionProperties?: ConnectionProperties): Promise { return new Promise((resolve, reject) => { const data = JSON.stringify({ - role: (!!connectionOptions && !!connectionOptions.role) ? connectionOptions.role : null, - data: (!!connectionOptions && !!connectionOptions.data) ? connectionOptions.data : null, - record: !!connectionOptions ? connectionOptions.record : null, - kurentoOptions: (!!connectionOptions && !!connectionOptions.kurentoOptions) ? connectionOptions.kurentoOptions : null + role: (!!connectionProperties && !!connectionProperties.role) ? connectionProperties.role : null, + data: (!!connectionProperties && !!connectionProperties.data) ? connectionProperties.data : null, + record: !!connectionProperties ? connectionProperties.record : null, + kurentoOptions: (!!connectionProperties && !!connectionProperties.kurentoOptions) ? connectionProperties.kurentoOptions : null }); axios.post( this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection', @@ -390,26 +390,26 @@ export class Session { } /** - * Updates the properties of a Connection with a [[ConnectionOptions]] object. + * Updates the properties of a Connection with a [[ConnectionProperties]] object. * Only these properties can be updated: * - * - [[ConnectionOptions.role]] - * - [[ConnectionOptions.record]] + * - [[ConnectionProperties.role]] + * - [[ConnectionProperties.record]] * * This method automatically updates the properties of the local affected objects. This means that there is no need to call * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @param connectionId The [[Connection.connectionId]] of the Connection object to modify - * @param connectionOptions A new [[ConnectionOptions]] object with the updated values to apply + * @param connectionProperties A new [[ConnectionProperties]] object with the updated values to apply * * @returns A Promise that is resolved to the updated [[Connection]] object if the operation was * successful and rejected with an Error object if not */ - public updateConnection(connectionId: string, connectionOptions: ConnectionOptions): Promise { + public updateConnection(connectionId: string, connectionProperties: ConnectionProperties): Promise { return new Promise((resolve, reject) => { axios.patch( this.ov.host + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId, - connectionOptions, + connectionProperties, { headers: { 'Authorization': this.ov.basicAuth, @@ -437,7 +437,7 @@ export class Session { resolve(newConnection); } else { // The updated Connection was available in local map - existingConnection.overrideConnectionOptions(connectionOptions); + existingConnection.overrideConnectionProperties(connectionProperties); this.updateActiveConnectionsArray(); resolve(existingConnection); } diff --git a/openvidu-node-client/src/TokenOptions.ts b/openvidu-node-client/src/TokenOptions.ts index cd4d947a..5a454cfe 100644 --- a/openvidu-node-client/src/TokenOptions.ts +++ b/openvidu-node-client/src/TokenOptions.ts @@ -18,7 +18,7 @@ import { OpenViduRole } from './OpenViduRole'; /** - * @deprecated Use [[ConnectionOptions]] instead + * @deprecated Use [[ConnectionProperties]] instead */ export interface TokenOptions { diff --git a/openvidu-node-client/src/index.ts b/openvidu-node-client/src/index.ts index a0887a7c..0878ad05 100644 --- a/openvidu-node-client/src/index.ts +++ b/openvidu-node-client/src/index.ts @@ -3,7 +3,7 @@ export * from './OpenViduRole'; export * from './Session'; export * from './SessionProperties'; export * from './TokenOptions'; -export * from './ConnectionOptions'; +export * from './ConnectionProperties'; export * from './ConnectionType'; export * from './MediaMode'; export * from './RecordingLayout'; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java index 20c62e00..312bc874 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Participant.java @@ -218,11 +218,20 @@ public class Participant { } public String getFullMetadata() { - String fullMetadata; - if ((!this.clientMetadata.isEmpty()) && (!this.token.getServerMetadata().isEmpty())) { - fullMetadata = this.clientMetadata + METADATA_SEPARATOR + this.token.getServerMetadata(); - } else { - fullMetadata = this.clientMetadata + this.token.getServerMetadata(); + String fullMetadata = ""; + if (this.clientMetadata != null && !this.clientMetadata.isEmpty()) { + // Client data defined + fullMetadata += this.clientMetadata; + } + if (this.token.getServerMetadata() != null && !this.token.getServerMetadata().isEmpty()) { + // Server data defined + if (fullMetadata.isEmpty()) { + // Only server data + fullMetadata += this.token.getServerMetadata(); + } else { + // Both client data and server data + fullMetadata += METADATA_SEPARATOR + this.token.getServerMetadata(); + } } return fullMetadata; } @@ -305,9 +314,9 @@ public class Participant { } else { json.add("token", null); } - // Add all ConnectionOptions - JsonObject connectionOptionsJson = this.token.getConnectionOptionsWithFinalJsonFormat(); - connectionOptionsJson.entrySet().forEach(entry -> { + // Add all ConnectionProperties + JsonObject connectionPropertiesJson = this.token.getConnectionPropertiesWithFinalJsonFormat(); + connectionPropertiesJson.entrySet().forEach(entry -> { json.add(entry.getKey(), entry.getValue()); }); json.addProperty("clientData", this.clientMetadata); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 9ac14df5..f1a99125 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -45,7 +45,7 @@ import com.google.gson.JsonSyntaxException; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; @@ -162,7 +162,7 @@ public abstract class SessionManager { String eventType); public abstract Participant publishIpcam(Session session, MediaOptions mediaOptions, - ConnectionOptions connectionOptions) throws Exception; + ConnectionProperties connectionProperties) throws Exception; public abstract void reconnectStream(Participant participant, String streamId, String sdpOffer, Integer transactionId); @@ -314,9 +314,9 @@ public abstract class SessionManager { return tokenObj; } - public Token newTokenForInsecureUser(Session session, String token, ConnectionOptions connectionOptions) + public Token newTokenForInsecureUser(Session session, String token, ConnectionProperties connectionProperties) throws Exception { - Token tokenObj = new Token(token, session.getSessionId(), connectionOptions, + Token tokenObj = new Token(token, session.getSessionId(), connectionProperties, this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null); session.storeToken(tokenObj); session.showTokens("Token created for insecure user"); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index ebb19202..2529badd 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -21,7 +21,7 @@ import org.apache.commons.lang3.RandomStringUtils; import com.google.gson.JsonObject; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; @@ -33,22 +33,22 @@ public class Token { private String token; private String sessionId; private Long createdAt; - private ConnectionOptions connectionOptions; + private ConnectionProperties connectionProperties; private TurnCredentials turnCredentials; private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); - public Token(String token, String sessionId, ConnectionOptions connectionOptions, TurnCredentials turnCredentials) { + public Token(String token, String sessionId, ConnectionProperties connectionProperties, TurnCredentials turnCredentials) { this.token = token; this.sessionId = sessionId; this.createdAt = System.currentTimeMillis(); - this.connectionOptions = connectionOptions; + this.connectionProperties = connectionProperties; this.turnCredentials = turnCredentials; } public ConnectionType getType() { - return this.connectionOptions.getType(); + return this.connectionProperties.getType(); } public String getToken() { @@ -64,49 +64,49 @@ public class Token { } public String getServerMetadata() { - return this.connectionOptions.getData(); + return this.connectionProperties.getData(); } public boolean record() { - return this.connectionOptions.record(); + return this.connectionProperties.record(); } public void setRecord(boolean newRecord) { - this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(), newRecord, - connectionOptions.getRole(), connectionOptions.getKurentoOptions(), connectionOptions.getRtspUri(), - connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(), - connectionOptions.getNetworkCache()); + this.updateConnectionProperties(connectionProperties.getType(), connectionProperties.getData(), newRecord, + connectionProperties.getRole(), connectionProperties.getKurentoOptions(), connectionProperties.getRtspUri(), + connectionProperties.adaptativeBitrate(), connectionProperties.onlyPlayWithSubscribers(), + connectionProperties.getNetworkCache()); } public OpenViduRole getRole() { - return this.connectionOptions.getRole(); + return this.connectionProperties.getRole(); } public void setRole(OpenViduRole newRole) { - this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(), - connectionOptions.record(), newRole, connectionOptions.getKurentoOptions(), - connectionOptions.getRtspUri(), connectionOptions.adaptativeBitrate(), - connectionOptions.onlyPlayWithSubscribers(), connectionOptions.getNetworkCache()); + this.updateConnectionProperties(connectionProperties.getType(), connectionProperties.getData(), + connectionProperties.record(), newRole, connectionProperties.getKurentoOptions(), + connectionProperties.getRtspUri(), connectionProperties.adaptativeBitrate(), + connectionProperties.onlyPlayWithSubscribers(), connectionProperties.getNetworkCache()); } public KurentoOptions getKurentoOptions() { - return this.connectionOptions.getKurentoOptions(); + return this.connectionProperties.getKurentoOptions(); } public String getRtspUri() { - return this.connectionOptions.getRtspUri(); + return this.connectionProperties.getRtspUri(); } public Boolean adaptativeBitrate() { - return this.connectionOptions.adaptativeBitrate(); + return this.connectionProperties.adaptativeBitrate(); } public Boolean onlyPlayWithSubscribers() { - return this.connectionOptions.onlyPlayWithSubscribers(); + return this.connectionProperties.onlyPlayWithSubscribers(); } public Integer getNetworkCache() { - return this.connectionOptions.getNetworkCache(); + return this.connectionProperties.getNetworkCache(); } public TurnCredentials getTurnCredentials() { @@ -141,9 +141,9 @@ public class Token { json.addProperty("sessionId", this.sessionId); json.addProperty("createdAt", this.createdAt); - // Add all ConnectionOptions - JsonObject connectionOptionsJson = this.getConnectionOptionsWithFinalJsonFormat(); - connectionOptionsJson.entrySet().forEach(entry -> { + // Add all ConnectionProperties + JsonObject connectionPropertiesJson = this.getConnectionPropertiesWithFinalJsonFormat(); + connectionPropertiesJson.entrySet().forEach(entry -> { json.add(entry.getKey(), entry.getValue()); }); @@ -157,18 +157,18 @@ public class Token { return json; } - protected JsonObject getConnectionOptionsWithFinalJsonFormat() { - JsonObject json = this.connectionOptions.toJson(this.sessionId); + protected JsonObject getConnectionPropertiesWithFinalJsonFormat() { + JsonObject json = this.connectionProperties.toJson(this.sessionId); json.remove("session"); json.addProperty("serverData", json.get("data").getAsString()); json.remove("data"); return json; } - private void updateConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role, + private void updateConnectionProperties(ConnectionType type, String data, Boolean record, OpenViduRole role, KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers, Integer networkCache) { - ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + ConnectionProperties.Builder builder = new ConnectionProperties.Builder(); if (type != null) { builder.type(type); } @@ -196,13 +196,13 @@ public class Token { if (networkCache != null) { builder.networkCache(networkCache); } - this.connectionOptions = builder.build(); + this.connectionProperties = builder.build(); } @Override public String toString() { - if (this.connectionOptions.getRole() != null) - return this.connectionOptions.getRole().name(); + if (this.connectionProperties.getRole() != null) + return this.connectionProperties.getRole().name(); else return this.token; } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index ed5b6966..7e3c70c2 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -20,7 +20,7 @@ package io.openvidu.server.core; import org.apache.commons.lang3.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; @@ -58,8 +58,8 @@ public class TokenGenerator { token += "&turnCredential=" + turnCredentials.getCredential(); } } - ConnectionOptions connectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC) + ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); - return new Token(token, sessionId, connectionOptions, turnCredentials); + return new Token(token, sessionId, connectionProperties, turnCredentials); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index c9ba06a5..fc078a1d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -48,7 +48,7 @@ import com.google.gson.JsonObject; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; import io.openvidu.java.client.Recording; @@ -992,7 +992,7 @@ public class KurentoSessionManager extends SessionManager { @Override /* Protected by Session.closingLock.readLock */ - public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionOptions connectionOptions) + public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionProperties connectionProperties) throws Exception { final String sessionId = session.getSessionId(); final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions; @@ -1035,7 +1035,7 @@ public class KurentoSessionManager extends SessionManager { String token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - this.newTokenForInsecureUser(session, token, connectionOptions); + this.newTokenForInsecureUser(session, token, connectionProperties); final Token tokenObj = session.consumeToken(token); Participant ipcamParticipant = this.newIpcamParticipant(sessionId, rtspConnectionId, tokenObj, location, diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 7f981f57..7fc10a6b 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -50,7 +50,7 @@ import com.google.gson.JsonParser; import io.openvidu.client.OpenViduException; import io.openvidu.client.internal.ProtocolElements; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; @@ -282,18 +282,18 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - ConnectionOptions connectionOptions; + ConnectionProperties connectionProperties; try { - connectionOptions = getConnectionOptionsFromParams(params); + connectionProperties = getConnectionPropertiesFromParams(params); } catch (Exception e) { return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } - switch (connectionOptions.getType()) { + switch (connectionProperties.getType()) { case WEBRTC: - return this.newWebrtcConnection(session, connectionOptions); + return this.newWebrtcConnection(session, connectionProperties); case IPCAM: - return this.newIpcamConnection(session, connectionOptions); + return this.newIpcamConnection(session, connectionProperties); default: return this.generateErrorResponse("Wrong type parameter", "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); @@ -657,14 +657,15 @@ public class SessionRestController { return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND); } - ConnectionOptions connectionOptions; + ConnectionProperties connectionProperties; + params.remove("record"); try { - connectionOptions = getConnectionOptionsFromParams(params); + connectionProperties = getConnectionPropertiesFromParams(params); } catch (Exception e) { return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); } - ResponseEntity entity = this.newWebrtcConnection(session, connectionOptions); + ResponseEntity entity = this.newWebrtcConnection(session, connectionProperties); JsonObject jsonResponse = JsonParser.parseString(entity.getBody().toString()).getAsJsonObject(); if (jsonResponse.has("error")) { @@ -779,15 +780,15 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.OK); } - protected ResponseEntity newWebrtcConnection(Session session, ConnectionOptions connectionOptions) { + protected ResponseEntity newWebrtcConnection(Session session, ConnectionProperties connectionProperties) { final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection"; // While closing a session tokens can't be generated if (session.closingLock.readLock().tryLock()) { try { - Token token = sessionManager.newToken(session, connectionOptions.getRole(), connectionOptions.getData(), - connectionOptions.record(), connectionOptions.getKurentoOptions()); + Token token = sessionManager.newToken(session, connectionProperties.getRole(), connectionProperties.getData(), + connectionProperties.record(), connectionProperties.getKurentoOptions()); return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (Exception e) { @@ -805,7 +806,7 @@ public class SessionRestController { } } - protected ResponseEntity newIpcamConnection(Session session, ConnectionOptions connectionOptions) { + protected ResponseEntity newIpcamConnection(Session session, ConnectionProperties connectionProperties) { final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection"; @@ -817,9 +818,9 @@ public class SessionRestController { Integer frameRate = null; String videoDimensions = null; KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive, - videoActive, typeOfVideo, frameRate, videoDimensions, null, false, connectionOptions.getRtspUri(), - connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(), - connectionOptions.getNetworkCache()); + videoActive, typeOfVideo, frameRate, videoDimensions, null, false, connectionProperties.getRtspUri(), + connectionProperties.adaptativeBitrate(), connectionProperties.onlyPlayWithSubscribers(), + connectionProperties.getNetworkCache()); // While closing a session IP cameras can't be published if (session.closingLock.readLock().tryLock()) { @@ -828,7 +829,7 @@ public class SessionRestController { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, - connectionOptions); + connectionProperties); return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (MalformedURLException e) { @@ -857,9 +858,9 @@ public class SessionRestController { return token; } - protected ConnectionOptions getConnectionOptionsFromParams(Map params) throws Exception { + protected ConnectionProperties getConnectionPropertiesFromParams(Map params) throws Exception { - ConnectionOptions.Builder builder = new ConnectionOptions.Builder(); + ConnectionProperties.Builder builder = new ConnectionProperties.Builder(); String typeString; String data; diff --git a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java index c50ca993..2d017b58 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rpc/RpcHandler.java @@ -45,7 +45,7 @@ import com.google.gson.JsonSyntaxException; import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.core.EndReason; import io.openvidu.server.core.IdentifierPrefixes; @@ -249,7 +249,7 @@ public class RpcHandler extends DefaultJsonRpcHandler { token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); try { - sessionManager.newTokenForInsecureUser(session, token, new ConnectionOptions.Builder().build()); + sessionManager.newTokenForInsecureUser(session, token, new ConnectionProperties.Builder().build()); } catch (Exception e) { throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE, "Unable to create token for session " + sessionId + ": " + e.getMessage()); diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index ddb56819..9bb5d109 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -36,7 +36,7 @@ import org.springframework.test.context.web.WebAppConfiguration; import com.google.gson.Gson; import com.google.gson.JsonObject; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.server.core.Participant; import io.openvidu.server.core.SessionManager; import io.openvidu.server.core.Token; @@ -115,8 +115,8 @@ public class SessionGarbageCollectorIntegrationTest { } private void joinParticipant(String sessionId, String token) { - ConnectionOptions connectionOptions = new ConnectionOptions.Builder().data("SERVER_METADATA").build(); - Token t = new Token(token, sessionId, connectionOptions, null); + ConnectionProperties connectionProperties = new ConnectionProperties.Builder().data("SERVER_METADATA").build(); + Token t = new Token(token, sessionId, connectionProperties, null); String uuid = UUID.randomUUID().toString(); String participantPrivateId = "PARTICIPANT_PRIVATE_ID_" + uuid; String finalUserId = "FINAL_USER_ID_" + uuid; diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 43b4da49..cd956268 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -25,7 +25,7 @@ import com.google.gson.stream.JsonReader; import com.mashape.unirest.http.HttpMethod; import io.openvidu.java.client.Connection; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.OpenVidu; import io.openvidu.java.client.OpenViduHttpException; import io.openvidu.java.client.OpenViduRole; @@ -230,14 +230,14 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertTrue("OpenVidu object should have changed", OV.fetch()); Session session = OV.getActiveSessions().get(0); try { - session.updateConnection("WRONG_CONNECTION_ID", new ConnectionOptions.Builder().build()); + session.updateConnection("WRONG_CONNECTION_ID", new ConnectionProperties.Builder().build()); Assert.fail("Expected OpenViduHttpException exception"); } catch (OpenViduHttpException exception) { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } Assert.assertFalse("Session object should not have changed", session.fetch()); Connection connection = session.updateConnection(tokenConnectionId, - new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); + new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); Assert.assertEquals("Wrong role Connection property", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Wrong record Connection property", connection.record()); @@ -339,25 +339,25 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Test with openvidu-java-client Assert.assertFalse("Session object should not have changed", session.fetch()); try { - session.updateConnection("WRONG_CONNECTION_ID", new ConnectionOptions.Builder().build()); + session.updateConnection("WRONG_CONNECTION_ID", new ConnectionProperties.Builder().build()); Assert.fail("Expected OpenViduHttpException exception"); } catch (OpenViduHttpException exception) { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } Assert.assertFalse("Session object should not have changed", session.fetch()); connection = session.updateConnection(tokenConnectionId, - new ConnectionOptions.Builder().role(OpenViduRole.PUBLISHER).build()); + new ConnectionProperties.Builder().role(OpenViduRole.PUBLISHER).build()); Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); connection = session.updateConnection(tokenConnectionId, - new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).build()); + new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).build()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Session object should not have changed", session.fetch()); connection = session.updateConnection(tokenConnectionId, - new ConnectionOptions.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + new ConnectionProperties.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); @@ -411,7 +411,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertTrue("Wrong record property", connection.record()); session.updateConnection(connection.getConnectionId(), - new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); + new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); Assert.assertEquals("Wrong role property", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Wrong record property", connection.record()); Assert.assertFalse(session.fetch()); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 160e9b7c..06455ddc 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -54,7 +54,7 @@ import com.google.gson.JsonParser; import com.mashape.unirest.http.HttpMethod; import io.openvidu.java.client.Connection; -import io.openvidu.java.client.ConnectionOptions; +import io.openvidu.java.client.ConnectionProperties; import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.MediaMode; @@ -2138,13 +2138,13 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { KurentoOptions kurentoOptions = new KurentoOptions.Builder().videoMaxRecvBandwidth(250) .allowedFilters(new String[] { "GStreamerFilter" }).build(); - ConnectionOptions moderatorConnectionOptions = new ConnectionOptions.Builder().role(OpenViduRole.MODERATOR) + ConnectionProperties moderatorConnectionProperties = new ConnectionProperties.Builder().role(OpenViduRole.MODERATOR) .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); - Connection connectionModerator = session.createConnection(moderatorConnectionOptions); + Connection connectionModerator = session.createConnection(moderatorConnectionProperties); - ConnectionOptions subscriberConnectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC) + ConnectionProperties subscriberConnectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .role(OpenViduRole.SUBSCRIBER).data(serverDataSubscriber).build(); - Connection connectionSubscriber = session.createConnection(subscriberConnectionOptions); + Connection connectionSubscriber = session.createConnection(subscriberConnectionProperties); Assert.assertFalse("Session.fetch() should return false after Session.createConnection", session.fetch()); Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch()); @@ -2543,7 +2543,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Test IPCAM final String rtsp = "rtsp://dummyurl.com"; - Connection ipcamera = session.createConnection(new ConnectionOptions.Builder().type(ConnectionType.IPCAM) + Connection ipcamera = session.createConnection(new ConnectionProperties.Builder().type(ConnectionType.IPCAM) .rtspUri(rtsp).adaptativeBitrate(false).onlyPlayWithSubscribers(false).networkCache(50).build()); Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch()); Assert.assertFalse("Session.fetch() should return false", session.fetch()); diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html index 60c9ed16..0885a902 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.html @@ -17,10 +17,10 @@
      - Record + Record - + {{ enumerator }} diff --git a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts index a670a596..d9fecba0 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-api-dialog/session-api-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout, ConnectionOptions, OpenViduRole } from 'openvidu-node-client'; +import { OpenVidu as OpenViduAPI, Session as SessionAPI, Recording, RecordingProperties, RecordingLayout, ConnectionProperties, OpenViduRole } from 'openvidu-node-client'; @Component({ selector: 'app-session-api-dialog', @@ -26,7 +26,7 @@ export class SessionApiDialogComponent { recPropertiesIcon = 'add_circle'; showRecProperties = false; - connectionOptions: ConnectionOptions = { + connectionProperties: ConnectionProperties = { record: true, role: OpenViduRole.PUBLISHER }; @@ -174,7 +174,7 @@ export class SessionApiDialogComponent { createConnection() { console.log('Creating connection'); - this.session.createConnection(this.connectionOptions) + this.session.createConnection(this.connectionProperties) .then(connection => { this.response = 'Connection created: ' + connection.connectionId; }) @@ -185,9 +185,9 @@ export class SessionApiDialogComponent { updateConnection() { console.log('Updating connection'); - this.session.updateConnection(this.connectionId, this.connectionOptions) + this.session.updateConnection(this.connectionId, this.connectionProperties) .then(modifiedConnection => { - this.response = 'Connection updated: ' + JSON.stringify({ role: modifiedConnection.connectionOptions.role, record: modifiedConnection.connectionOptions.record }); + this.response = 'Connection updated: ' + JSON.stringify({ role: modifiedConnection.connectionProperties.role, record: modifiedConnection.connectionProperties.record }); }) .catch(error => { this.response = 'Error [' + error.message + ']'; diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html index 9efe933d..5ed01d00 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.html @@ -68,7 +68,7 @@
      - + SUB PUB MOD @@ -79,19 +79,19 @@
      + [(ngModel)]="connectionProperties.kurentoOptions.videoMaxRecvBandwidth"> + [(ngModel)]="connectionProperties.kurentoOptions.videoMinRecvBandwidth"> + [(ngModel)]="connectionProperties.kurentoOptions.videoMaxSendBandwidth"> + [(ngModel)]="connectionProperties.kurentoOptions.videoMinSendBandwidth">
      - Record + Record
      @@ -132,6 +132,6 @@ + [mat-dialog-close]="{sessionProperties: sessionProperties, turnConf: turnConf, manualTurnConf: manualTurnConf, customToken: customToken, forcePublishing: forcePublishing, connectionProperties: generateConnectionProperties()}">SAVE
      diff --git a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts index c705c10f..48d6ab98 100644 --- a/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts +++ b/openvidu-testapp/src/app/components/dialogs/session-properties-dialog/session-properties-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; -import { SessionProperties, MediaMode, Recording, RecordingMode, RecordingLayout, ConnectionOptions } from 'openvidu-node-client'; +import { SessionProperties, MediaMode, Recording, RecordingMode, RecordingLayout, ConnectionProperties } from 'openvidu-node-client'; @Component({ selector: 'app-session-properties-dialog', @@ -15,7 +15,7 @@ export class SessionPropertiesDialogComponent { manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; forcePublishing: boolean = false; - connectionOptions: ConnectionOptions; + connectionProperties: ConnectionProperties; filterName = 'GStreamerFilter'; filters: string[] = []; @@ -32,16 +32,16 @@ export class SessionPropertiesDialogComponent { this.manualTurnConf = data.manualTurnConf; this.customToken = data.customToken; this.forcePublishing = data.forcePublishing; - this.connectionOptions = data.connectionOptions; + this.connectionProperties = data.connectionProperties; } enumToArray(enumerator: any) { return Object.keys(enumerator); } - generateConnectionOptions(): ConnectionOptions { - this.connectionOptions.kurentoOptions.allowedFilters = this.filters; - return this.connectionOptions; + generateConnectionProperties(): ConnectionProperties { + this.connectionProperties.kurentoOptions.allowedFilters = this.filters; + return this.connectionProperties; } } diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index d5dd064d..32610b07 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -16,7 +16,7 @@ import { RecordingMode, RecordingLayout, Connection, - ConnectionOptions, + ConnectionProperties, OpenViduRole, RecordingProperties, Recording, @@ -129,7 +129,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { manualTurnConf: RTCIceServer = { urls: [] }; customToken: string; forcePublishing: boolean; - connectionOptions: ConnectionOptions = { + connectionProperties: ConnectionProperties = { role: OpenViduRole.PUBLISHER, record: true, kurentoOptions: { @@ -566,7 +566,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { manualTurnConf: this.manualTurnConf, customToken: this.customToken, forcePublishing: this.forcePublishing, - connectionOptions: this.connectionOptions, + connectionProperties: this.connectionProperties, }, width: '450px' }); @@ -581,7 +581,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { this.manualTurnConf = result.manualTurnConf; this.customToken = result.customToken; this.forcePublishing = result.forcePublishing; - this.connectionOptions = result.connectionOptions; + this.connectionProperties = result.connectionProperties; } document.getElementById('session-settings-btn-' + this.index).classList.remove('cdk-program-focused'); }); @@ -693,7 +693,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { } async createConnection(): Promise { - return this.sessionAPI.createConnection(this.connectionOptions); + return this.sessionAPI.createConnection(this.connectionProperties); } updateEventFromChild(event: OpenViduEvent) { From 41ac4ccec46a767b9865ec1158fbd3da0c1b86a7 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 22 Oct 2020 00:38:27 +0200 Subject: [PATCH 170/435] openvidu-test-e2e: fix testapp pro test --- .../test/e2e/OpenViduProTestAppE2eTest.java | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index cd956268..2641c9a2 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -188,39 +188,39 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { **/ String body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); - body = "{'session':'CUSTOM_SESSION_ID','role':'PUBLISHER','record':false}"; - JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK); + body = "{'role':'PUBLISHER','record':false}"; + JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, HttpStatus.SC_OK); final String token = res.get("token").getAsString(); - final String tokenConnectionId = res.get("connectionId").getAsString(); + final String connectionId = res.get("connectionId").getAsString(); final long createdAt = res.get("createdAt").getAsLong(); - /** UPDATE TOKEN **/ + /** UPDATE PENDING CONNECTION **/ // Test with REST API - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':false}", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'record':123}", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_BAD_REQUEST); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/WRONG/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/WRONG/connection/" + connectionId, "{'role':'PUBLISHER','record':'WRONG'}", HttpStatus.SC_NOT_FOUND); restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/WRONG", "{'role':'PUBLISHER','record':true}", HttpStatus.SC_NOT_FOUND); // Updating only role should let record value untouched - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, mergeJson(DEFAULT_JSON_PENDING_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'MODERATOR','serverData':'','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}", new String[0])); // Updating only record should let role value untouched - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'record':true}", HttpStatus.SC_OK, true, true, true, mergeJson(DEFAULT_JSON_PENDING_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'MODERATOR','serverData':'','token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}", new String[0])); @@ -236,7 +236,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } Assert.assertFalse("Session object should not have changed", session.fetch()); - Connection connection = session.updateConnection(tokenConnectionId, + Connection connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).record(false).build()); Assert.assertEquals("Wrong role Connection property", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Wrong record Connection property", connection.record()); @@ -283,35 +283,35 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { // Test with REST API // Updating only role should let record value untouched - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'MODERATOR','record':false,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); // Updating only record should let role value untouched - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'record':true}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'MODERATOR','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); - restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId, + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, - "{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId + "{'id':'" + connectionId + "','connectionId':'" + connectionId + "','role':'PUBLISHER','record':true,'token':'" + token + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", @@ -321,7 +321,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getDriver().findElement(By.id("session-api-btn-0")).click(); Thread.sleep(1000); user.getDriver().findElement(By.id("connection-id-field")).clear(); - user.getDriver().findElement(By.id("connection-id-field")).sendKeys(tokenConnectionId); + user.getDriver().findElement(By.id("connection-id-field")).sendKeys(connectionId); user.getDriver().findElement(By.id("update-connection-api-btn")).click(); user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Connection updated: {\"role\":\"PUBLISHER\",\"record\":true}")); @@ -345,18 +345,18 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong HTTP status", HttpStatus.SC_NOT_FOUND, exception.getStatus()); } Assert.assertFalse("Session object should not have changed", session.fetch()); - connection = session.updateConnection(tokenConnectionId, + connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.PUBLISHER).build()); Assert.assertFalse("Session object should not have changed", session.fetch()); - Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId()); + Assert.assertEquals("Wrong connectionId in Connection object", connectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); - connection = session.updateConnection(tokenConnectionId, + connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).build()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Session object should not have changed", session.fetch()); - connection = session.updateConnection(tokenConnectionId, + connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); @@ -374,7 +374,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getEventManager().waitUntilEventReaches("streamCreated", 1); // connectionId should be equal to the one brought by the token - Assert.assertEquals("Wrong connectionId", tokenConnectionId, + Assert.assertEquals("Wrong connectionId", connectionId, restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK) .get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject() .get("connectionId").getAsString()); From 97e02094f38a4456ab70c180cf932b73253d73f1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 22 Oct 2020 11:02:40 +0200 Subject: [PATCH 171/435] openvidu-server: Postman collection --- .../OpenVidu.postman_collection.json | 1120 +++++++++++++++++ 1 file changed, 1120 insertions(+) create mode 100644 openvidu-server/src/main/resources/OpenVidu.postman_collection.json diff --git a/openvidu-server/src/main/resources/OpenVidu.postman_collection.json b/openvidu-server/src/main/resources/OpenVidu.postman_collection.json new file mode 100644 index 00000000..86399bcd --- /dev/null +++ b/openvidu-server/src/main/resources/OpenVidu.postman_collection.json @@ -0,0 +1,1120 @@ +{ + "info": { + "_postman_id": "b2fbd114-3827-4117-8281-a16afaf81dcc", + "name": "OpenVidu REST API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "POST Session", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"mediaMode\": \"ROUTED\",\n \"recordingMode\": \"MANUAL\",\n \"customSessionId\": \"TestSession\",\n \"defaultOutputMode\": \"COMPOSED\",\n \"defaultRecordingLayout\": \"BEST_FIT\",\n \"defaultCustomLayout\": \"CUSTOM_LAYOUT\"\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions" + ] + } + }, + "response": [] + }, + { + "name": "GET Session/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID?webRtcStats=false&pendingConnections=true", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID" + ], + "query": [ + { + "key": "webRtcStats", + "value": "false" + }, + { + "key": "pendingConnections", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "GET Sessions", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions?webRtcStats=false&pendingConnections=true", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions" + ], + "query": [ + { + "key": "webRtcStats", + "value": "false" + }, + { + "key": "pendingConnections", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "DELETE Session/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "POST Connection", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"asdf\",\n \"role\": \"PUBLISHER\",\n \"data\": \"SERVER_DATA\",\n \"record\": true,\n \"kurentoOptions\": {\n \"videoMaxRecvBandwidth\": 1000,\n \"videoMinRecvBandwidth\": 300,\n \"videoMaxSendBandwidth\": 1000,\n \"videoMinSendBandwidth\": 300,\n \"allowedFilters\": [\n \"GStreamerFilter\",\n \"ZBarFilter\"\n ]\n },\n \"rtspUri\": \"rtsp://your.camera.ip.sdp\",\n \"adaptativeBitrate\": true,\n \"onlyPlayWithSubscribers\": true,\n \"networkCache\": 2000\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/TestSession/connection", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "TestSession", + "connection" + ] + } + }, + "response": [] + }, + { + "name": "GET Connection/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID/connection/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID", + "connection", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "GET Connections", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID/connection", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID", + "connection" + ] + } + }, + "response": [] + }, + { + "name": "PATCH Connection", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"role\": \"MODERATOR\",\n \"record\": false\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/TestSession/connection/con_SKoAiag7OO", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "TestSession", + "connection", + "con_SKoAiag7OO" + ] + } + }, + "response": [] + }, + { + "name": "DELETE Connection/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID/connection/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID", + "connection", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "POST Recording Start", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"session\":\"TestSession\",\n \"name\":\"MyRecording\",\n \"outputMode\":\"COMPOSED\",\n \"hasAudio\": true,\n \"hasVideo\": true,\n \"recordingLayout\":\"BEST_FIT\",\n \"customLayout\":\"\",\n \"resolution\": \"1280x720\"\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/recordings/start", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "recordings", + "start" + ] + } + }, + "response": [] + }, + { + "name": "POST Recording Stop", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "https://localhost:4443/openvidu/api/recordings/stop/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "recordings", + "stop", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "GET Recording/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/recordings/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "recordings", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "GET Recordings", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/recordings", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "recordings" + ] + } + }, + "response": [] + }, + { + "name": "DELETE Recording", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/recordings/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "recordings", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "GET MediaNode/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes/ID?sessions=true&extra-info=false", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes", + "ID" + ], + "query": [ + { + "key": "sessions", + "value": "true" + }, + { + "key": "extra-info", + "value": "false" + } + ] + } + }, + "response": [] + }, + { + "name": "GET MediaNodes", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes?sessions=true&extra-info=false", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes" + ], + "query": [ + { + "key": "sessions", + "value": "true" + }, + { + "key": "extra-info", + "value": "false" + } + ] + } + }, + "response": [] + }, + { + "name": "POST Media Node", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes?wait=true", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes" + ], + "query": [ + { + "key": "wait", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "DELETE Media Node", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes/ID?wait=true&deletion-strategy=when-no-sessions", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes", + "ID" + ], + "query": [ + { + "key": "wait", + "value": "true" + }, + { + "key": "deletion-strategy", + "value": "when-no-sessions" + } + ] + } + }, + "response": [] + }, + { + "name": "PATCH Media Node", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"status\": \"terminating\"\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes/kms_LmVJiQpm", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes", + "kms_LmVJiQpm" + ] + } + }, + "response": [] + }, + { + "name": "PUT Media Nodes", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "PUT", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/media-nodes", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "media-nodes" + ] + } + }, + "response": [] + }, + { + "name": "POST Token", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"session\": \"TestSession\",\n \"role\": \"PUBLISHER\",\n \"data\": \"SERVER_DATA\",\n \"record\": true,\n \"kurentoOptions\": {\n \"videoMaxRecvBandwidth\": 1000,\n \"videoMinRecvBandwidth\": 300,\n \"videoMaxSendBandwidth\": 1000,\n \"videoMinSendBandwidth\": 300,\n \"allowedFilters\": [ \"GStreamerFilter\", \"ZBarFilter\" ]\n }\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/tokens", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "tokens" + ] + } + }, + "response": [] + }, + { + "name": "DELETE Stream/ID", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "DELETE", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/sessions/ID/stream/ID", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "sessions", + "ID", + "stream", + "ID" + ] + } + }, + "response": [] + }, + { + "name": "POST Signal", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"session\":\"TestSession\",\n \"to\": [],\n \"type\":\"MY_TYPE\",\n \"data\":\"This is my signal data\"\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/signal", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "signal" + ] + } + }, + "response": [] + }, + { + "name": "GET Config", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/config", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "config" + ] + } + }, + "response": [] + }, + { + "name": "GET Health", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://localhost:4443/openvidu/api/health", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "health" + ] + } + }, + "response": [] + }, + { + "name": "POST Restart", + "request": { + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "MY_SECRET", + "type": "string" + }, + { + "key": "username", + "value": "OPENVIDUAPP", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "type": "text", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"OPENVIDU_SECRET\":\"MY_SECRET\",\n \"OPENVIDU_CDR\":true,\n \"OPENVIDU_RECORDING\":true,\n \"OPENVIDU_RECORDING_PUBLIC_ACCESS\":true,\n \"OPENVIDU_RECORDING_NOTIFICATION\":\"publisher_moderator\",\n \"OPENVIDU_RECORDING_PATH\":\"/opt/openvidu/recordings\",\n \"OPENVIDU_RECORDING_CUSTOM_LAYOUT\":\"/opt/openvidu/custom-layout\",\n \"OPENVIDU_RECORDING_AUTOSTOP_TIMEOUT\":120,\n \"OPENVIDU_WEBHOOK\":false,\n \"OPENVIDU_WEBHOOK_ENDPOINT\":\"http://localhost:7777/webhook/\",\n \"OPENVIDU_WEBHOOK_HEADERS\":[\n \"Authorization: Basic T1BFTlZJRFVBUFA6TVlfU0VDUkVU\"\n ],\n \"OPENVIDU_WEBHOOK_EVENTS\":[\n \"recordingStatusChanged\"\n ],\n \"OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH\":1000,\n \"OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH\":300,\n \"OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH\":1000,\n \"OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH\":300,\n \"OPENVIDU_SESSIONS_GARBAGE_INTERVAL\":900,\n \"OPENVIDU_SESSIONS_GARBAGE_THRESHOLD\":3600,\n \"OPENVIDU_PRO_STATS_MONITORING_INTERVAL\":30,\n \"OPENVIDU_PRO_STATS_WEBRTC_INTERVAL\":20\n}" + }, + "url": { + "raw": "https://localhost:4443/openvidu/api/restart", + "protocol": "https", + "host": [ + "localhost" + ], + "port": "4443", + "path": [ + "openvidu", + "api", + "restart" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file From 4ce089acb8fa8cc23096977921c3317a2fa18327 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 22 Oct 2020 13:04:20 +0200 Subject: [PATCH 172/435] openvidu-browser: change token processing after joinRoom --- openvidu-browser/src/OpenVidu/Connection.ts | 43 +++++---- openvidu-browser/src/OpenVidu/Session.ts | 87 +++++++++---------- .../OpenViduInternal/Events/StreamEvent.ts | 4 +- .../Private/LocalConnectionOptions.ts | 32 +++++++ ...nOptions.ts => RemoteConnectionOptions.ts} | 2 +- .../server/core/SessionEventsHandler.java | 17 ++++ .../openvidu/server/core/TokenGenerator.java | 7 -- .../test/e2e/OpenViduTestAppE2eTest.java | 8 +- 8 files changed, 123 insertions(+), 77 deletions(-) create mode 100644 openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts rename openvidu-browser/src/OpenViduInternal/Interfaces/Private/{ConnectionOptions.ts => RemoteConnectionOptions.ts} (94%) diff --git a/openvidu-browser/src/OpenVidu/Connection.ts b/openvidu-browser/src/OpenVidu/Connection.ts index 87776d15..6c13c9ba 100644 --- a/openvidu-browser/src/OpenVidu/Connection.ts +++ b/openvidu-browser/src/OpenVidu/Connection.ts @@ -17,7 +17,8 @@ import { Session } from './Session'; import { Stream } from './Stream'; -import { ConnectionOptions } from '../OpenViduInternal/Interfaces/Private/ConnectionOptions'; +import { LocalConnectionOptions } from '../OpenViduInternal/Interfaces/Private/LocalConnectionOptions'; +import { RemoteConnectionOptions } from '../OpenViduInternal/Interfaces/Private/RemoteConnectionOptions'; import { InboundStreamOptions } from '../OpenViduInternal/Interfaces/Private/InboundStreamOptions'; import { StreamOptionsServer } from '../OpenViduInternal/Interfaces/Private/StreamOptionsServer'; import { OpenViduLogger } from '../OpenViduInternal/Logger/OpenViduLogger'; @@ -58,7 +59,12 @@ export class Connection { /** * @hidden */ - options: ConnectionOptions | undefined; + localOptions: LocalConnectionOptions | undefined; + + /** + * @hidden + */ + remoteOptions: RemoteConnectionOptions | undefined; /** * @hidden @@ -73,23 +79,28 @@ export class Connection { /** * @hidden */ - constructor(private session: Session, opts?: ConnectionOptions) { + constructor(private session: Session, connectionOptions: LocalConnectionOptions | RemoteConnectionOptions) { let msg = "'Connection' created "; - if (!!opts) { - // Connection is remote - msg += "(remote) with 'connectionId' [" + opts.id + ']'; - this.options = opts; - this.connectionId = opts.id; - this.creationTime = opts.createdAt; - if (opts.metadata) { - this.data = opts.metadata; - } - if (opts.streams) { - this.initRemoteStreams(opts.streams); - } - } else { + if (!!(connectionOptions).role) { // Connection is local + this.localOptions = connectionOptions; + this.connectionId = this.localOptions.id; + this.creationTime = this.localOptions.createdAt; + this.data = this.localOptions.metadata; + this.rpcSessionId = this.localOptions.sessionId; msg += '(local)'; + } else { + // Connection is remote + this.remoteOptions = connectionOptions; + this.connectionId = this.remoteOptions.id; + this.creationTime = this.remoteOptions.createdAt; + if (this.remoteOptions.metadata) { + this.data = this.remoteOptions.metadata; + } + if (this.remoteOptions.streams) { + this.initRemoteStreams(this.remoteOptions.streams); + } + msg += "(remote) with 'connectionId' [" + this.remoteOptions.id + ']'; } logger.info(msg); } diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 14906d24..dc09d650 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -26,7 +26,8 @@ import { Capabilities } from '../OpenViduInternal/Interfaces/Public/Capabilities import { EventDispatcher } from './EventDispatcher'; import { SignalOptions } from '../OpenViduInternal/Interfaces/Public/SignalOptions'; import { SubscriberProperties } from '../OpenViduInternal/Interfaces/Public/SubscriberProperties'; -import { ConnectionOptions } from '../OpenViduInternal/Interfaces/Private/ConnectionOptions'; +import { RemoteConnectionOptions } from '../OpenViduInternal/Interfaces/Private/RemoteConnectionOptions'; +import { LocalConnectionOptions } from '../OpenViduInternal/Interfaces/Private/LocalConnectionOptions'; import { ObjMap } from '../OpenViduInternal/Interfaces/Private/ObjMap'; import { SessionOptions } from '../OpenViduInternal/Interfaces/Private/SessionOptions'; import { ConnectionEvent } from '../OpenViduInternal/Events/ConnectionEvent'; @@ -702,7 +703,7 @@ export class Session extends EventDispatcher { /** * @hidden */ - onParticipantJoined(response: ConnectionOptions): void { + onParticipantJoined(response: RemoteConnectionOptions): void { // Connection shouldn't exist this.getConnection(response.id, '') @@ -749,9 +750,10 @@ export class Session extends EventDispatcher { /** * @hidden */ - onParticipantPublished(response: ConnectionOptions): void { + onParticipantPublished(response: RemoteConnectionOptions): void { const afterConnectionFound = (connection) => { + this.remoteConnections[connection.connectionId] = connection; if (!this.remoteStreamsCreated[connection.stream.streamId]) { @@ -775,7 +777,7 @@ export class Session extends EventDispatcher { // Update existing Connection connection = con; response.metadata = con.data; - connection.options = response; + connection.remoteOptions = response; connection.initRemoteStreams(response.streams); afterConnectionFound(connection); }) @@ -1191,34 +1193,24 @@ export class Session extends EventDispatcher { const joinParams = this.initializeParams(token); - this.openvidu.sendRequest('joinRoom', joinParams, (error, response) => { + this.openvidu.sendRequest('joinRoom', joinParams, (error, response: LocalConnectionOptions) => { if (!!error) { reject(error); } else { - // Initialize capabilities object with the role - this.capabilities = { - subscribe: true, - publish: this.openvidu.role !== 'SUBSCRIBER', - forceUnpublish: this.openvidu.role === 'MODERATOR', - forceDisconnect: this.openvidu.role === 'MODERATOR' - }; + this.processJoinRoomResponse(response); // Initialize local Connection object with values returned by openvidu-server - this.connection = new Connection(this); - this.connection.connectionId = response.id; - this.connection.creationTime = response.createdAt; - this.connection.data = response.metadata; - this.connection.rpcSessionId = response.sessionId; + this.connection = new Connection(this, response); // Initialize remote Connections with value returned by openvidu-server const events = { connections: new Array(), streams: new Array() }; - const existingParticipants: ConnectionOptions[] = response.value; - existingParticipants.forEach(participant => { - const connection = new Connection(this, participant); + const existingParticipants: RemoteConnectionOptions[] = response.value; + existingParticipants.forEach((remoteConnectionOptions: RemoteConnectionOptions) => { + const connection = new Connection(this, remoteConnectionOptions); this.remoteConnections[connection.connectionId] = connection; events.connections.push(connection); if (!!connection.stream) { @@ -1323,12 +1315,7 @@ export class Session extends EventDispatcher { this.sessionId = queryParams['sessionId']; const secret = queryParams['secret']; const recorder = queryParams['recorder']; - const coturnIp = queryParams['coturnIp']; - const turnUsername = queryParams['turnUsername']; - const turnCredential = queryParams['turnCredential']; - const role = queryParams['role']; const webrtcStatsInterval = queryParams['webrtcStatsInterval']; - const openviduServerVersion = queryParams['version']; if (!!secret) { this.openvidu.secret = secret; @@ -1336,31 +1323,9 @@ export class Session extends EventDispatcher { if (!!recorder) { this.openvidu.recorder = true; } - if (!!turnUsername && !!turnCredential) { - const stunUrl = 'stun:' + coturnIp + ':3478'; - const turnUrl1 = 'turn:' + coturnIp + ':3478'; - const turnUrl2 = turnUrl1 + '?transport=tcp'; - this.openvidu.iceServers = [ - { urls: [stunUrl] }, - { urls: [turnUrl1, turnUrl2], username: turnUsername, credential: turnCredential } - ]; - logger.log("STUN/TURN server IP: " + coturnIp); - logger.log('TURN temp credentials [' + turnUsername + ':' + turnCredential + ']'); - } - if (!!role) { - this.openvidu.role = role; - } if (!!webrtcStatsInterval) { this.openvidu.webrtcStatsInterval = +webrtcStatsInterval; } - if (!!openviduServerVersion) { - logger.info("openvidu-server version: " + openviduServerVersion); - if (openviduServerVersion !== this.openvidu.libraryVersion) { - logger.warn('OpenVidu Server (' + openviduServerVersion + - ') and OpenVidu Browser (' + this.openvidu.libraryVersion + - ') versions do NOT match. There may be incompatibilities') - } - } this.openvidu.wsUri = 'wss://' + url.host + '/openvidu'; this.openvidu.httpUri = 'https://' + url.host; @@ -1370,4 +1335,32 @@ export class Session extends EventDispatcher { } } + private processJoinRoomResponse(opts: LocalConnectionOptions) { + this.sessionId = opts.session; + if (!!opts.coturnIp && !!opts.turnUsername && !!opts.turnCredential) { + const stunUrl = 'stun:' + opts.coturnIp + ':3478'; + const turnUrl1 = 'turn:' + opts.coturnIp + ':3478'; + const turnUrl2 = turnUrl1 + '?transport=tcp'; + this.openvidu.iceServers = [ + { urls: [stunUrl] }, + { urls: [turnUrl1, turnUrl2], username: opts.turnUsername, credential: opts.turnCredential } + ]; + logger.log("STUN/TURN server IP: " + opts.coturnIp); + logger.log('TURN temp credentials [' + opts.turnUsername + ':' + opts.turnCredential + ']'); + } + this.openvidu.role = opts.role; + this.capabilities = { + subscribe: true, + publish: this.openvidu.role !== 'SUBSCRIBER', + forceUnpublish: this.openvidu.role === 'MODERATOR', + forceDisconnect: this.openvidu.role === 'MODERATOR' + }; + logger.info("openvidu-server version: " + opts.version); + if (opts.version !== this.openvidu.libraryVersion) { + logger.warn('OpenVidu Server (' + opts.version + + ') and OpenVidu Browser (' + this.openvidu.libraryVersion + + ') versions do NOT match. There may be incompatibilities') + } + } + } diff --git a/openvidu-browser/src/OpenViduInternal/Events/StreamEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/StreamEvent.ts index 88d57dff..93ff0809 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/StreamEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/StreamEvent.ts @@ -101,8 +101,8 @@ export class StreamEvent extends Event { // Delete StreamOptionsServer from remote Connection const remoteConnection = this.stream.session.remoteConnections[this.stream.connection.connectionId]; - if (!!remoteConnection && !!remoteConnection.options) { - const streamOptionsServer = remoteConnection.options.streams; + if (!!remoteConnection && !!remoteConnection.remoteOptions) { + const streamOptionsServer = remoteConnection.remoteOptions.streams; for (let i = streamOptionsServer.length - 1; i >= 0; --i) { if (streamOptionsServer[i].id === this.stream.streamId) { streamOptionsServer.splice(i, 1); diff --git a/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts new file mode 100644 index 00000000..27cbd8be --- /dev/null +++ b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts @@ -0,0 +1,32 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { RemoteConnectionOptions } from './RemoteConnectionOptions'; + +export interface LocalConnectionOptions { + id: string; + createdAt: number; + metadata: string; + value: RemoteConnectionOptions[]; + session: string; // OpenVidu Session identifier + sessionId: string; // JSON-RPC session identifier + role: string; + coturnIp: string; + turnUsername: string; + turnCredential: string; + version: string; +} \ No newline at end of file diff --git a/openvidu-browser/src/OpenViduInternal/Interfaces/Private/ConnectionOptions.ts b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/RemoteConnectionOptions.ts similarity index 94% rename from openvidu-browser/src/OpenViduInternal/Interfaces/Private/ConnectionOptions.ts rename to openvidu-browser/src/OpenViduInternal/Interfaces/Private/RemoteConnectionOptions.ts index 12b38df7..250d406d 100644 --- a/openvidu-browser/src/OpenViduInternal/Interfaces/Private/ConnectionOptions.ts +++ b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/RemoteConnectionOptions.ts @@ -17,7 +17,7 @@ import { StreamOptionsServer } from './StreamOptionsServer'; -export interface ConnectionOptions { +export interface RemoteConnectionOptions { id: string; createdAt: number; metadata: string; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 54344d8c..c23de26a 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -38,6 +38,7 @@ import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; import io.openvidu.java.client.OpenViduRole; import io.openvidu.server.cdr.CallDetailRecord; +import io.openvidu.server.config.OpenviduBuildInfo; import io.openvidu.server.config.OpenviduConfig; import io.openvidu.server.kurento.core.KurentoParticipant; import io.openvidu.server.kurento.endpoint.KurentoFilter; @@ -57,6 +58,9 @@ public class SessionEventsHandler { @Autowired protected OpenviduConfig openviduConfig; + @Autowired + protected OpenviduBuildInfo openviduBuildConfig; + private Map recordingsToSendClientEvents = new ConcurrentHashMap<>(); public void onSessionCreated(Session session) { @@ -151,6 +155,19 @@ public class SessionEventsHandler { result.addProperty(ProtocolElements.PARTICIPANTJOINED_METADATA_PARAM, participant.getFullMetadata()); result.add("value", resultArray); + if (participant.getToken() != null) { + result.addProperty("session", participant.getSessionId()); + result.addProperty("coturnIp", openviduConfig.getCoturnIp()); + if (participant.getToken().getRole() != null) { + result.addProperty("role", participant.getToken().getRole().name()); + } + if (participant.getToken().getTurnCredentials() != null) { + result.addProperty("turnUsername", participant.getToken().getTurnCredentials().getUsername()); + result.addProperty("turnCredential", participant.getToken().getTurnCredentials().getCredential()); + } + result.addProperty("version", openviduBuildConfig.getOpenViduServerVersion()); + } + rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result); } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 7e3c70c2..7aac70ab 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -47,16 +47,9 @@ public class TokenGenerator { token += "?sessionId=" + sessionId; token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - token += "&role=" + role.name(); - token += "&version=" + openviduBuildConfig.getOpenViduServerVersion(); TurnCredentials turnCredentials = null; if (this.openviduConfig.isTurnadminAvailable()) { turnCredentials = coturnCredentialsService.createUser(); - if (turnCredentials != null) { - token += "&coturnIp=" + openviduConfig.getCoturnIp(); - token += "&turnUsername=" + turnCredentials.getUsername(); - token += "&turnCredential=" + turnCredentials.getCredential(); - } } ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 06455ddc..0137b987 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -2138,12 +2138,12 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { KurentoOptions kurentoOptions = new KurentoOptions.Builder().videoMaxRecvBandwidth(250) .allowedFilters(new String[] { "GStreamerFilter" }).build(); - ConnectionProperties moderatorConnectionProperties = new ConnectionProperties.Builder().role(OpenViduRole.MODERATOR) - .data(serverDataModerator).kurentoOptions(kurentoOptions).build(); + ConnectionProperties moderatorConnectionProperties = new ConnectionProperties.Builder() + .role(OpenViduRole.MODERATOR).data(serverDataModerator).kurentoOptions(kurentoOptions).build(); Connection connectionModerator = session.createConnection(moderatorConnectionProperties); - ConnectionProperties subscriberConnectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) - .role(OpenViduRole.SUBSCRIBER).data(serverDataSubscriber).build(); + ConnectionProperties subscriberConnectionProperties = new ConnectionProperties.Builder() + .type(ConnectionType.WEBRTC).role(OpenViduRole.SUBSCRIBER).data(serverDataSubscriber).build(); Connection connectionSubscriber = session.createConnection(subscriberConnectionProperties); Assert.assertFalse("Session.fetch() should return false after Session.createConnection", session.fetch()); From 7a26b25f12b8b5a29d0f70704b9e36b69b26ef15 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 22 Oct 2020 20:42:54 +0200 Subject: [PATCH 173/435] ConnectionPropertyChanged event --- openvidu-browser/src/OpenVidu/Connection.ts | 19 +++++ openvidu-browser/src/OpenVidu/OpenVidu.ts | 1 + openvidu-browser/src/OpenVidu/Session.ts | 24 +++++- .../Events/ConnectionPropertyChangedEvent.ts | 74 +++++++++++++++++++ .../Events/NetworkQualityLevelChangedEvent.ts | 4 +- .../Private/LocalConnectionOptions.ts | 1 + openvidu-browser/src/index.ts | 1 + .../client/internal/ProtocolElements.java | 6 +- .../java/io/openvidu/java/client/Session.java | 15 ++-- openvidu-node-client/src/Session.ts | 6 +- .../server/core/SessionEventsHandler.java | 24 +++--- .../core/KurentoSessionEventsHandler.java | 10 --- .../test/e2e/OpenViduProTestAppE2eTest.java | 53 ++++++++++++- .../openvidu-instance.component.ts | 15 +++- 14 files changed, 214 insertions(+), 39 deletions(-) create mode 100644 openvidu-browser/src/OpenViduInternal/Events/ConnectionPropertyChangedEvent.ts diff --git a/openvidu-browser/src/OpenVidu/Connection.ts b/openvidu-browser/src/OpenVidu/Connection.ts index 6c13c9ba..72ad4e32 100644 --- a/openvidu-browser/src/OpenVidu/Connection.ts +++ b/openvidu-browser/src/OpenVidu/Connection.ts @@ -51,6 +51,23 @@ export class Connection { */ data: string; + /** + * Role of the connection. + * - `SUBSCRIBER`: can subscribe to published Streams of other users by calling [[Session.subscribe]] + * - `PUBLISHER`: SUBSCRIBER permissions + can publish their own Streams by calling [[Session.publish]] + * - `MODERATOR`: SUBSCRIBER + PUBLISHER permissions + can force the unpublishing or disconnection over a third-party Stream or Connection by call [[Session.forceUnpublish]] and [[Session.forceDisconnect]] + * + * **Only defined for the local connection. In remote connections will be `undefined`** + */ + role: string; + + /** + * Whether the streams published by this connection will be recorded or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) PRO + * + * **Only defined for the local connection. In remote connections will be `undefined`** + */ + record: boolean; + /** * @hidden */ @@ -88,6 +105,8 @@ export class Connection { this.creationTime = this.localOptions.createdAt; this.data = this.localOptions.metadata; this.rpcSessionId = this.localOptions.sessionId; + this.role = this.localOptions.role; + this.record = this.localOptions.record; msg += '(local)'; } else { // Connection is remote diff --git a/openvidu-browser/src/OpenVidu/OpenVidu.ts b/openvidu-browser/src/OpenVidu/OpenVidu.ts index 3b5d80c1..d4f01140 100644 --- a/openvidu-browser/src/OpenVidu/OpenVidu.ts +++ b/openvidu-browser/src/OpenVidu/OpenVidu.ts @@ -759,6 +759,7 @@ export class OpenVidu { recordingStopped: this.session.onRecordingStopped.bind(this.session), sendMessage: this.session.onNewMessage.bind(this.session), streamPropertyChanged: this.session.onStreamPropertyChanged.bind(this.session), + connectionPropertyChanged: this.session.onConnectionPropertyChanged.bind(this.session), networkQualityLevelChanged: this.session.onNetworkQualityLevelChangedChanged.bind(this.session), filterEventDispatched: this.session.onFilterEventDispatched.bind(this.session), iceCandidate: this.session.recvIceCandidate.bind(this.session), diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index dc09d650..450213f2 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -38,6 +38,7 @@ import { SessionDisconnectedEvent } from '../OpenViduInternal/Events/SessionDisc import { SignalEvent } from '../OpenViduInternal/Events/SignalEvent'; import { StreamEvent } from '../OpenViduInternal/Events/StreamEvent'; import { StreamPropertyChangedEvent } from '../OpenViduInternal/Events/StreamPropertyChangedEvent'; +import { ConnectionPropertyChangedEvent } from '../OpenViduInternal/Events/ConnectionPropertyChangedEvent'; import { NetworkQualityLevelChangedEvent } from '../OpenViduInternal/Events/NetworkQualityLevelChangedEvent'; import { OpenViduError, OpenViduErrorName } from '../OpenViduInternal/Enums/OpenViduError'; import { VideoInsertMode } from '../OpenViduInternal/Enums/VideoInsertMode'; @@ -63,6 +64,7 @@ const platform: PlatformUtils = PlatformUtils.getInstance(); * * - connectionCreated ([[ConnectionEvent]]) * - connectionDestroyed ([[ConnectionEvent]]) + * - connectionPropertyChanged ([[ConnectionPropertyChangedEvent]]) PRO * - sessionDisconnected ([[SessionDisconnectedEvent]]) * - streamCreated ([[StreamEvent]]) * - streamDestroyed ([[StreamEvent]]) @@ -95,7 +97,7 @@ export class Session extends EventDispatcher { streamManagers: StreamManager[] = []; /** - * Object defining the methods that the client is able to call. These are defined by the role of the token used to connect to the Session. + * Object defining the methods that the client is able to call. These are defined by the [[Connection.role]]. * This object is only defined after [[Session.connect]] has been successfully resolved */ capabilities: Capabilities; @@ -930,6 +932,26 @@ export class Session extends EventDispatcher { } } + /** + * @hidden + */ + onConnectionPropertyChanged(msg): void { + let oldValue; + switch (msg.property) { + case 'role': + oldValue = this.connection.role.slice(); + this.connection.role = msg.newValue; + this.connection.localOptions!.role = msg.newValue; + break; + case 'record': + oldValue = this.connection.record; + msg.newValue = msg.newValue === 'true'; + this.connection.record = msg.newValue; + this.connection.localOptions!.record = msg.newValue; + break; + } + this.ee.emitEvent('connectionPropertyChanged', [new ConnectionPropertyChangedEvent(this, this.connection, msg.property, msg.newValue, oldValue)]); + } /** * @hidden diff --git a/openvidu-browser/src/OpenViduInternal/Events/ConnectionPropertyChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/ConnectionPropertyChangedEvent.ts new file mode 100644 index 00000000..2747925e --- /dev/null +++ b/openvidu-browser/src/OpenViduInternal/Events/ConnectionPropertyChangedEvent.ts @@ -0,0 +1,74 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import { Connection } from '../../OpenVidu/Connection'; +import { Session } from '../../OpenVidu/Session'; +import { Event } from './Event'; + +/** + * **This feature is part of OpenVidu Pro tier** PRO + * + * Defines event `connectionPropertyChanged` dispatched by [[Session]] object. + * This event is fired when any property of the local [[Connection]] object changes. + * The properties that may change are [[Connection.role]] and [[Connection.record]]. + * + * The only way the Connection properties may change is by updating them through: + * + * - [API REST](/en/stable/reference-docs/REST-API/#patch-openviduapisessionsltsession_idgtconnectionltconnection_idgt) + * - [openvidu-java-client](/en/stable/reference-docs/openvidu-java-client/#update-a-connection) + * - [openvidu-node-client](/en/stable/reference-docs/openvidu-node-client/#update-a-connection)

      + */ +export class ConnectionPropertyChangedEvent extends Event { + + /** + * The Connection whose property has changed + */ + connection: Connection; + + /** + * The property of the stream that changed. This value is either `"role"` or `"record"` + */ + changedProperty: string; + + /** + * New value of the property (after change, current value) + */ + newValue: Object; + + /** + * Previous value of the property (before change) + */ + oldValue: Object; + + /** + * @hidden + */ + constructor(target: Session, connection: Connection, changedProperty: string, newValue: Object, oldValue: Object) { + super(false, target, 'connectionPropertyChanged'); + this.connection = connection; + this.changedProperty = changedProperty; + this.newValue = newValue; + this.oldValue = oldValue; + } + + /** + * @hidden + */ + // tslint:disable-next-line:no-empty + callDefaultBehavior() { } + +} \ No newline at end of file diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts index a9eba26b..0dbfdc95 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts @@ -20,8 +20,10 @@ import { Session } from '../../OpenVidu/Session'; import { Connection } from '../../OpenVidu/Connection'; /** + * **This feature is part of OpenVidu Pro tier** PRO + * * Defines event `networkQualityLevelChanged` dispatched by [[Session]]. - * This event is fired when the network quality level of a [[Connection]] changes. + * This event is fired when the network quality level of a [[Connection]] changes. See [network quality](/en/stable/advanced-features/network-quality/) */ export class NetworkQualityLevelChangedEvent extends Event { diff --git a/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts index 27cbd8be..b53c4940 100644 --- a/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts +++ b/openvidu-browser/src/OpenViduInternal/Interfaces/Private/LocalConnectionOptions.ts @@ -25,6 +25,7 @@ export interface LocalConnectionOptions { session: string; // OpenVidu Session identifier sessionId: string; // JSON-RPC session identifier role: string; + record: boolean; coturnIp: string; turnUsername: string; turnCredential: string; diff --git a/openvidu-browser/src/index.ts b/openvidu-browser/src/index.ts index a2d82dda..8576b022 100644 --- a/openvidu-browser/src/index.ts +++ b/openvidu-browser/src/index.ts @@ -22,6 +22,7 @@ export { StreamEvent } from './OpenViduInternal/Events/StreamEvent'; export { StreamManagerEvent } from './OpenViduInternal/Events/StreamManagerEvent'; export { VideoElementEvent } from './OpenViduInternal/Events/VideoElementEvent'; export { StreamPropertyChangedEvent } from './OpenViduInternal/Events/StreamPropertyChangedEvent'; +export { ConnectionPropertyChangedEvent } from './OpenViduInternal/Events/ConnectionPropertyChangedEvent'; export { FilterEvent } from './OpenViduInternal/Events/FilterEvent'; export { NetworkQualityLevelChangedEvent } from './OpenViduInternal/Events/NetworkQualityLevelChangedEvent'; diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index 2d5afd0d..52c6145d 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -93,6 +93,10 @@ public class ProtocolElements { public static final String STREAMPROPERTYCHANGED_NEWVALUE_PARAM = "newValue"; public static final String STREAMPROPERTYCHANGED_REASON_PARAM = "reason"; + public static final String CONNECTIONPERTYCHANGED_METHOD = "connectionPropertyChanged"; + public static final String CONNECTIONROPERTYCHANGED_PROPERTY_PARAM = "property"; + public static final String CONNECTIONPROPERTYCHANGED_NEWVALUE_PARAM = "newValue"; + public static final String NETWORKQUALITYLEVELCHANGED_METHOD = "networkQualityLevelChanged"; public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId"; public static final String NETWORKQUALITYCHANGED_QUALITYLEVEL_PARAM = "qualityLevel"; @@ -125,7 +129,7 @@ public class ProtocolElements { public static final String RECONNECTSTREAM_METHOD = "reconnectStream"; public static final String RECONNECTSTREAM_STREAM_PARAM = "stream"; public static final String RECONNECTSTREAM_SDPOFFER_PARAM = "sdpOffer"; - + public static final String VIDEODATA_METHOD = "videoData"; // ---------------------------- SERVER RESPONSES & EVENTS ----------------- diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index b45e9e4f..1682f006 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -463,9 +463,12 @@ public class Session { } /** - * Updates the properties of a Connection with a - * {@link io.openvidu.java.client.ConnectionProperties} object. Only these - * properties can be updated: + * PRO Updates the properties of a Connection with a + * {@link io.openvidu.java.client.ConnectionProperties} object. Only these properties can be updated: *
        *
      • {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole) * ConnectionProperties.Builder.role(OpenViduRole)}
      • @@ -481,9 +484,9 @@ public class Session { * changes consequence of the execution of this method applied in the local * objects. * - * @param connectionId The Connection to modify - * @param connectionProperties A ConnectionProperties object with the new values to - * apply + * @param connectionId The Connection to modify + * @param connectionProperties A ConnectionProperties object with the new values + * to apply * * @return The updated {@link io.openvidu.java.client.Connection Connection} * object diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index f1333182..eacf8bba 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -49,7 +49,7 @@ export class Session { * **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**. * Exceptions to this rule are: * - * - Calling [[Session.createConnection]] automatically adds the new Connection object to the local collection. + * - Calling [[Session.createConnection]] automatically adds the new Connection object to the local collection. * - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object. * - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object. * - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object. @@ -390,6 +390,8 @@ export class Session { } /** + * **This feature is part of OpenVidu Pro tier** PRO + * * Updates the properties of a Connection with a [[ConnectionProperties]] object. * Only these properties can be updated: * @@ -420,8 +422,6 @@ export class Session { .then(res => { if (res.status === 200) { console.log('Connection ' + connectionId + ' updated'); - } else if (res.status === 204) { - console.log('Properties of Connection ' + connectionId + ' remain the same'); } else { // ERROR response from openvidu-server. Resolve HTTP status reject(new Error(res.status.toString())); diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index c23de26a..791b2be6 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -61,7 +61,7 @@ public class SessionEventsHandler { @Autowired protected OpenviduBuildInfo openviduBuildConfig; - private Map recordingsToSendClientEvents = new ConcurrentHashMap<>(); + protected Map recordingsToSendClientEvents = new ConcurrentHashMap<>(); public void onSessionCreated(Session session) { CDR.recordSessionCreated(session); @@ -155,17 +155,18 @@ public class SessionEventsHandler { result.addProperty(ProtocolElements.PARTICIPANTJOINED_METADATA_PARAM, participant.getFullMetadata()); result.add("value", resultArray); + result.addProperty("session", participant.getSessionId()); + result.addProperty("version", openviduBuildConfig.getOpenViduServerVersion()); if (participant.getToken() != null) { - result.addProperty("session", participant.getSessionId()); - result.addProperty("coturnIp", openviduConfig.getCoturnIp()); + result.addProperty("record", participant.getToken().record()); if (participant.getToken().getRole() != null) { result.addProperty("role", participant.getToken().getRole().name()); } + result.addProperty("coturnIp", openviduConfig.getCoturnIp()); if (participant.getToken().getTurnCredentials() != null) { result.addProperty("turnUsername", participant.getToken().getTurnCredentials().getUsername()); result.addProperty("turnCredential", participant.getToken().getTurnCredentials().getCredential()); } - result.addProperty("version", openviduBuildConfig.getOpenViduServerVersion()); } rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, result); @@ -315,13 +316,6 @@ public class SessionEventsHandler { rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); } - public void onNetworkQualityLevelChanged(Session session, JsonObject params) { - session.getParticipants().forEach(p -> { - rpcNotificationService.sendNotification(p.getParticipantPrivateId(), - ProtocolElements.NETWORKQUALITYLEVELCHANGED_METHOD, params); - }); - } - public void onSendMessage(Participant participant, JsonObject message, Set participants, Integer transactionId, OpenViduException error) { @@ -593,7 +587,13 @@ public class SessionEventsHandler { recordingsToSendClientEvents.put(recording.getSessionId(), recording); } - private Set filterParticipantsByRole(OpenViduRole[] roles, Set participants) { + public void onNetworkQualityLevelChanged(Session session, JsonObject params) { + } + + public void onConnectionPropertyChanged(Participant participant, String property, Object newValue) { + } + + protected Set filterParticipantsByRole(OpenViduRole[] roles, Set participants) { return participants.stream().filter(part -> { if (ProtocolElements.RECORDER_PARTICIPANT_PUBLICID.equals(part.getParticipantPublicId())) { return false; diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionEventsHandler.java index a47f18ce..ebf4aa0d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionEventsHandler.java @@ -29,9 +29,6 @@ import io.openvidu.server.core.SessionEventsHandler; public class KurentoSessionEventsHandler extends SessionEventsHandler { - public KurentoSessionEventsHandler() { - } - public void onIceCandidate(String roomName, String participantPrivateId, String senderPublicId, String endpointName, IceCandidate candidate) { JsonObject params = new JsonObject(); @@ -59,11 +56,4 @@ public class KurentoSessionEventsHandler extends SessionEventsHandler { rpcNotificationService.sendNotification(participantId, ProtocolElements.MEDIAERROR_METHOD, notifParams); } - public void updateFilter(String roomName, Participant participant, String filterId, String state) { - } - - public String getNextFilterState(String filterId, String state) { - return null; - } - } diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 2641c9a2..01df4abc 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -189,7 +189,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { String body = "{'customSessionId': 'CUSTOM_SESSION_ID'}"; restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK); body = "{'role':'PUBLISHER','record':false}"; - JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, HttpStatus.SC_OK); + JsonObject res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body, + HttpStatus.SC_OK); final String token = res.get("token").getAsString(); final String connectionId = res.get("connectionId").getAsString(); final long createdAt = res.get("createdAt").getAsLong(); @@ -208,6 +209,16 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/WRONG", "{'role':'PUBLISHER','record':true}", HttpStatus.SC_NOT_FOUND); + // No change should return 200. At this point role=PUBLISHER and record=false + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{}", + HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'role':'PUBLISHER'}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'record':false}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'role':'PUBLISHER','record':false}", HttpStatus.SC_OK); + // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true, @@ -279,9 +290,20 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); - /** UPDATE CONNECTION **/ + /** UPDATE ACTIVE CONNECTION **/ // Test with REST API + + // No change should return 200. At this point role=SUBSCRIBER and record=false + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{}", + HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'role':'SUBSCRIBER'}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'record':false}", HttpStatus.SC_OK); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, + "{'role':'SUBSCRIBER','record':false}", HttpStatus.SC_OK); + // Updating only role should let record value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true, @@ -291,6 +313,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 1); + // Updating only record should let role value untouched restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'record':true}", HttpStatus.SC_OK, false, true, true, @@ -300,6 +325,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 2); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, @@ -308,6 +336,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':" + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 3); + restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId, "{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true, mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION, @@ -317,6 +348,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + activeAt + ",'serverData':''}", new String[] { "location", "platform", "clientData" })); + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 4); + // Test with openvidu-node-client user.getDriver().findElement(By.id("session-api-btn-0")).click(); Thread.sleep(1000); @@ -333,6 +366,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getDriver().findElement(By.id("update-connection-api-btn")).click(); user.getWaiter().until(ExpectedConditions.attributeToBe(By.id("api-response-text-area"), "value", "Connection updated: {\"role\":\"SUBSCRIBER\",\"record\":false}")); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 6); + user.getDriver().findElement(By.id("close-dialog-btn")).click(); Thread.sleep(1000); @@ -347,6 +383,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertFalse("Session object should not have changed", session.fetch()); connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.PUBLISHER).build()); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 7); + Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong connectionId in Connection object", connectionId, connection.getConnectionId()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole()); @@ -354,10 +393,16 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus()); connection = session.updateConnection(connectionId, new ConnectionProperties.Builder().role(OpenViduRole.SUBSCRIBER).build()); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 8); + Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole()); Assert.assertFalse("Session object should not have changed", session.fetch()); - connection = session.updateConnection(connectionId, - new ConnectionProperties.Builder().role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + connection = session.updateConnection(connectionId, new ConnectionProperties.Builder() + .role(OpenViduRole.MODERATOR).record(false).data("NO CHANGE").build()); + + user.getEventManager().waitUntilEventReaches("connectionPropertyChanged", 9); + Assert.assertFalse("Session object should not have changed", session.fetch()); Assert.assertEquals("Wrong role in Connection object", OpenViduRole.MODERATOR, connection.getRole()); Assert.assertFalse("Wrong record in Connection object", connection.record()); diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 32610b07..5cfb392f 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -6,7 +6,7 @@ import { import { OpenVidu, Session, Subscriber, Publisher, Event, StreamEvent, ConnectionEvent, SessionDisconnectedEvent, SignalEvent, RecordingEvent, - PublisherSpeakingEvent, PublisherProperties, StreamPropertyChangedEvent, OpenViduError + PublisherSpeakingEvent, PublisherProperties, StreamPropertyChangedEvent, ConnectionPropertyChangedEvent, OpenViduError } from 'openvidu-browser'; import { OpenVidu as OpenViduAPI, @@ -115,6 +115,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamCreated: true, streamDestroyed: true, streamPropertyChanged: true, + connectionPropertyChanged: true, recordingStarted: true, recordingStopped: true, signal: true, @@ -223,6 +224,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamCreated: false, streamDestroyed: false, streamPropertyChanged: false, + connectionPropertyChanged: false, recordingStarted: false, recordingStopped: false, signal: false, @@ -372,6 +374,15 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { } } + if (this.sessionEvents.connectionPropertyChanged !== oldValues.connectionPropertyChanged || firstTime) { + this.session.off('connectionPropertyChanged'); + if (this.sessionEvents.connectionPropertyChanged) { + this.session.on('connectionPropertyChanged', (event: ConnectionPropertyChangedEvent) => { + this.updateEventList('connectionPropertyChanged', event.changedProperty + ' [' + event.newValue + ']', event); + }); + } + } + if (this.sessionEvents.connectionCreated !== oldValues.connectionCreated || firstTime) { this.session.off('connectionCreated'); if (this.sessionEvents.connectionCreated) { @@ -626,6 +637,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamCreated: this.sessionEvents.streamCreated, streamDestroyed: this.sessionEvents.streamDestroyed, streamPropertyChanged: this.sessionEvents.streamPropertyChanged, + connectionPropertyChanged: this.sessionEvents.connectionPropertyChanged, recordingStarted: this.sessionEvents.recordingStarted, recordingStopped: this.sessionEvents.recordingStopped, signal: this.sessionEvents.signal, @@ -658,6 +670,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamCreated: result.streamCreated, streamDestroyed: result.streamDestroyed, streamPropertyChanged: result.streamPropertyChanged, + connectionPropertyChanged: result.connectionPropertyChanged, recordingStarted: result.recordingStarted, recordingStopped: result.recordingStopped, signal: result.signal, From 06fdc2de546a9a8ba56ab064b48740fdccdd1982 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 22 Oct 2020 21:28:23 +0200 Subject: [PATCH 174/435] openvidu-server: RPC joinRoom params to ProtocolElements. Fix Token#getRecord --- openvidu-browser/src/OpenVidu/Session.ts | 3 +-- .../client/internal/ProtocolElements.java | 8 ++++++++ .../server/core/SessionEventsHandler.java | 20 +++++++++++-------- .../java/io/openvidu/server/core/Token.java | 11 +++++----- ...essionGarbageCollectorIntegrationTest.java | 6 ++---- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 450213f2..c83eea6c 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -77,7 +77,6 @@ const platform: PlatformUtils = PlatformUtils.getInstance(); * - networkQualityLevelChanged ([[NetworkQualityLevelChangedEvent]]) * - reconnecting * - reconnected - * */ export class Session extends EventDispatcher { @@ -1359,7 +1358,7 @@ export class Session extends EventDispatcher { private processJoinRoomResponse(opts: LocalConnectionOptions) { this.sessionId = opts.session; - if (!!opts.coturnIp && !!opts.turnUsername && !!opts.turnCredential) { + if (opts.coturnIp != null && opts.turnUsername != null && opts.turnCredential != null) { const stunUrl = 'stun:' + opts.coturnIp + ':3478'; const turnUrl1 = 'turn:' + opts.coturnIp + ':3478'; const turnUrl2 = turnUrl1 + '?transport=tcp'; diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index 52c6145d..f347c2cf 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -138,6 +138,14 @@ public class ProtocolElements { public static final String PARTICIPANTJOINED_USER_PARAM = "id"; public static final String PARTICIPANTJOINED_CREATEDAT_PARAM = "createdAt"; public static final String PARTICIPANTJOINED_METADATA_PARAM = "metadata"; + public static final String PARTICIPANTJOINED_VALUE_PARAM = "value"; + public static final String PARTICIPANTJOINED_SESSION_PARAM = "session"; + public static final String PARTICIPANTJOINED_VERSION_PARAM = "version"; + public static final String PARTICIPANTJOINED_RECORD_PARAM = "record"; + public static final String PARTICIPANTJOINED_ROLE_PARAM = "role"; + public static final String PARTICIPANTJOINED_COTURNIP_PARAM = "coturnIp"; + public static final String PARTICIPANTJOINED_TURNUSERNAME_PARAM = "turnUsername"; + public static final String PARTICIPANTJOINED_TURNCREDENTIAL_PARAM = "turnCredential"; public static final String PARTICIPANTLEFT_METHOD = "participantLeft"; public static final String PARTICIPANTLEFT_NAME_PARAM = "connectionId"; diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 791b2be6..70f1fa6d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -153,19 +153,23 @@ public class SessionEventsHandler { result.addProperty(ProtocolElements.PARTICIPANTJOINED_USER_PARAM, participant.getParticipantPublicId()); result.addProperty(ProtocolElements.PARTICIPANTJOINED_CREATEDAT_PARAM, participant.getActiveAt()); result.addProperty(ProtocolElements.PARTICIPANTJOINED_METADATA_PARAM, participant.getFullMetadata()); - result.add("value", resultArray); + result.add(ProtocolElements.PARTICIPANTJOINED_VALUE_PARAM, resultArray); - result.addProperty("session", participant.getSessionId()); - result.addProperty("version", openviduBuildConfig.getOpenViduServerVersion()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_SESSION_PARAM, participant.getSessionId()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_VERSION_PARAM, + openviduBuildConfig.getOpenViduServerVersion()); if (participant.getToken() != null) { - result.addProperty("record", participant.getToken().record()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_RECORD_PARAM, participant.getToken().record()); if (participant.getToken().getRole() != null) { - result.addProperty("role", participant.getToken().getRole().name()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_ROLE_PARAM, + participant.getToken().getRole().name()); } - result.addProperty("coturnIp", openviduConfig.getCoturnIp()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_COTURNIP_PARAM, openviduConfig.getCoturnIp()); if (participant.getToken().getTurnCredentials() != null) { - result.addProperty("turnUsername", participant.getToken().getTurnCredentials().getUsername()); - result.addProperty("turnCredential", participant.getToken().getTurnCredentials().getCredential()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_TURNUSERNAME_PARAM, + participant.getToken().getTurnCredentials().getUsername()); + result.addProperty(ProtocolElements.PARTICIPANTJOINED_TURNCREDENTIAL_PARAM, + participant.getToken().getTurnCredentials().getCredential()); } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java index 2529badd..1501858d 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java @@ -39,7 +39,8 @@ public class Token { private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); - public Token(String token, String sessionId, ConnectionProperties connectionProperties, TurnCredentials turnCredentials) { + public Token(String token, String sessionId, ConnectionProperties connectionProperties, + TurnCredentials turnCredentials) { this.token = token; this.sessionId = sessionId; this.createdAt = System.currentTimeMillis(); @@ -67,15 +68,15 @@ public class Token { return this.connectionProperties.getData(); } - public boolean record() { + public Boolean record() { return this.connectionProperties.record(); } public void setRecord(boolean newRecord) { this.updateConnectionProperties(connectionProperties.getType(), connectionProperties.getData(), newRecord, - connectionProperties.getRole(), connectionProperties.getKurentoOptions(), connectionProperties.getRtspUri(), - connectionProperties.adaptativeBitrate(), connectionProperties.onlyPlayWithSubscribers(), - connectionProperties.getNetworkCache()); + connectionProperties.getRole(), connectionProperties.getKurentoOptions(), + connectionProperties.getRtspUri(), connectionProperties.adaptativeBitrate(), + connectionProperties.onlyPlayWithSubscribers(), connectionProperties.getNetworkCache()); } public OpenViduRole getRole() { diff --git a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java index 9bb5d109..8b49bdc6 100644 --- a/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java +++ b/openvidu-server/src/test/java/io/openvidu/server/test/integration/SessionGarbageCollectorIntegrationTest.java @@ -18,7 +18,6 @@ package io.openvidu.server.test.integration; import java.util.HashMap; -import java.util.Map; import java.util.UUID; import org.junit.Assert; @@ -103,9 +102,8 @@ public class SessionGarbageCollectorIntegrationTest { } private String getToken(String sessionId) { - Map map = new HashMap<>(); - map.put("session", sessionId); - String stringResponse = (String) sessionRestController.newToken(map).getBody(); + String stringResponse = (String) sessionRestController.initializeConnection(sessionId, new HashMap<>()) + .getBody(); return new Gson().fromJson(stringResponse, JsonObject.class).get("token").getAsString(); } From c17265a9b052423ac2206c64d139d442ba0f92c3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 11:26:58 +0200 Subject: [PATCH 175/435] SDKs: remove record property from deprecated TokenOptions --- .../java/io/openvidu/java/client/Session.java | 13 ++++++-- .../io/openvidu/java/client/TokenOptions.java | 32 +++---------------- openvidu-node-client/src/Session.ts | 4 ++- openvidu-node-client/src/TokenOptions.ts | 7 ---- 4 files changed, 18 insertions(+), 38 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index 1682f006..bb6cf846 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -100,7 +100,7 @@ public class Session { */ @Deprecated public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException { - return generateToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build()); + return generateToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).build()); } /** @@ -468,7 +468,8 @@ public class Session { * white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: * 3px; font-size: 13px; line-height:21px; font-family: Montserrat, * sans-serif">PRO Updates the properties of a Connection with a - * {@link io.openvidu.java.client.ConnectionProperties} object. Only these properties can be updated: + * {@link io.openvidu.java.client.ConnectionProperties} object. Only these + * properties can be updated: *
          *
        • {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole) * ConnectionProperties.Builder.role(OpenViduRole)}
        • @@ -482,7 +483,13 @@ public class Session { * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the * changes consequence of the execution of this method applied in the local - * objects. + * objects.
          + *
          + * + * The affected client will trigger one ConnectionPropertyChangedEvent for each modified + * property. * * @param connectionId The Connection to modify * @param connectionProperties A ConnectionProperties object with the new values diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java index ab3f1ffe..90629781 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/TokenOptions.java @@ -28,7 +28,6 @@ public class TokenOptions { private OpenViduRole role; private String data; - private Boolean record; private KurentoOptions kurentoOptions; /** @@ -39,14 +38,13 @@ public class TokenOptions { private OpenViduRole role = OpenViduRole.PUBLISHER; private String data; - private Boolean record = true; private KurentoOptions kurentoOptions; /** * Builder for {@link io.openvidu.java.client.TokenOptions}. */ public TokenOptions build() { - return new TokenOptions(this.role, this.data, this.record, this.kurentoOptions); + return new TokenOptions(this.role, this.data, this.kurentoOptions); } /** @@ -84,17 +82,6 @@ public class TokenOptions { return this; } - /** - * Call this method to flag the streams published by the participant owning this - * token to be recorded or not. This only affects INDIVIDUAL recording. If not set by default will be true. - */ - public Builder record(boolean record) { - this.record = record; - return this; - } - /** * Call this method to set a {@link io.openvidu.java.client.KurentoOptions} * object for this token. @@ -106,10 +93,9 @@ public class TokenOptions { } - TokenOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) { + TokenOptions(OpenViduRole role, String data, KurentoOptions kurentoOptions) { this.role = role; this.data = data; - this.record = record; this.kurentoOptions = kurentoOptions; } @@ -128,13 +114,10 @@ public class TokenOptions { } /** - * Whether the streams published by the participant owning this token will be - * recorded or not. This only affects INDIVIDUAL recording. + * Returns the Kurento options assigned to this token */ - public Boolean record() { - return this.record; + public KurentoOptions getKurentoOptions() { + return this.kurentoOptions; } protected JsonObject toJsonObject(String sessionId) { @@ -150,11 +133,6 @@ public class TokenOptions { } else { json.add("data", JsonNull.INSTANCE); } - if (record() != null) { - json.addProperty("record", record()); - } else { - json.add("record", JsonNull.INSTANCE); - } if (this.kurentoOptions != null) { json.add("kurentoOptions", kurentoOptions.toJson()); } diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index eacf8bba..2d86dfaa 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -114,7 +114,6 @@ export class Session { session: this.sessionId, role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null, data: (!!tokenOptions && !!tokenOptions.data) ? tokenOptions.data : null, - record: !!tokenOptions ? tokenOptions.record : null, kurentoOptions: (!!tokenOptions && !!tokenOptions.kurentoOptions) ? tokenOptions.kurentoOptions : null }); axios.post( @@ -401,6 +400,9 @@ export class Session { * This method automatically updates the properties of the local affected objects. This means that there is no need to call * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * + * The affected client will trigger one [ConnectionPropertyChangedEvent](/en/stable/api/openvidu-browser/classes/connectionpropertychangedevent.html) + * for each modified property. + * * @param connectionId The [[Connection.connectionId]] of the Connection object to modify * @param connectionProperties A new [[ConnectionProperties]] object with the updated values to apply * diff --git a/openvidu-node-client/src/TokenOptions.ts b/openvidu-node-client/src/TokenOptions.ts index 5a454cfe..5dd41539 100644 --- a/openvidu-node-client/src/TokenOptions.ts +++ b/openvidu-node-client/src/TokenOptions.ts @@ -37,13 +37,6 @@ export interface TokenOptions { */ data?: string; - /** - * Whether to record the streams published by the participant owning this token or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) - * - * @default true - */ - record?: boolean; - /** * **WARNING**: experimental option. This interface may change in the near future * From cf5d1f7cdf2972dfe2927bbbe0535bca27b9d4ac Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 11:51:47 +0200 Subject: [PATCH 176/435] openvidu-server: update SessionRestController#initializeConnection --- .../java/client/ConnectionProperties.java | 14 ++++++++++---- .../src/ConnectionProperties.ts | 2 ++ .../server/rest/SessionRestController.java | 18 ++++++++---------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java index f857d415..dd5b77cd 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java @@ -56,7 +56,8 @@ public class ConnectionProperties { * have effect: *
            *
          • {@link io.openvidu.java.client.ConnectionType#WEBRTC}: - * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) + * data}, * {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean) * record}, * {@link io.openvidu.java.client.ConnectionProperties.Builder#role(OpenViduRole) @@ -64,7 +65,8 @@ public class ConnectionProperties { * {@link io.openvidu.java.client.ConnectionProperties.Builder#kurentoOptions(KurentoOptions) * kurentoOptions}
          • *
          • {@link io.openvidu.java.client.ConnectionType#IPCAM}: - * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) data}, + * {@link io.openvidu.java.client.ConnectionProperties.Builder#data(String) + * data}, * {@link io.openvidu.java.client.ConnectionProperties.Builder#record(boolean) * record}, * {@link io.openvidu.java.client.ConnectionProperties.Builder#rtspUri(String) @@ -248,8 +250,12 @@ public class ConnectionProperties { } /** - * Whether the streams published by this Connection will be recorded or not. - * This only affects PRO Whether the streams published by this Connection will be + * recorded or not. This only affects INDIVIDUAL recording. */ diff --git a/openvidu-node-client/src/ConnectionProperties.ts b/openvidu-node-client/src/ConnectionProperties.ts index 8ba7f518..ca88e962 100644 --- a/openvidu-node-client/src/ConnectionProperties.ts +++ b/openvidu-node-client/src/ConnectionProperties.ts @@ -39,6 +39,8 @@ export interface ConnectionProperties { data?: string; /** + * **This feature is part of OpenVidu Pro tier** PRO + * * Whether to record the streams published by this Connection or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded) * * @default true diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 7fc10a6b..59aca901 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -284,7 +284,7 @@ public class SessionRestController { ConnectionProperties connectionProperties; try { - connectionProperties = getConnectionPropertiesFromParams(params); + connectionProperties = getConnectionPropertiesFromParams(params).build(); } catch (Exception e) { return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); @@ -660,7 +660,7 @@ public class SessionRestController { ConnectionProperties connectionProperties; params.remove("record"); try { - connectionProperties = getConnectionPropertiesFromParams(params); + connectionProperties = getConnectionPropertiesFromParams(params).build(); } catch (Exception e) { return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST); @@ -787,8 +787,9 @@ public class SessionRestController { // While closing a session tokens can't be generated if (session.closingLock.readLock().tryLock()) { try { - Token token = sessionManager.newToken(session, connectionProperties.getRole(), connectionProperties.getData(), - connectionProperties.record(), connectionProperties.getKurentoOptions()); + Token token = sessionManager.newToken(session, connectionProperties.getRole(), + connectionProperties.getData(), connectionProperties.record(), + connectionProperties.getKurentoOptions()); return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK); } catch (Exception e) { @@ -858,17 +859,15 @@ public class SessionRestController { return token; } - protected ConnectionProperties getConnectionPropertiesFromParams(Map params) throws Exception { + protected ConnectionProperties.Builder getConnectionPropertiesFromParams(Map params) throws Exception { ConnectionProperties.Builder builder = new ConnectionProperties.Builder(); String typeString; String data; - Boolean record; try { typeString = (String) params.get("type"); data = (String) params.get("data"); - record = (Boolean) params.get("record"); } catch (ClassCastException e) { throw new Exception("Type error in some parameter: " + e.getMessage()); } @@ -884,10 +883,9 @@ public class SessionRestController { throw new Exception("Parameter 'type' " + typeString + " is not defined"); } data = data != null ? data : ""; - record = record != null ? record : true; // Build COMMON options - builder.type(type).data(data).record(record); + builder.type(type).data(data).record(true); OpenViduRole role = null; KurentoOptions kurentoOptions = null; @@ -974,7 +972,7 @@ public class SessionRestController { .onlyPlayWithSubscribers(onlyPlayWithSubscribers).networkCache(networkCache).build(); } - return builder.build(); + return builder; } protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { From e32b1f01b46ef10d5b66966f04ed66aa2f3db754 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 12:04:06 +0200 Subject: [PATCH 177/435] openvidu-test-e2e: REST API test GET Session with pending Connections --- .../io/openvidu/test/e2e/OpenViduTestAppE2eTest.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 0137b987..21a72851 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -2686,6 +2686,16 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { final String token2 = res.get("token").getAsString(); final String connectionId2 = res.get("id").getAsString(); + /** GET /openvidu/api/sessions (with pending connections) **/ + res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", null, HttpStatus.SC_OK, true, + false, true, DEFAULT_JSON_SESSION); + Assert.assertEquals("GET session should not bring pending connections", 0, + res.get("connections").getAsJsonObject().get("numberOfElements").getAsInt()); + res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID?pendingConnections=true", null, + HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_SESSION); + Assert.assertEquals("GET session should bring pending connections if query params pendingConnections=true", 2, + res.get("connections").getAsJsonObject().get("numberOfElements").getAsInt()); + /** GET /openvidu/api/sessions/ID/connection (with pending connections) **/ restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK, true, true, false, "{'numberOfElements':2,'content':[]}"); From d358562033cbb0de1154e4b7dbf5e7322fc12eb2 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 20:00:01 +0200 Subject: [PATCH 178/435] openvidu-server: refactor Media Node selection --- .../openvidu/server/core/SessionManager.java | 5 +- .../kurento/core/KurentoSessionManager.java | 52 +++--- .../server/rest/SessionRestController.java | 167 ++++++++++-------- 3 files changed, 118 insertions(+), 106 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index f1a99125..c38ac353 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -46,7 +46,6 @@ import io.openvidu.client.OpenViduException; import io.openvidu.client.OpenViduException.Code; import io.openvidu.client.internal.ProtocolElements; import io.openvidu.java.client.ConnectionProperties; -import io.openvidu.java.client.ConnectionType; import io.openvidu.java.client.KurentoOptions; import io.openvidu.java.client.OpenViduRole; import io.openvidu.java.client.Recording; @@ -307,8 +306,8 @@ public abstract class SessionManager { log.error("Data invalid format"); throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format"); } - Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata, - record, role, kurentoOptions); + Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata, record, role, + kurentoOptions); session.storeToken(tokenObj); session.showTokens("Token created"); return tokenObj; diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index fc078a1d..7799a805 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -78,13 +78,13 @@ public class KurentoSessionManager extends SessionManager { private static final Logger log = LoggerFactory.getLogger(KurentoSessionManager.class); @Autowired - private KmsManager kmsManager; + protected KmsManager kmsManager; @Autowired - private KurentoSessionEventsHandler kurentoSessionEventsHandler; + protected KurentoSessionEventsHandler kurentoSessionEventsHandler; @Autowired - private KurentoParticipantEndpointConfig kurentoEndpointConfig; + protected KurentoParticipantEndpointConfig kurentoEndpointConfig; @Override /* Protected by Session.closingLock.readLock */ @@ -110,23 +110,10 @@ public class KurentoSessionManager extends SessionManager { if (KmsManager.selectAndRemoveKmsLock.tryLock(KmsManager.MAX_SECONDS_LOCK_WAIT, TimeUnit.SECONDS)) { try { kSession = (KurentoSession) sessions.get(sessionId); - if (kSession == null) { // Session still null. It was not created by other thread while waiting for lock - Kms lessLoadedKms = null; - try { - lessLoadedKms = this.kmsManager.getLessLoadedConnectedAndRunningKms(); - } catch (NoSuchElementException e) { - // Restore session not active - this.cleanCollections(sessionId); - this.storeSessionNotActive(sessionNotActive); - throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE, - "There is no available Media Node where to initialize session '" + sessionId - + "'"); - } - log.info("KMS less loaded is {} with a load of {}", lessLoadedKms.getUri(), - lessLoadedKms.getLoad()); - kSession = createSession(sessionNotActive, lessLoadedKms); + Kms selectedMediaNode = this.selectMediaNode(sessionNotActive); + kSession = createSession(sessionNotActive, selectedMediaNode); } } finally { KmsManager.selectAndRemoveKmsLock.unlock(); @@ -992,8 +979,8 @@ public class KurentoSessionManager extends SessionManager { @Override /* Protected by Session.closingLock.readLock */ - public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionProperties connectionProperties) - throws Exception { + public Participant publishIpcam(Session session, MediaOptions mediaOptions, + ConnectionProperties connectionProperties) throws Exception { final String sessionId = session.getSessionId(); final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions; @@ -1119,7 +1106,7 @@ public class KurentoSessionManager extends SessionManager { sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive); } - private void applyFilterInPublisher(KurentoParticipant kParticipant, KurentoFilter filter) + protected void applyFilterInPublisher(KurentoParticipant kParticipant, KurentoFilter filter) throws OpenViduException { GenericMediaElement.Builder builder = new GenericMediaElement.Builder(kParticipant.getPipeline(), filter.getType()); @@ -1131,13 +1118,13 @@ public class KurentoSessionManager extends SessionManager { kParticipant.getPublisher().getMediaOptions().setFilter(filter); } - private void removeFilterInPublisher(KurentoParticipant kParticipant) { + protected void removeFilterInPublisher(KurentoParticipant kParticipant) { kParticipant.getPublisher().cleanAllFilterListeners(); kParticipant.getPublisher().revert(kParticipant.getPublisher().getFilter()); kParticipant.getPublisher().getMediaOptions().setFilter(null); } - private KurentoFilter execFilterMethodInPublisher(KurentoParticipant kParticipant, String method, + protected KurentoFilter execFilterMethodInPublisher(KurentoParticipant kParticipant, String method, JsonObject params) { kParticipant.getPublisher().execMethod(method, params); KurentoFilter filter = kParticipant.getPublisher().getMediaOptions().getFilter(); @@ -1146,7 +1133,7 @@ public class KurentoSessionManager extends SessionManager { return updatedFilter; } - private void addFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) + protected void addFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) throws OpenViduException { PublisherEndpoint pub = kParticipant.getPublisher(); if (!pub.isListenerAddedToFilterEvent(eventType)) { @@ -1170,7 +1157,7 @@ public class KurentoSessionManager extends SessionManager { } } - private void removeFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) { + protected void removeFilterEventListenerInPublisher(KurentoParticipant kParticipant, String eventType) { PublisherEndpoint pub = kParticipant.getPublisher(); if (pub.isListenerAddedToFilterEvent(eventType)) { GenericMediaElement filter = kParticipant.getPublisher().getFilter(); @@ -1178,4 +1165,19 @@ public class KurentoSessionManager extends SessionManager { } } + protected Kms selectMediaNode(Session session) throws OpenViduException { + Kms lessLoadedKms = null; + try { + lessLoadedKms = this.kmsManager.getLessLoadedConnectedAndRunningKms(); + } catch (NoSuchElementException e) { + // Restore session not active + this.cleanCollections(session.getSessionId()); + this.storeSessionNotActive(session); + throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE, + "There is no available Media Node where to initialize session '" + session + "'"); + } + log.info("KMS less loaded is {} with a load of {}", lessLoadedKms.getUri(), lessLoadedKms.getLoad()); + return lessLoadedKms; + } + } diff --git a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java index 59aca901..f14a09f8 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java +++ b/openvidu-server/src/main/java/io/openvidu/server/rest/SessionRestController.java @@ -99,80 +99,19 @@ public class SessionRestController { log.info("REST API: POST {}/sessions {}", RequestMappings.API, params != null ? params.toString() : "{}"); - SessionProperties.Builder builder = new SessionProperties.Builder(); - String customSessionId = null; - - if (params != null) { - - String mediaModeString; - String recordingModeString; - String defaultOutputModeString; - String defaultRecordingLayoutString; - String defaultCustomLayout; - try { - mediaModeString = (String) params.get("mediaMode"); - recordingModeString = (String) params.get("recordingMode"); - defaultOutputModeString = (String) params.get("defaultOutputMode"); - defaultRecordingLayoutString = (String) params.get("defaultRecordingLayout"); - defaultCustomLayout = (String) params.get("defaultCustomLayout"); - customSessionId = (String) params.get("customSessionId"); - } catch (ClassCastException e) { - return this.generateErrorResponse("Type error in some parameter", "/sessions", HttpStatus.BAD_REQUEST); - } - - try { - - // Safe parameter retrieval. Default values if not defined - if (recordingModeString != null) { - RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString); - builder = builder.recordingMode(recordingMode); - } else { - builder = builder.recordingMode(RecordingMode.MANUAL); - } - if (defaultOutputModeString != null) { - OutputMode defaultOutputMode = OutputMode.valueOf(defaultOutputModeString); - builder = builder.defaultOutputMode(defaultOutputMode); - } else { - builder.defaultOutputMode(OutputMode.COMPOSED); - } - if (defaultRecordingLayoutString != null) { - RecordingLayout defaultRecordingLayout = RecordingLayout.valueOf(defaultRecordingLayoutString); - builder = builder.defaultRecordingLayout(defaultRecordingLayout); - } else { - builder.defaultRecordingLayout(RecordingLayout.BEST_FIT); - } - if (mediaModeString != null) { - MediaMode mediaMode = MediaMode.valueOf(mediaModeString); - builder = builder.mediaMode(mediaMode); - } else { - builder = builder.mediaMode(MediaMode.ROUTED); - } - if (customSessionId != null && !customSessionId.isEmpty()) { - if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) { - return this.generateErrorResponse( - "Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]", - "/sessions", HttpStatus.BAD_REQUEST); - } - builder = builder.customSessionId(customSessionId); - } - builder = builder.defaultCustomLayout((defaultCustomLayout != null) ? defaultCustomLayout : ""); - - } catch (IllegalArgumentException e) { - return this.generateErrorResponse("RecordingMode " + params.get("recordingMode") + " | " - + "Default OutputMode " + params.get("defaultOutputMode") + " | " + "Default RecordingLayout " - + params.get("defaultRecordingLayout") + " | " + "MediaMode " + params.get("mediaMode") - + ". Some parameter is not defined", "/sessions", HttpStatus.BAD_REQUEST); - } + SessionProperties sessionProperties; + try { + sessionProperties = getSessionPropertiesFromParams(params).build(); + } catch (Exception e) { + return this.generateErrorResponse(e.getMessage(), "/sessions", HttpStatus.BAD_REQUEST); } - SessionProperties sessionProperties = builder.build(); - String sessionId; - if (customSessionId != null && !customSessionId.isEmpty()) { - if (sessionManager.getSessionWithNotActive(customSessionId) != null) { + if (sessionProperties.customSessionId() != null && !sessionProperties.customSessionId().isEmpty()) { + if (sessionManager.getSessionWithNotActive(sessionProperties.customSessionId()) != null) { return new ResponseEntity<>(HttpStatus.CONFLICT); } - sessionId = customSessionId; + sessionId = sessionProperties.customSessionId(); } else { sessionId = IdentifierPrefixes.SESSION_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9); @@ -846,17 +785,76 @@ public class SessionRestController { } } - protected Token getTokenFromConnectionId(String connectionId, Iterator> iterator) { - boolean found = false; - Token token = null; - while (iterator.hasNext() && !found) { - Token tAux = iterator.next().getValue(); - found = tAux.getConnectionId().equals(connectionId); - if (found) { - token = tAux; + protected SessionProperties.Builder getSessionPropertiesFromParams(Map params) throws Exception { + + SessionProperties.Builder builder = new SessionProperties.Builder(); + String customSessionId = null; + + if (params != null) { + + String mediaModeString; + String recordingModeString; + String defaultOutputModeString; + String defaultRecordingLayoutString; + String defaultCustomLayout; + try { + mediaModeString = (String) params.get("mediaMode"); + recordingModeString = (String) params.get("recordingMode"); + defaultOutputModeString = (String) params.get("defaultOutputMode"); + defaultRecordingLayoutString = (String) params.get("defaultRecordingLayout"); + defaultCustomLayout = (String) params.get("defaultCustomLayout"); + customSessionId = (String) params.get("customSessionId"); + } catch (ClassCastException e) { + throw new Exception("Type error in some parameter: " + e.getMessage()); + } + + try { + // Safe parameter retrieval. Default values if not defined + if (recordingModeString != null) { + RecordingMode recordingMode = RecordingMode.valueOf(recordingModeString); + builder = builder.recordingMode(recordingMode); + } else { + builder = builder.recordingMode(RecordingMode.MANUAL); + } + if (defaultOutputModeString != null) { + OutputMode defaultOutputMode = OutputMode.valueOf(defaultOutputModeString); + builder = builder.defaultOutputMode(defaultOutputMode); + } else { + builder.defaultOutputMode(OutputMode.COMPOSED); + } + if (defaultRecordingLayoutString != null) { + RecordingLayout defaultRecordingLayout = RecordingLayout.valueOf(defaultRecordingLayoutString); + builder = builder.defaultRecordingLayout(defaultRecordingLayout); + } else { + builder.defaultRecordingLayout(RecordingLayout.BEST_FIT); + } + if (defaultCustomLayout != null) { + builder.defaultCustomLayout(defaultCustomLayout); + } else { + builder.defaultCustomLayout(""); + } + if (mediaModeString != null) { + MediaMode mediaMode = MediaMode.valueOf(mediaModeString); + builder = builder.mediaMode(mediaMode); + } else { + builder = builder.mediaMode(MediaMode.ROUTED); + } + if (customSessionId != null && !customSessionId.isEmpty()) { + if (!sessionManager.formatChecker.isValidCustomSessionId(customSessionId)) { + throw new Exception( + "Parameter 'customSessionId' is wrong. Must be an alphanumeric string [a-zA-Z0-9_-]"); + } + builder = builder.customSessionId(customSessionId); + } + + } catch (IllegalArgumentException e) { + throw new Exception("RecordingMode " + params.get("recordingMode") + " | " + "Default OutputMode " + + params.get("defaultOutputMode") + " | " + "Default RecordingLayout " + + params.get("defaultRecordingLayout") + " | " + "MediaMode " + params.get("mediaMode") + + ". Some parameter is not defined"); } } - return token; + return builder; } protected ConnectionProperties.Builder getConnectionPropertiesFromParams(Map params) throws Exception { @@ -975,6 +973,19 @@ public class SessionRestController { return builder; } + protected Token getTokenFromConnectionId(String connectionId, Iterator> iterator) { + boolean found = false; + Token token = null; + while (iterator.hasNext() && !found) { + Token tAux = iterator.next().getValue(); + found = tAux.getConnectionId().equals(connectionId); + if (found) { + token = tAux; + } + } + return token; + } + protected ResponseEntity generateErrorResponse(String errorMessage, String path, HttpStatus status) { JsonObject responseJson = new JsonObject(); responseJson.addProperty("timestamp", System.currentTimeMillis()); From dff5f8f5d4a0dff1d96e4289f6efc0ca04e5d082 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 20:42:19 +0200 Subject: [PATCH 179/435] openvidu-test-e2e: fix Kurento reconnect test --- .../openvidu/server/kurento/core/KurentoSessionManager.java | 3 +-- .../io/openvidu/server/utils/MediaNodeStatusManager.java | 2 ++ .../openvidu/server/utils/MediaNodeStatusManagerDummy.java | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 7799a805..61e9e971 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -118,7 +118,6 @@ public class KurentoSessionManager extends SessionManager { } finally { KmsManager.selectAndRemoveKmsLock.unlock(); } - } else { String error = "Timeout of " + KmsManager.MAX_SECONDS_LOCK_WAIT + " seconds waiting to acquire lock"; @@ -1174,7 +1173,7 @@ public class KurentoSessionManager extends SessionManager { this.cleanCollections(session.getSessionId()); this.storeSessionNotActive(session); throw new OpenViduException(Code.ROOM_CANNOT_BE_CREATED_ERROR_CODE, - "There is no available Media Node where to initialize session '" + session + "'"); + "There is no available Media Node where to initialize session '" + session.getSessionId() + "'"); } log.info("KMS less loaded is {} with a load of {}", lessLoadedKms.getUri(), lessLoadedKms.getLoad()); return lessLoadedKms; diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java index cfad5e5c..46a91680 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java @@ -12,4 +12,6 @@ public interface MediaNodeStatusManager { public boolean isWaitingIdleToTerminate(String mediaNodeId); + public String instanceStatus(String mediaNodeId); + } diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java index d0eacd25..1b35f3be 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java @@ -27,4 +27,9 @@ public class MediaNodeStatusManagerDummy implements MediaNodeStatusManager { return false; } + @Override + public String instanceStatus(String mediaNodeId) { + return null; + } + } From 8ddd9bfc1b3503f063abe100cbde0063cee37d0c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 20:44:00 +0200 Subject: [PATCH 180/435] openvidu-server-pro: removed MediaNodeStatusManager#instanceStatus --- .../io/openvidu/server/utils/MediaNodeStatusManager.java | 2 -- .../openvidu/server/utils/MediaNodeStatusManagerDummy.java | 5 ----- 2 files changed, 7 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java index 46a91680..cfad5e5c 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManager.java @@ -12,6 +12,4 @@ public interface MediaNodeStatusManager { public boolean isWaitingIdleToTerminate(String mediaNodeId); - public String instanceStatus(String mediaNodeId); - } diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java index 1b35f3be..d0eacd25 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/MediaNodeStatusManagerDummy.java @@ -27,9 +27,4 @@ public class MediaNodeStatusManagerDummy implements MediaNodeStatusManager { return false; } - @Override - public String instanceStatus(String mediaNodeId) { - return null; - } - } From e384a0706374cfed88292316d60fe3b4f5b98605 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 23 Oct 2020 22:10:15 +0200 Subject: [PATCH 181/435] SDKs: SessionProperties#mediaNode --- .../java/client/SessionProperties.java | 44 ++++++++++++++++--- openvidu-node-client/src/SessionProperties.ts | 9 ++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java index 8f436721..820c45ff 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java @@ -30,6 +30,7 @@ public class SessionProperties { private RecordingLayout defaultRecordingLayout; private String defaultCustomLayout; private String customSessionId; + private String mediaNode; /** * Builder for {@link io.openvidu.java.client.SessionProperties} @@ -42,6 +43,7 @@ public class SessionProperties { private RecordingLayout defaultRecordingLayout = RecordingLayout.BEST_FIT; private String defaultCustomLayout = ""; private String customSessionId = ""; + private String mediaNode; /** * Returns the {@link io.openvidu.java.client.SessionProperties} object properly @@ -49,7 +51,7 @@ public class SessionProperties { */ public SessionProperties build() { return new SessionProperties(this.mediaMode, this.recordingMode, this.defaultOutputMode, - this.defaultRecordingLayout, this.defaultCustomLayout, this.customSessionId); + this.defaultRecordingLayout, this.defaultCustomLayout, this.customSessionId, this.mediaNode); } /** @@ -117,9 +119,9 @@ public class SessionProperties { *
            * * Custom layouts are only applicable to recordings with OutputMode - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and - * RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM} + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) + * and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM} */ public SessionProperties.Builder defaultCustomLayout(String path) { this.defaultCustomLayout = path; @@ -138,6 +140,19 @@ public class SessionProperties { return this; } + /** + * PRO Call this method to force the session to be hosted in the + * Media Node with identifier mediaNodeId + */ + public SessionProperties.Builder mediaNode(String mediaNodeId) { + this.mediaNode = mediaNodeId; + return this; + } + } protected SessionProperties() { @@ -147,16 +162,18 @@ public class SessionProperties { this.defaultRecordingLayout = RecordingLayout.BEST_FIT; this.defaultCustomLayout = ""; this.customSessionId = ""; + this.mediaNode = ""; } private SessionProperties(MediaMode mediaMode, RecordingMode recordingMode, OutputMode outputMode, - RecordingLayout layout, String defaultCustomLayout, String customSessionId) { + RecordingLayout layout, String defaultCustomLayout, String customSessionId, String mediaNode) { this.mediaMode = mediaMode; this.recordingMode = recordingMode; this.defaultOutputMode = outputMode; this.defaultRecordingLayout = layout; this.defaultCustomLayout = defaultCustomLayout; this.customSessionId = customSessionId; + this.mediaNode = mediaNode; } /** @@ -213,8 +230,8 @@ public class SessionProperties { * with any other value.
            * Custom layouts are only applicable to recordings with OutputMode * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED} (or - * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) and - * RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM} + * {@link io.openvidu.java.client.Recording.OutputMode#COMPOSED_QUICK_START}) + * and RecordingLayout {@link io.openvidu.java.client.RecordingLayout#CUSTOM} */ public String defaultCustomLayout() { return this.defaultCustomLayout; @@ -231,4 +248,17 @@ public class SessionProperties { return this.customSessionId; } + /** + * PRO The Media Node where to host the session. The default + * option if this property is not defined is the less loaded Media Node at the + * moment the first user joins the session. + */ + public String mediaNode() { + return this.mediaNode; + } + } \ No newline at end of file diff --git a/openvidu-node-client/src/SessionProperties.ts b/openvidu-node-client/src/SessionProperties.ts index f866e1b8..e08aa0d0 100644 --- a/openvidu-node-client/src/SessionProperties.ts +++ b/openvidu-node-client/src/SessionProperties.ts @@ -64,4 +64,13 @@ export interface SessionProperties { * If this parameter is undefined or an empty string, OpenVidu Server will generate a random sessionId for you. */ customSessionId?: string; + + /** + * **This feature is part of OpenVidu Pro tier** PRO + * + * The Media Node where to host the session. The default option if this property is not defined is the less loaded + * Media Node at the moment the first user joins the session. + */ + mediaNode?: string; + } From 64b241c17080567673c3d2134c20e481cb314643 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sun, 25 Oct 2020 16:42:40 +0100 Subject: [PATCH 182/435] Minor documentation fixes --- .../java/io/openvidu/java/client/Connection.java | 8 ++++++-- .../java/client/ConnectionProperties.java | 4 ++-- .../java/io/openvidu/java/client/Session.java | 2 +- openvidu-node-client/src/Connection.ts | 3 ++- openvidu-node-client/src/OpenVidu.ts | 13 ++++++------- openvidu-node-client/src/Session.ts | 16 ++++++++-------- .../java/io/openvidu/server/OpenViduServer.java | 4 ++-- 7 files changed, 27 insertions(+), 23 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index ca51e7f5..da194f85 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -52,7 +52,7 @@ public class Connection { /** * Returns the identifier of the Connection. You can call methods * {@link io.openvidu.java.client.Session#forceDisconnect(String)} or - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionProperties)} * passing this property as parameter */ public String getConnectionId() { @@ -190,7 +190,11 @@ public class Connection { } /** - * Returns the token string associated to the Connection + * Returns the token string associated to the Connection. This is the value that + * must be sent to the client-side to be consumed in OpenVidu Browser method + * Session.connect. */ public String getToken() { return this.token; diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java index dd5b77cd..b68504c3 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java @@ -78,8 +78,8 @@ public class ConnectionProperties { * {@link io.openvidu.java.client.ConnectionProperties.Builder#networkCache(int) * networkCache}
          • *
          - * If not set by default will be @link - * io.openvidu.java.client.ConnectionType#WEBRTC}. + * If not set by default will be + * {@link io.openvidu.java.client.ConnectionType#WEBRTC}. */ public Builder type(ConnectionType type) { this.type = type; diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index bb6cf846..ccf65b2f 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -155,7 +155,7 @@ public class Session { /** * Same as - * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties) + * {@link io.openvidu.java.client.Session#createConnection(ConnectionProperties)} * but with default ConnectionProperties values. * * @return The generated {@link io.openvidu.java.client.Connection Connection} diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index 3507fe72b..bf774c81 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -76,7 +76,8 @@ export class Connection { connectionProperties: ConnectionProperties; /** - * Token associated to the Connection + * Token associated to the Connection. This is the value that must be sent to the client-side to be consumed in OpenVidu Browser + * method [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect). */ token: string; diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index b98a2ee1..463a91c9 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -17,13 +17,11 @@ import axios from 'axios'; import { Connection } from './Connection'; -import { Publisher } from './Publisher'; import { Recording } from './Recording'; import { RecordingProperties } from './RecordingProperties'; import { Session } from './Session'; import { SessionProperties } from './SessionProperties'; import { RecordingLayout } from './RecordingLayout'; -import { RecordingMode } from 'RecordingMode'; /** * @hidden @@ -90,17 +88,18 @@ export class OpenVidu { activeSessions: Session[] = []; /** - * @param urlOpenViduServer URL where your instance of OpenVidu Server is up an running. - * It must be the full URL (e.g. `https://12.34.56.78:1234/`) + * @param hostname URL where your instance of OpenVidu Server is up an running. + * It must be the full URL (e.g. `https://12.34.56.78:1234/`) + * * @param secret Secret used on OpenVidu Server initialization */ - constructor(private urlOpenViduServer: string, secret: string) { + constructor(private hostname: string, secret: string) { this.setHostnameAndPort(); this.basicAuth = this.getBasicAuth(secret); } /** - * Creates an OpenVidu session. You can call [[Session.getSessionId]] inside the resolved promise to retrieve the `sessionId` + * Creates an OpenVidu session. The session identifier will be available at property [[Session.sessionId]] * * @returns A Promise that is resolved to the [[Session]] if success and rejected with an Error object if not. */ @@ -669,7 +668,7 @@ export class OpenVidu { private setHostnameAndPort(): void { let url: URL; try { - url = new URL(this.urlOpenViduServer); + url = new URL(this.hostname); } catch (error) { console.error('URL format incorrect', error); throw new Error('URL format incorrect: ' + error); diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 2d86dfaa..3f92a1e8 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -96,13 +96,6 @@ export class Session { this.properties.defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT; } - /** - * Gets the unique identifier of the Session - */ - public getSessionId(): string { - return this.sessionId; - } - /** * @deprecated Use [[Session.createConnection]] instead to get a [[Connection]] object. * @@ -401,7 +394,7 @@ export class Session { * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * The affected client will trigger one [ConnectionPropertyChangedEvent](/en/stable/api/openvidu-browser/classes/connectionpropertychangedevent.html) - * for each modified property. + * for each modified property. * * @param connectionId The [[Connection.connectionId]] of the Connection object to modify * @param connectionProperties A new [[ConnectionProperties]] object with the updated values to apply @@ -449,6 +442,13 @@ export class Session { }); } + /** + * @hidden + */ + public getSessionId(): string { + return this.sessionId; + } + /** * @hidden */ diff --git a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java index 419d6e77..92964b48 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java +++ b/openvidu-server/src/main/java/io/openvidu/server/OpenViduServer.java @@ -347,11 +347,11 @@ public class OpenViduServer implements JsonRpcConfigurer { @EventListener(ApplicationReadyEvent.class) public void whenReady() { - String dashboardUrl = httpUrl + "dashboard/"; + String dashboardUrl = httpUrl + config.getOpenViduFrontendDefaultPath().replaceAll("^/", ""); // @formatter:off String msg = "\n\n----------------------------------------------------\n" + "\n" + " OpenVidu is ready!\n" - + " ---------------------------\n" + "\n" + " * OpenVidu Server: " + httpUrl + "\n" + "\n" + + " ---------------------------\n" + "\n" + " * OpenVidu Server URL: " + httpUrl + "\n" + "\n" + " * OpenVidu Dashboard: " + dashboardUrl + "\n" + "\n" + "----------------------------------------------------\n"; // @formatter:on From 0e4bbc4555e3f778c663f92036399b5609fb5db3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 26 Oct 2020 19:22:59 +0100 Subject: [PATCH 183/435] SDKs send "mediaNode" property --- .../java/io/openvidu/java/client/Session.java | 10 +-- .../java/client/SessionProperties.java | 18 +++++ openvidu-node-client/src/Session.ts | 3 +- openvidu-node-client/src/SessionProperties.ts | 7 +- .../openvidu/server/core/SessionManager.java | 72 ++++++++++--------- 5 files changed, 66 insertions(+), 44 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index ccf65b2f..13dd609e 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -661,17 +661,9 @@ public class Session { } HttpPost request = new HttpPost(this.openVidu.hostname + OpenVidu.API_SESSIONS); - - JsonObject json = new JsonObject(); - json.addProperty("mediaMode", properties.mediaMode().name()); - json.addProperty("recordingMode", properties.recordingMode().name()); - json.addProperty("defaultOutputMode", properties.defaultOutputMode().name()); - json.addProperty("defaultRecordingLayout", properties.defaultRecordingLayout().name()); - json.addProperty("defaultCustomLayout", properties.defaultCustomLayout()); - json.addProperty("customSessionId", properties.customSessionId()); StringEntity params = null; try { - params = new StringEntity(json.toString()); + params = new StringEntity(properties.toJson().toString()); } catch (UnsupportedEncodingException e1) { throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause()); } diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java index 820c45ff..1305a0ab 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/SessionProperties.java @@ -17,6 +17,8 @@ package io.openvidu.java.client; +import com.google.gson.JsonObject; + import io.openvidu.java.client.Recording.OutputMode; /** @@ -261,4 +263,20 @@ public class SessionProperties { return this.mediaNode; } + protected JsonObject toJson() { + JsonObject json = new JsonObject(); + json.addProperty("mediaMode", mediaMode().name()); + json.addProperty("recordingMode", recordingMode().name()); + json.addProperty("defaultOutputMode", defaultOutputMode().name()); + json.addProperty("defaultRecordingLayout", defaultRecordingLayout().name()); + json.addProperty("defaultCustomLayout", defaultCustomLayout()); + json.addProperty("customSessionId", customSessionId()); + if (mediaNode() != null) { + JsonObject mediaNodeJson = new JsonObject(); + mediaNodeJson.addProperty("id", mediaNode()); + json.add("mediaNode", mediaNodeJson); + } + return json; + } + } \ No newline at end of file diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 3f92a1e8..a374c1eb 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -465,7 +465,8 @@ export class Session { defaultOutputMode: !!this.properties.defaultOutputMode ? this.properties.defaultOutputMode : Recording.OutputMode.COMPOSED, defaultRecordingLayout: !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT, defaultCustomLayout: !!this.properties.defaultCustomLayout ? this.properties.defaultCustomLayout : '', - customSessionId: !!this.properties.customSessionId ? this.properties.customSessionId : '' + customSessionId: !!this.properties.customSessionId ? this.properties.customSessionId : '', + mediaNode: !!this.properties.mediaNode ? this.properties.mediaNode : undefined }); axios.post( diff --git a/openvidu-node-client/src/SessionProperties.ts b/openvidu-node-client/src/SessionProperties.ts index e08aa0d0..3c2ad5ef 100644 --- a/openvidu-node-client/src/SessionProperties.ts +++ b/openvidu-node-client/src/SessionProperties.ts @@ -69,8 +69,11 @@ export interface SessionProperties { * **This feature is part of OpenVidu Pro tier** PRO * * The Media Node where to host the session. The default option if this property is not defined is the less loaded - * Media Node at the moment the first user joins the session. + * Media Node at the moment the first user joins the session. This object defines the following properties as Media Node selector: + * - `id`: Media Node unique identifier */ - mediaNode?: string; + mediaNode?: { + id: string; + } } diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index c38ac353..0bcc6155 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; +import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.PostConstruct; @@ -445,38 +446,11 @@ public abstract class SessionManager { log.info("Running non active sessions garbage collector..."); final long currentMillis = System.currentTimeMillis(); - // Loop through all non active sessions. Safely remove them and clean all of - // their data if their threshold has elapsed - for (Iterator> iter = sessionsNotActive.entrySet().iterator(); iter.hasNext();) { - final Session sessionNotActive = iter.next().getValue(); - final String sessionId = sessionNotActive.getSessionId(); - long sessionExistsSince = currentMillis - sessionNotActive.getStartTime(); - if (sessionExistsSince > (openviduConfig.getSessionGarbageThreshold() * 1000)) { - try { - if (sessionNotActive.closingLock.writeLock().tryLock(15, TimeUnit.SECONDS)) { - try { - if (sessions.containsKey(sessionId)) { - // The session passed to active during lock wait - continue; - } - iter.remove(); - cleanCollections(sessionId); - log.info("Non active session {} cleaned up by garbage collector", sessionId); - } finally { - sessionNotActive.closingLock.writeLock().unlock(); - } - } else { - log.error( - "Timeout waiting for Session closing lock to be available for garbage collector to clean session {}", - sessionId); - } - } catch (InterruptedException e) { - log.error( - "InterruptedException while waiting for Session closing lock to be available for garbage collector to clean session {}", - sessionId); - } - } - } + this.closeNonActiveSessions(sessionNotActive -> { + // Remove non active session if threshold has elapsed + return (currentMillis - sessionNotActive.getStartTime()) > (openviduConfig.getSessionGarbageThreshold() + * 1000); + }); // Warn about possible ghost sessions for (Iterator> iter = sessions.entrySet().iterator(); iter.hasNext();) { @@ -550,6 +524,40 @@ public abstract class SessionManager { } } + public void closeNonActiveSessions(Function conditionToRemove) { + // Loop through all non active sessions. Safely remove and clean all of + // the data for each non active session meeting the condition + for (Iterator> iter = sessionsNotActive.entrySet().iterator(); iter.hasNext();) { + final Session sessionNotActive = iter.next().getValue(); + final String sessionId = sessionNotActive.getSessionId(); + if (conditionToRemove.apply(sessionNotActive)) { + try { + if (sessionNotActive.closingLock.writeLock().tryLock(15, TimeUnit.SECONDS)) { + try { + if (sessions.containsKey(sessionId)) { + // The session passed to active during lock wait + continue; + } + iter.remove(); + cleanCollections(sessionId); + log.info("Non active session {} cleaned up", sessionId); + } finally { + sessionNotActive.closingLock.writeLock().unlock(); + } + } else { + log.error( + "Timeout waiting for Session closing lock to be available to clean up non active session {}", + sessionId); + } + } catch (InterruptedException e) { + log.error( + "InterruptedException while waiting for non active Session closing lock to be available to clean up non active session session {}", + sessionId); + } + } + } + } + public void closeSessionAndEmptyCollections(Session session, EndReason reason, boolean stopRecording) { if (openviduConfig.isRecordingModuleEnabled()) { From d5e84709ad8a9c1755ecbd4fe22c3ed0b30e0efa Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 30 Oct 2020 22:37:05 +0100 Subject: [PATCH 184/435] ci: Add option to upload installation scripts automatically --- openvidu-server/deployments/pro/aws/createAMIs.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index 4ca8adec..da9fd402 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -51,6 +51,11 @@ sed -i "s/AMIUSEAST1/${AMIUSEAST1}/g" cfn-mkt-kms-ami.yaml aws s3 cp cfn-mkt-kms-ami.yaml s3://aws.openvidu.io TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-kms-ami.yaml +# Update installation script +if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then + aws s3 cp ../docker-compose/media-node/install_media_node.sh s3://aws.openvidu.io/install_media_node_$OPENVIDU_PRO_VERSION.sh --acl public-read +fi + aws cloudformation create-stack \ --stack-name kms-${DATESTAMP} \ --template-url ${TEMPLATE_URL} \ @@ -79,6 +84,11 @@ aws cloudformation delete-stack --stack-name kms-${DATESTAMP} aws s3 cp cfn-mkt-ov-ami.yaml s3://aws.openvidu.io TEMPLATE_URL=https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/cfn-mkt-ov-ami.yaml +# Update installation script +if [[ ${UPDATE_INSTALLATION_SCRIPT} == "true" ]]; then + aws s3 cp ../docker-compose/openvidu-server-pro/install_openvidu_pro.sh s3://aws.openvidu.io/install_openvidu_pro_$OPENVIDU_PRO_VERSION.sh --acl public-read +fi + aws cloudformation create-stack \ --stack-name openvidu-${DATESTAMP} \ --template-url ${TEMPLATE_URL} \ From 79648c4006c4f858e1d679dac1e359c7fe9f5478 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 30 Oct 2020 22:42:41 +0100 Subject: [PATCH 185/435] Add env variable to checkout automatically for releases --- openvidu-server/deployments/pro/aws/createAMIs.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index da9fd402..3b3fe9af 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -1,4 +1,12 @@ #!/bin/bash -x +set -eu -o pipefail + +CF_RELEASE=${CF_RELEASE:-false} + +if [[ $CF_RELEASE == "true" ]]; then + git checkout v$OPENVIDU_PRO_VERSION +fi + export AWS_DEFAULT_REGION=eu-west-1 DATESTAMP=$(date +%s) From 44bb958da3672e96c186007697978e1ebb4fc72c Mon Sep 17 00:00:00 2001 From: cruizba Date: Sun, 1 Nov 2020 21:03:12 +0100 Subject: [PATCH 186/435] deployment: nginx refactor --- .../deployments/ce/docker-compose/.env | 3 + .../ce/docker-compose/docker-compose.yml | 1 + .../docker-compose/openvidu-server-pro/.env | 3 + .../openvidu-server-pro/docker-compose.yml | 1 + .../ce/default-app-without-demos.conf | 105 -------- .../default_nginx_conf/ce/default-app.conf | 92 +------ .../default-app-without-demos.conf | 146 ----------- .../support_deprecated_api/default-app.conf | 146 ----------- .../global/default-root.conf | 2 + .../global/location-yourapp.conf | 4 + .../global/locations-ce/common-api-ce.conf | 14 ++ .../locations-ce/deprecated-api-ce.conf | 40 +++ .../global/locations-ce/new-api-ce.conf | 33 +++ .../global/locations-pro/common-api-pro.conf | 27 +++ .../locations-pro/deprecated-api-pro.conf | 59 +++++ .../global/locations-pro/new-api-pro.conf | 46 ++++ .../default_nginx_conf/global/proxy.conf | 13 + .../default_nginx_conf/global/ssl.conf | 14 ++ .../global/upstream-yourapp.conf | 4 + .../pro/default-app-without-demos.conf | 169 ------------- .../default_nginx_conf/pro/default.conf | 119 +-------- .../default-app-without-demos.conf | 229 ------------------ .../pro/support_deprecated_api/default.conf | 229 ------------------ .../docker/openvidu-proxy/entrypoint.sh | 3 +- openvidu-server/docker/openvidu-proxy/test.sh | 0 25 files changed, 286 insertions(+), 1216 deletions(-) delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf create mode 100644 openvidu-server/docker/openvidu-proxy/test.sh diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 279ec85e..0a6a7da8 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -39,6 +39,9 @@ LETSENCRYPT_EMAIL=user@example.com # SDKs, REST clients and browsers will have to connect to this port # HTTPS_PORT=443 +# If true request to with www will be redirected to non-www requests +# REDIRECT_WWW=false + # Access restrictions # In this section you will be able to restrict the IPs from which you can access to # Openvidu API and the Administration Panel diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 4e1cbdae..baeef2dc 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -92,3 +92,4 @@ services: - PROXY_MODE=CE - WITH_APP=true - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} + - REDIRECT_WWW=${REDIRECT_WWW:-false} diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 6cf0d1ae..02c68e18 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -42,6 +42,9 @@ LETSENCRYPT_EMAIL=user@example.com # SDKs, REST clients and browsers will have to connect to this port # HTTPS_PORT=443 +# If true request to with www will be redirected to non-www requests +# REDIRECT_WWW=false + # Access restrictions # In this section you will be able to restrict the IPs from which you can access to # Openvidu API and the Administration Panel diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index e8681b99..034d6035 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -86,6 +86,7 @@ services: - PROXY_MODE=PRO - WITH_APP=true - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} + - REDIRECT_WWW=${REDIRECT_WWW:-false} elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0 diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf deleted file mode 100644 index eecf11c5..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app-without-demos.conf +++ /dev/null @@ -1,105 +0,0 @@ -# Your app -#upstream yourapp { -# server localhost:5442; -#} - -upstream openviduserver { - server localhost:5443; -} - -server { - listen {https_port} ssl; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - root /var/www/html; - - # Your app - #location / { - # proxy_pass http://yourapp; # Openvidu call by default - #} - - ################################# - # Common rules # - ################################# - # Dashboard rule - location /dashboard { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - # Websocket rule - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # LetsEncrypt # - ################################# - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf index 9b1c21ab..efc7d333 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf @@ -1,7 +1,4 @@ -# Openvidu call -upstream yourapp { - server localhost:5442; -} +{app_upstream} upstream openviduserver { server localhost:5443; @@ -11,89 +8,20 @@ server { listen {https_port} ssl; server_name {domain_name}; - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + {ssl_config} - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; + {proxy_config} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; + {app_config} - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; + ######################## + # OpenVidu Locations # + ######################## + {common_api_ce} - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; + {deprecated_api_ce} - # Welcome - #root /var/www/html; - - # Your app - location / { - proxy_pass http://yourapp; # Openvidu call by default - } - - ################################# - # Common rules # - ################################# - # Dashboard rule - location /dashboard { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - # Websocket rule - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } + {new_api_ce} ################################# # LetsEncrypt # diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf deleted file mode 100644 index 6cb723f0..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf +++ /dev/null @@ -1,146 +0,0 @@ -# Your app -#upstream yourapp { -# server localhost:5442; -#} - -upstream openviduserver { - server localhost:5443; -} - -server { - listen {https_port} ssl; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - root /var/www/html; - - # Your app - #location / { - # proxy_pass http://yourapp; # Openvidu call by default - #} - - ################################# - # Common rules # - ################################# - # Dashboard rule - location /dashboard { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - # Websocket rule - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - ################################# - # Deprecated API # - ################################# - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /recordings { - proxy_pass http://openviduserver; - } - - location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # LetsEncrypt # - ################################# - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf deleted file mode 100644 index e4c1f8d7..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/support_deprecated_api/default-app.conf +++ /dev/null @@ -1,146 +0,0 @@ -# Openvidu call -upstream yourapp { - server localhost:5442; -} - -upstream openviduserver { - server localhost:5443; -} - -server { - listen {https_port} ssl; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - #root /var/www/html; - - # Your app - location / { - proxy_pass http://yourapp; # Openvidu call by default - } - - ################################# - # Common rules # - ################################# - # Dashboard rule - location /dashboard { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - # Websocket rule - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - ################################# - # Deprecated API # - ################################# - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /recordings { - proxy_pass http://openviduserver; - } - - location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # LetsEncrypt # - ################################# - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf new file mode 100644 index 00000000..eaef697f --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf @@ -0,0 +1,2 @@ +# Welcome +root /var/www/html; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf new file mode 100644 index 00000000..1f714085 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf @@ -0,0 +1,4 @@ +# Your App +location / { + proxy_pass http://yourapp; # Openvidu call by default +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf new file mode 100644 index 00000000..e5609e8d --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf @@ -0,0 +1,14 @@ +################################# +# Common rules # +################################# +# Dashboard rule +location /dashboard { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +# Websocket rule +location ~ /openvidu$ { + proxy_pass http://openviduserver; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf new file mode 100644 index 00000000..f8406500 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf @@ -0,0 +1,40 @@ +################################# +# Deprecated API # +################################# +# Openvidu Server +location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; +} + +location /recordings { + proxy_pass http://openviduserver; +} + +location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /accept-certificate { + proxy_pass http://openviduserver; +} + +location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf new file mode 100644 index 00000000..992eb7db --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf @@ -0,0 +1,33 @@ +################################# +# New API # +################################# +location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; +} + +location /openvidu/recordings { + proxy_pass http://openviduserver; +} + +location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +location /openvidu/accept-certificate { + proxy_pass http://openviduserver; +} + +location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf new file mode 100644 index 00000000..ea22f7de --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf @@ -0,0 +1,27 @@ +################################# +# Common rules # +################################# +location /dashboard { + {rules_access_dashboard} + deny all; + rewrite ^/dashboard/(.*)$ /$1 break; + proxy_pass http://openviduserver/; +} + +location /inspector { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +location ~ /openvidu$ { + proxy_pass http://openviduserver; +} + +location /kibana { + {rules_access_dashboard} + deny all; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf new file mode 100644 index 00000000..95fe3481 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf @@ -0,0 +1,59 @@ +################################# +# Deprecated API # +################################# +# Openvidu Server +location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; +} + +location /recordings { + proxy_pass http://openviduserver; +} + +location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /accept-certificate { + proxy_pass http://openviduserver; +} + +location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +# Openvidu Server Pro +location /pro { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /api-login { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /elasticsearch { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf new file mode 100644 index 00000000..ef33eba1 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf @@ -0,0 +1,46 @@ +################################# +# New API # +################################# +# OpenVidu Server +location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; +} + +location /openvidu/recordings { + proxy_pass http://openviduserver; +} + +location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; +} + +location /openvidu/accept-certificate { + proxy_pass http://openviduserver; +} + +location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} +# OpenVidu Server PRO +location /openvidu/elk { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} + +location /openvidu/inspector-api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf new file mode 100644 index 00000000..197cdab3 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf @@ -0,0 +1,13 @@ +# Proxy +proxy_set_header Host $host; +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $scheme; +proxy_set_header X-Forwarded-Proto https; +proxy_headers_hash_bucket_size 512; +proxy_redirect off; + +# Websockets +proxy_http_version 1.1; +proxy_set_header Upgrade $http_upgrade; +proxy_set_header Connection "upgrade"; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf new file mode 100644 index 00000000..38395628 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf @@ -0,0 +1,14 @@ +# SSL Config +ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; +ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; +ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + +ssl_session_cache shared:SSL:50m; +ssl_session_timeout 5m; +ssl_stapling on; +ssl_stapling_verify on; + +ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + +ssl_prefer_server_ciphers on; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf new file mode 100644 index 00000000..f4048ec8 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf @@ -0,0 +1,4 @@ +# Your App +upstream yourapp { + server localhost:5442; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf deleted file mode 100644 index 9bae1de9..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default-app-without-demos.conf +++ /dev/null @@ -1,169 +0,0 @@ -add_header X-Frame-Options SAMEORIGIN; -add_header X-Content-Type-Options nosniff; -add_header X-XSS-Protection "1; mode=block"; - -# Openvidu call -#upstream yourapp { -# server localhost:5442; -#} - -upstream kibana { - server localhost:5601; -} - -upstream openviduserver { - server localhost:5443; -} - -server { - # Redirect to https - if ($host = {domain_name}) { - rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; - } # managed by Certbot - - listen {http_port} default_server; - server_name {domain_name}; - - # letsencrypt - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } - - # Kibana panel - location /kibana { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } -} - -server { - listen {https_port} ssl default deferred; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - root /var/www/html; - - # Your app - # location / { - # proxy_pass http://yourapp; # Openvidu call by default - #} - - ################################# - # Common rules # - ################################# - location /dashboard { - {rules_access_dashboard} - deny all; - rewrite ^/dashboard/(.*)$ /$1 break; - proxy_pass http://openviduserver/; - } - - location /inspector { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /kibana { - {rules_access_dashboard} - deny all; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } - - ################################# - # New API # - ################################# - # OpenVidu Server - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - # OpenVidu Server PRO - location /openvidu/elk { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/inspector-api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - - ################################# - # LetsEncrypt # - ################################# - - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf index 4c6a4df8..510d59e6 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf @@ -2,10 +2,7 @@ add_header X-Frame-Options SAMEORIGIN; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block"; -# Openvidu call -upstream yourapp { - server localhost:5442; -} +{app_upstream} upstream kibana { server localhost:5601; @@ -47,116 +44,20 @@ server { listen {https_port} ssl default deferred; server_name {domain_name}; - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + {ssl_config} - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; + {proxy_config} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + {app_config} - ssl_prefer_server_ciphers on; + ######################## + # OpenVidu Locations # + ######################## + {common_api_pro} - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - #root /var/www/html; - - # Your app - location / { - proxy_pass http://yourapp; # Openvidu call by default - } - - ################################# - # Common rules # - ################################# - location /dashboard { - {rules_access_dashboard} - deny all; - rewrite ^/dashboard/(.*)$ /$1 break; - proxy_pass http://openviduserver/; - } - - location /inspector { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /kibana { - {rules_access_dashboard} - deny all; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } - - ################################# - # New API # - ################################# - # OpenVidu Server - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - # OpenVidu Server PRO - location /openvidu/elk { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/inspector-api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } + {deprecated_api_pro} + {new_api_pro} ################################# # LetsEncrypt # diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf deleted file mode 100644 index e74c8782..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf +++ /dev/null @@ -1,229 +0,0 @@ -add_header X-Frame-Options SAMEORIGIN; -add_header X-Content-Type-Options nosniff; -add_header X-XSS-Protection "1; mode=block"; - -# Openvidu call -#upstream yourapp { -# server localhost:5442; -#} - -upstream kibana { - server localhost:5601; -} - -upstream openviduserver { - server localhost:5443; -} - -server { - # Redirect to https - if ($host = {domain_name}) { - rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; - } # managed by Certbot - - listen {http_port} default_server; - server_name {domain_name}; - - # letsencrypt - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } - - # Kibana panel - location /kibana { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } -} - -server { - listen {https_port} ssl default deferred; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - root /var/www/html; - - # Your app - # location / { - # proxy_pass http://yourapp; # Openvidu call by default - #} - - ################################# - # Common rules # - ################################# - location /dashboard { - {rules_access_dashboard} - deny all; - rewrite ^/dashboard/(.*)$ /$1 break; - proxy_pass http://openviduserver/; - } - - location /inspector { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /kibana { - {rules_access_dashboard} - deny all; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } - - ################################# - # Deprecated API # - ################################# - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /recordings { - proxy_pass http://openviduserver; - } - - location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # Openvidu Server Pro - location /pro { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /api-login { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /elasticsearch { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - # OpenVidu Server - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - # OpenVidu Server PRO - location /openvidu/elk { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/inspector-api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - - ################################# - # LetsEncrypt # - ################################# - - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf deleted file mode 100644 index a84514c7..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/support_deprecated_api/default.conf +++ /dev/null @@ -1,229 +0,0 @@ -add_header X-Frame-Options SAMEORIGIN; -add_header X-Content-Type-Options nosniff; -add_header X-XSS-Protection "1; mode=block"; - -# Openvidu call -upstream yourapp { - server localhost:5442; -} - -upstream kibana { - server localhost:5601; -} - -upstream openviduserver { - server localhost:5443; -} - -server { - # Redirect to https - if ($host = {domain_name}) { - rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; - } # managed by Certbot - - listen {http_port} default_server; - server_name {domain_name}; - - # letsencrypt - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } - - # Kibana panel - location /kibana { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_set_header Host $host; - proxy_cache_bypass $http_upgrade; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } -} - -server { - listen {https_port} ssl default deferred; - server_name {domain_name}; - - ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; - ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - - ssl_session_cache shared:SSL:50m; - ssl_session_timeout 5m; - ssl_stapling on; - ssl_stapling_verify on; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - - ssl_prefer_server_ciphers on; - - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Proto https; - proxy_headers_hash_bucket_size 512; - proxy_redirect off; - - # Websockets - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - - # Welcome - #root /var/www/html; - - # Your app - location / { - proxy_pass http://yourapp; # Openvidu call by default - } - - ################################# - # Common rules # - ################################# - location /dashboard { - {rules_access_dashboard} - deny all; - rewrite ^/dashboard/(.*)$ /$1 break; - proxy_pass http://openviduserver/; - } - - location /inspector { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location ~ /openvidu$ { - proxy_pass http://openviduserver; - } - - location /kibana { - {rules_access_dashboard} - deny all; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; - } - - ################################# - # Deprecated API # - ################################# - # Openvidu Server - location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /recordings { - proxy_pass http://openviduserver; - } - - location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /accept-certificate { - proxy_pass http://openviduserver; - } - - location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - # Openvidu Server Pro - location /pro { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /api-login { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /elasticsearch { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - ################################# - # New API # - ################################# - # OpenVidu Server - location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; - } - - location /openvidu/recordings { - proxy_pass http://openviduserver; - } - - location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/accept-certificate { - proxy_pass http://openviduserver; - } - - location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - # OpenVidu Server PRO - location /openvidu/elk { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - location /openvidu/inspector-api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; - } - - - ################################# - # LetsEncrypt # - ################################# - - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 8df13142..e975e800 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -148,7 +148,8 @@ case ${CERTIFICATE_TYPE} in certbot certonly -n --webroot -w /var/www/certbot \ -m "${LETSENCRYPT_EMAIL}" \ - --agree-tos -d "${DOMAIN_OR_PUBLIC_IP}" + --agree-tos -d "${DOMAIN_OR_PUBLIC_IP}" \ + `if [[ "${REDIRECT_WWW}" == "true" ]]; then echo "-d www.${DOMAIN_OR_PUBLIC_IP}" ; fi` else printf "\n - LetsEncrypt certificate already exists, using them..." fi diff --git a/openvidu-server/docker/openvidu-proxy/test.sh b/openvidu-server/docker/openvidu-proxy/test.sh new file mode 100644 index 00000000..e69de29b From e9426aebef4031898ffe3d8066408509fa8b6108 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 2 Nov 2020 14:13:04 +0100 Subject: [PATCH 187/435] openvidu-server: CommandExecutor return output as list --- .../server/utils/CommandExecutor.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java b/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java index 9d933ed0..608a1b84 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java +++ b/openvidu-server/src/main/java/io/openvidu/server/utils/CommandExecutor.java @@ -21,7 +21,9 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; @@ -37,13 +39,20 @@ public class CommandExecutor { public static String execCommand(long msTimeout, String... command) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); - return commonExecCommand(msTimeout, processBuilder); + return commonExecCommand(msTimeout, processBuilder, true).get(0); + } + + public static List execCommandReturnList(long msTimeout, String... command) + throws IOException, InterruptedException { + ProcessBuilder processBuilder = new ProcessBuilder(command); + processBuilder.redirectErrorStream(true); + return commonExecCommand(msTimeout, processBuilder, false); } public static String execCommandRedirectError(long msTimeout, File errorOutputFile, String... command) throws IOException, InterruptedException { ProcessBuilder processBuilder = new ProcessBuilder(command).redirectError(errorOutputFile); - return commonExecCommand(msTimeout, processBuilder); + return commonExecCommand(msTimeout, processBuilder, true).get(0); } public static void execCommandRedirectStandardOutputAndError(long msTimeout, File standardOutputFile, @@ -59,11 +68,11 @@ public class CommandExecutor { } } - private static String commonExecCommand(long msTimeout, ProcessBuilder processBuilder) + private static List commonExecCommand(long msTimeout, ProcessBuilder processBuilder, boolean singleString) throws IOException, InterruptedException { Process process = processBuilder.start(); StringBuilder processOutput = new StringBuilder(); - String output; + List outputList = new ArrayList<>(); InputStreamReader inputStreamReader = null; BufferedReader processOutputReader = null; try { @@ -71,9 +80,15 @@ public class CommandExecutor { processOutputReader = new BufferedReader(inputStreamReader); String readLine; while ((readLine = processOutputReader.readLine()) != null) { - processOutput.append(readLine + System.lineSeparator()); + if (singleString) { + processOutput.append(readLine + System.lineSeparator()); + } else { + outputList.add(readLine); + } + } + if (singleString) { + outputList = Arrays.asList(processOutput.toString().trim()); } - if (!process.waitFor(msTimeout, TimeUnit.MILLISECONDS)) { log.error("Command {} did not receive a response in {} ms", Arrays.toString(processBuilder.command().toArray()), msTimeout); @@ -81,7 +96,6 @@ public class CommandExecutor { log.error(errorMsg); throw new IOException(errorMsg); } - output = processOutput.toString().trim(); } finally { if (inputStreamReader != null) { inputStreamReader.close(); @@ -90,7 +104,7 @@ public class CommandExecutor { processOutputReader.close(); } } - return output; + return outputList; } public static String gatherLinuxHostInformation() throws IOException, InterruptedException { From ede9589b292e82af513a97d1baaa5e9f30bcaa63 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Mon, 2 Nov 2020 17:06:04 +0100 Subject: [PATCH 188/435] Install ethtool on Dockerfile --- openvidu-server/docker/openvidu-server-pro/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/docker/openvidu-server-pro/Dockerfile b/openvidu-server/docker/openvidu-server-pro/Dockerfile index 4271b2ea..24be405c 100644 --- a/openvidu-server/docker/openvidu-server-pro/Dockerfile +++ b/openvidu-server/docker/openvidu-server-pro/Dockerfile @@ -10,6 +10,7 @@ RUN apt-get update && apt-get install -y \ redis-tools \ jq \ docker.io \ + ethtool \ && rm -rf /var/lib/apt/lists/* RUN mkdir -p /opt/openvidu /usr/local/bin/ From 6a73083e7bc302c12694b0a042fc17b48ded9228 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 19:46:59 +0100 Subject: [PATCH 189/435] openvidu-deployment: General updates in nginx and public ip discovering: - Add option to redirect www to non-www (REDIRECT_WWW). - Add endpoint to check nginx workers. - Custom virtual hosts (Server blocks) can be added by the user to create custom rules in `/opt/openvidu/custom-nginx-vhost`. - Parametrize `worker_connections` in nginx.conf (WORKER_CONNECTIONS) - Improve `discover_my_public_ip.sh` to use dns servers instead of http servers - Posibility to autodiscover ipv6 if available by using `PUBLIC_IP=auto-ipv6` in nginx, `TURN_PUBLIC_IP=auto-ipv6` in coturn and `COTURN_IP=auto-ipv6` in openvidu-server. By default ipv4 is used. --- .../deployments/ce/docker-compose/.env | 6 + .../ce/docker-compose/docker-compose.yml | 12 +- .../ce/docker-compose/install_openvidu.sh | 4 + .../docker-compose/openvidu-server-pro/.env | 6 + .../openvidu-server-pro/docker-compose.yml | 9 +- .../install_openvidu_pro.sh | 4 + .../docker/openvidu-coturn/entrypoint.sh | 3 +- .../docker/openvidu-proxy/Dockerfile | 10 +- .../default_nginx_conf/ce/default-app.conf | 33 ---- .../default_nginx_conf/ce/default.conf | 40 +++++ .../default_nginx_conf/global/app_config.conf | 4 + .../global/app_config_default.conf | 2 + ...pstream-yourapp.conf => app_upstream.conf} | 0 .../global/ce/common_api_ce.conf | 14 ++ .../global/ce/deprecated_api_ce.conf | 40 +++++ .../global/ce/new_api_ce.conf | 33 ++++ .../global/ce/redirect_www.conf | 14 ++ .../global/default-root.conf | 2 - .../global/location-yourapp.conf | 4 - .../global/locations-ce/common-api-ce.conf | 14 -- .../locations-ce/deprecated-api-ce.conf | 40 ----- .../global/locations-ce/new-api-ce.conf | 33 ---- .../global/locations-pro/common-api-pro.conf | 27 ---- .../locations-pro/deprecated-api-pro.conf | 59 ------- .../global/locations-pro/new-api-pro.conf | 46 ------ .../global/nginx_status.conf | 5 + .../global/pro/common_api_pro.conf | 27 ++++ .../global/pro/deprecated_api_pro.conf | 59 +++++++ .../global/pro/new_api_pro.conf | 46 ++++++ .../global/pro/redirect_www.conf | 3 + .../default_nginx_conf/global/proxy.conf | 13 -- .../global/proxy_config.conf | 13 ++ .../global/redirect_www_ssl.conf | 18 +++ .../default_nginx_conf/global/ssl.conf | 14 -- .../default_nginx_conf/global/ssl_config.conf | 14 ++ .../default_nginx_conf/pro/default.conf | 6 + .../docker/openvidu-proxy/entrypoint.sh | 110 +++++++++---- .../docker/openvidu-proxy/nginx.conf | 32 ++++ openvidu-server/docker/openvidu-proxy/test.sh | 0 .../docker/openvidu-server-pro/entrypoint.sh | 8 + .../docker/openvidu-server/entrypoint.sh | 8 + .../docker/utils/discover_my_public_ip.sh | 145 +++++++++++++----- 42 files changed, 616 insertions(+), 364 deletions(-) delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config_default.conf rename openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/{upstream-yourapp.conf => app_upstream.conf} (100%) create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/common_api_ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/deprecated_api_ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/new_api_ce.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/redirect_www.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/nginx_status.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/common_api_pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/deprecated_api_pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/new_api_pro.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/redirect_www.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy_config.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/redirect_www_ssl.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf create mode 100644 openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl_config.conf create mode 100644 openvidu-server/docker/openvidu-proxy/nginx.conf delete mode 100644 openvidu-server/docker/openvidu-proxy/test.sh diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 0a6a7da8..86cba267 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -40,8 +40,14 @@ LETSENCRYPT_EMAIL=user@example.com # HTTPS_PORT=443 # If true request to with www will be redirected to non-www requests +# Default value is false # REDIRECT_WWW=false +# How many workers to configure in nginx proxy. +# The more workers, the more requests will be handled +# Default value is 10240 +# WORKER_CONNECTIONS=10240 + # Access restrictions # In this section you will be able to restrict the IPs from which you can access to # Openvidu API and the Administration Panel diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index baeef2dc..9bdc7081 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -22,10 +22,10 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server:2.16.0-dev1 + image: openvidu/openvidu-server:2.16.0-dev2 restart: on-failure network_mode: host - entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh'] + entrypoint: ['/usr/local/bin/entrypoint.sh'] volumes: - /var/run/docker.sock:/var/run/docker.sock - ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH} @@ -39,6 +39,7 @@ services: - KMS_URIS=["ws://localhost:8888/kurento"] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} + - COTURN_IP=${COTURN_IP:-auto-ipv4} kms: image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} @@ -62,7 +63,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:2.0.0-dev2 + image: openvidu/openvidu-coturn:2.0.0-dev3 restart: on-failure network_mode: host environment: @@ -74,12 +75,13 @@ services: - MAX_PORT=65535 nginx: - image: openvidu/openvidu-proxy:4.0.0-dev4 + image: openvidu/openvidu-proxy:4.0.0-dev5 restart: on-failure network_mode: host volumes: - ./certificates:/etc/letsencrypt - ./owncert:/owncert + - ./custom-nginx-vhosts:/etc/nginx/vhost.d/ - ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout environment: - DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP} @@ -93,3 +95,5 @@ services: - WITH_APP=true - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} - REDIRECT_WWW=${REDIRECT_WWW:-false} + - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} + - PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} diff --git a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh index 634d104d..fdaa61cb 100755 --- a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh +++ b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh @@ -54,6 +54,10 @@ new_ov_installation() { printf "\n => Creating folder 'owncert'..." mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the folder 'owncert'" + # Create vhost nginx folder + printf "\n => Creating folder 'custom-nginx-vhosts'..." + mkdir "${OPENVIDU_FOLDER}/custom-nginx-vhosts" || fatal_error "Error while creating the folder 'custom-nginx-vhosts'" + # Ready to use printf '\n' printf '\n' diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 02c68e18..cb4e985a 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -43,8 +43,14 @@ LETSENCRYPT_EMAIL=user@example.com # HTTPS_PORT=443 # If true request to with www will be redirected to non-www requests +# Default value is false # REDIRECT_WWW=false +# How many workers to configure in nginx proxy. +# The more workers, the more requests will be handled +# Default value is 10240 +# WORKER_CONNECTIONS=10240 + # Access restrictions # In this section you will be able to restrict the IPs from which you can access to # Openvidu API and the Administration Panel diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 034d6035..71c0ac62 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -22,10 +22,10 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server-pro:2.16.0-dev2 + image: openvidu/openvidu-server-pro:2.16.0-dev4 restart: on-failure network_mode: host - entrypoint: ['/bin/bash', '-c', 'export COTURN_IP=`/usr/local/bin/discover_my_public_ip.sh`; /usr/local/bin/entrypoint.sh'] + entrypoint: ['/usr/local/bin/entrypoint.sh'] volumes: - /var/run/docker.sock:/var/run/docker.sock - ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH} @@ -41,6 +41,7 @@ services: - KMS_URIS=[] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} + - COTURN_IP=${COTURN_IP:-auto-ipv4} - OPENVIDU_PRO_CLUSTER=true - OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana} - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} @@ -65,7 +66,7 @@ services: - DB_PASSWORD=${OPENVIDU_SECRET} - MIN_PORT=40000 - MAX_PORT=65535 - - TURN_PUBLIC_IP=auto + - TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4} nginx: image: openvidu/openvidu-proxy:4.0.0-dev4 @@ -74,6 +75,7 @@ services: volumes: - ./certificates:/etc/letsencrypt - ./owncert:/owncert + - ./custom-nginx-vhosts:/etc/nginx/vhost.d/ - ${OPENVIDU_RECORDING_CUSTOM_LAYOUT}:/opt/openvidu/custom-layout environment: - DOMAIN_OR_PUBLIC_IP=${DOMAIN_OR_PUBLIC_IP} @@ -87,6 +89,7 @@ services: - WITH_APP=true - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} - REDIRECT_WWW=${REDIRECT_WWW:-false} + - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0 diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index 0a4f48d9..232ca29e 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -95,6 +95,10 @@ new_ov_installation() { printf "\n => Creating folder 'owncert'..." mkdir "${OPENVIDU_FOLDER}/owncert" || fatal_error "Error while creating the folder 'owncert'" + # Create vhost nginx folder + printf "\n => Creating folder 'custom-nginx-vhosts'..." + mkdir "${OPENVIDU_FOLDER}/custom-nginx-vhosts" || fatal_error "Error while creating the folder 'custom-nginx-vhosts'" + # Ready to use printf '\n' printf '\n' diff --git a/openvidu-server/docker/openvidu-coturn/entrypoint.sh b/openvidu-server/docker/openvidu-coturn/entrypoint.sh index c5799225..36152330 100644 --- a/openvidu-server/docker/openvidu-coturn/entrypoint.sh +++ b/openvidu-server/docker/openvidu-coturn/entrypoint.sh @@ -5,7 +5,8 @@ DEBUG=${DEBUG:-false} [ "$DEBUG" == "true" ] && set -x #Check parameters -[[ "${TURN_PUBLIC_IP}" == "auto" ]] && export TURN_PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) +[[ "${TURN_PUBLIC_IP}" == "auto-ipv4" ]] && export TURN_PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) +[[ "${TURN_PUBLIC_IP}" == "auto-ipv6" ]] && export TURN_PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) echo "TURN public IP: ${TURN_PUBLIC_IP:-"empty"}" diff --git a/openvidu-server/docker/openvidu-proxy/Dockerfile b/openvidu-server/docker/openvidu-proxy/Dockerfile index b29fd066..3eb033f3 100644 --- a/openvidu-server/docker/openvidu-proxy/Dockerfile +++ b/openvidu-server/docker/openvidu-proxy/Dockerfile @@ -5,7 +5,9 @@ RUN apk update && \ apk add bash \ certbot \ openssl \ - apache2-utils && \ + apache2-utils \ + bind-tools \ + perl pcre grep && \ rm -rf /var/cache/apk/* # Default nginx conf @@ -14,9 +16,15 @@ COPY ./default_nginx_conf /default_nginx_conf # Entrypoint and discover public ip scripts COPY ./discover_my_public_ip.sh /usr/local/bin + +# Copy nginx.conf +COPY ./nginx.conf /etc/nginx/nginx.conf + +# Entrypoint COPY ./entrypoint.sh /usr/local/bin RUN mkdir -p /var/www/certbot && \ + mkdir -p /etc/nginx/vhost.d/ && \ chmod +x /usr/local/bin/entrypoint.sh && \ chmod +x /usr/local/bin/discover_my_public_ip.sh diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf deleted file mode 100644 index efc7d333..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default-app.conf +++ /dev/null @@ -1,33 +0,0 @@ -{app_upstream} - -upstream openviduserver { - server localhost:5443; -} - -server { - listen {https_port} ssl; - server_name {domain_name}; - - {ssl_config} - - {proxy_config} - - {app_config} - - ######################## - # OpenVidu Locations # - ######################## - {common_api_ce} - - {deprecated_api_ce} - - {new_api_ce} - - ################################# - # LetsEncrypt # - ################################# - location /.well-known/acme-challenge { - root /var/www/certbot; - try_files $uri $uri/ =404; - } -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default.conf index 6afc2bbd..d7ad3644 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/ce/default.conf @@ -1,3 +1,9 @@ +{app_upstream} + +upstream openviduserver { + server localhost:5443; +} + server { listen {http_port}; server_name {domain_name}; @@ -11,4 +17,38 @@ server { location /.well-known/acme-challenge/ { root /var/www/certbot; } + + {nginx_status} +} + +{redirect_www} + +{redirect_www_ssl} + +server { + listen {https_port} ssl; + server_name {domain_name}; + + {ssl_config} + + {proxy_config} + + {app_config} + + ######################## + # OpenVidu Locations # + ######################## + {common_api_ce} + + {deprecated_api_ce} + + {new_api_ce} + + ################################# + # LetsEncrypt # + ################################# + location /.well-known/acme-challenge { + root /var/www/certbot; + try_files $uri $uri/ =404; + } } diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config.conf new file mode 100644 index 00000000..2dd7bcee --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config.conf @@ -0,0 +1,4 @@ + # Your App + location / { + proxy_pass http://yourapp; # Openvidu call by default + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config_default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config_default.conf new file mode 100644 index 00000000..82f76720 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_config_default.conf @@ -0,0 +1,2 @@ + # Welcome + root /var/www/html; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_upstream.conf similarity index 100% rename from openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/upstream-yourapp.conf rename to openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/app_upstream.conf diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/common_api_ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/common_api_ce.conf new file mode 100644 index 00000000..1ac0df12 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/common_api_ce.conf @@ -0,0 +1,14 @@ + ################################# + # Common rules # + ################################# + # Dashboard rule + location /dashboard { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + # Websocket rule + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/deprecated_api_ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/deprecated_api_ce.conf new file mode 100644 index 00000000..a572356d --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/deprecated_api_ce.conf @@ -0,0 +1,40 @@ + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/new_api_ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/new_api_ce.conf new file mode 100644 index 00000000..4b9d940b --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/new_api_ce.conf @@ -0,0 +1,33 @@ + ################################# + # New API # + ################################# + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/redirect_www.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/redirect_www.conf new file mode 100644 index 00000000..bdff866e --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ce/redirect_www.conf @@ -0,0 +1,14 @@ +server { + listen {http_port}; + server_name www.{domain_name}; + + # Redirect to https + location / { + rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; + } + + # letsencrypt + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf deleted file mode 100644 index eaef697f..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/default-root.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Welcome -root /var/www/html; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf deleted file mode 100644 index 1f714085..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/location-yourapp.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Your App -location / { - proxy_pass http://yourapp; # Openvidu call by default -} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf deleted file mode 100644 index e5609e8d..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/common-api-ce.conf +++ /dev/null @@ -1,14 +0,0 @@ -################################# -# Common rules # -################################# -# Dashboard rule -location /dashboard { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -# Websocket rule -location ~ /openvidu$ { - proxy_pass http://openviduserver; -} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf deleted file mode 100644 index f8406500..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/deprecated-api-ce.conf +++ /dev/null @@ -1,40 +0,0 @@ -################################# -# Deprecated API # -################################# -# Openvidu Server -location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; -} - -location /recordings { - proxy_pass http://openviduserver; -} - -location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /accept-certificate { - proxy_pass http://openviduserver; -} - -location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf deleted file mode 100644 index 992eb7db..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-ce/new-api-ce.conf +++ /dev/null @@ -1,33 +0,0 @@ -################################# -# New API # -################################# -location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; -} - -location /openvidu/recordings { - proxy_pass http://openviduserver; -} - -location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -location /openvidu/accept-certificate { - proxy_pass http://openviduserver; -} - -location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf deleted file mode 100644 index ea22f7de..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/common-api-pro.conf +++ /dev/null @@ -1,27 +0,0 @@ -################################# -# Common rules # -################################# -location /dashboard { - {rules_access_dashboard} - deny all; - rewrite ^/dashboard/(.*)$ /$1 break; - proxy_pass http://openviduserver/; -} - -location /inspector { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -location ~ /openvidu$ { - proxy_pass http://openviduserver; -} - -location /kibana { - {rules_access_dashboard} - deny all; - - rewrite ^/kibana/(.*)$ /$1 break; - proxy_pass http://kibana/; -} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf deleted file mode 100644 index 95fe3481..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/deprecated-api-pro.conf +++ /dev/null @@ -1,59 +0,0 @@ -################################# -# Deprecated API # -################################# -# Openvidu Server -location /layouts/custom { - rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; -} - -location /recordings { - proxy_pass http://openviduserver; -} - -location /api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -location /config { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /accept-certificate { - proxy_pass http://openviduserver; -} - -location /cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -# Openvidu Server Pro -location /pro { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /api-login { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /elasticsearch { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf deleted file mode 100644 index ef33eba1..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/locations-pro/new-api-pro.conf +++ /dev/null @@ -1,46 +0,0 @@ -################################# -# New API # -################################# -# OpenVidu Server -location /openvidu/layouts { - rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; - root /opt/openvidu; -} - -location /openvidu/recordings { - proxy_pass http://openviduserver; -} - -location /openvidu/api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /openvidu/info { - {rules_access_dashboard} - deny all; - proxy_pass http://openviduserver; -} - -location /openvidu/accept-certificate { - proxy_pass http://openviduserver; -} - -location /openvidu/cdr { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} -# OpenVidu Server PRO -location /openvidu/elk { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} - -location /openvidu/inspector-api { - {rules_acess_api} - deny all; - proxy_pass http://openviduserver; -} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/nginx_status.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/nginx_status.conf new file mode 100644 index 00000000..be33d323 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/nginx_status.conf @@ -0,0 +1,5 @@ + location /nginx_status { + stub_status; + allow 127.0.0.1; #only allow requests from localhost + deny all; #deny all other hosts + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/common_api_pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/common_api_pro.conf new file mode 100644 index 00000000..6df8b233 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/common_api_pro.conf @@ -0,0 +1,27 @@ + ################################# + # Common rules # + ################################# + location /dashboard { + {rules_access_dashboard} + deny all; + rewrite ^/dashboard/(.*)$ /$1 break; + proxy_pass http://openviduserver/; + } + + location /inspector { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location ~ /openvidu$ { + proxy_pass http://openviduserver; + } + + location /kibana { + {rules_access_dashboard} + deny all; + + rewrite ^/kibana/(.*)$ /$1 break; + proxy_pass http://kibana/; + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/deprecated_api_pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/deprecated_api_pro.conf new file mode 100644 index 00000000..1c8a45eb --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/deprecated_api_pro.conf @@ -0,0 +1,59 @@ + ################################# + # Deprecated API # + ################################# + # Openvidu Server + location /layouts/custom { + rewrite ^/layouts/custom/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /recordings { + proxy_pass http://openviduserver; + } + + location /api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /config { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /accept-certificate { + proxy_pass http://openviduserver; + } + + location /cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + # Openvidu Server Pro + location /pro { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /api-login { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /elasticsearch { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/new_api_pro.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/new_api_pro.conf new file mode 100644 index 00000000..ea426b5c --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/new_api_pro.conf @@ -0,0 +1,46 @@ + ################################# + # New API # + ################################# + # OpenVidu Server + location /openvidu/layouts { + rewrite ^/openvidu/layouts/(.*)$ /custom-layout/$1 break; + root /opt/openvidu; + } + + location /openvidu/recordings { + proxy_pass http://openviduserver; + } + + location /openvidu/api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/info { + {rules_access_dashboard} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/accept-certificate { + proxy_pass http://openviduserver; + } + + location /openvidu/cdr { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + # OpenVidu Server PRO + location /openvidu/elk { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } + + location /openvidu/inspector-api { + {rules_acess_api} + deny all; + proxy_pass http://openviduserver; + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/redirect_www.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/redirect_www.conf new file mode 100644 index 00000000..bd17a798 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/pro/redirect_www.conf @@ -0,0 +1,3 @@ + if ($host = www.{domain_name}) { + rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; + } \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf deleted file mode 100644 index 197cdab3..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy.conf +++ /dev/null @@ -1,13 +0,0 @@ -# Proxy -proxy_set_header Host $host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -proxy_set_header X-Forwarded-Proto $scheme; -proxy_set_header X-Forwarded-Proto https; -proxy_headers_hash_bucket_size 512; -proxy_redirect off; - -# Websockets -proxy_http_version 1.1; -proxy_set_header Upgrade $http_upgrade; -proxy_set_header Connection "upgrade"; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy_config.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy_config.conf new file mode 100644 index 00000000..9c3add1c --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/proxy_config.conf @@ -0,0 +1,13 @@ + # Proxy + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Proto https; + proxy_headers_hash_bucket_size 512; + proxy_redirect off; + + # Websockets + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/redirect_www_ssl.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/redirect_www_ssl.conf new file mode 100644 index 00000000..fd1c7803 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/redirect_www_ssl.conf @@ -0,0 +1,18 @@ +server { + listen 443 ssl; + server_name www.{domain_name}; + + {ssl_config} + + {proxy_config} + + # Redirect to non-www + location / { + rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; + } + + # letsencrypt + location /.well-known/acme-challenge/ { + root /var/www/certbot; + } +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf deleted file mode 100644 index 38395628..00000000 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl.conf +++ /dev/null @@ -1,14 +0,0 @@ -# SSL Config -ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; -ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; - -ssl_session_cache shared:SSL:50m; -ssl_session_timeout 5m; -ssl_stapling on; -ssl_stapling_verify on; - -ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; -ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; - -ssl_prefer_server_ciphers on; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl_config.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl_config.conf new file mode 100644 index 00000000..ae29491c --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/global/ssl_config.conf @@ -0,0 +1,14 @@ + # SSL Config + ssl_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{domain_name}/privkey.pem; + ssl_trusted_certificate /etc/letsencrypt/live/{domain_name}/fullchain.pem; + + ssl_session_cache shared:SSL:50m; + ssl_session_timeout 5m; + ssl_stapling on; + ssl_stapling_verify on; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + + ssl_prefer_server_ciphers on; \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf index 510d59e6..7566442a 100644 --- a/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf +++ b/openvidu-server/docker/openvidu-proxy/default_nginx_conf/pro/default.conf @@ -12,11 +12,15 @@ upstream openviduserver { server localhost:5443; } +{redirect_www_ssl} + server { # Redirect to https if ($host = {domain_name}) { rewrite ^(.*) https://{domain_name}:{https_port}$1 permanent; } # managed by Certbot + + {redirect_www} listen {http_port} default_server; server_name {domain_name}; @@ -38,6 +42,8 @@ server { rewrite ^/kibana/(.*)$ /$1 break; proxy_pass http://kibana/; } + + {nginx_status} } server { diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index e975e800..1b72f4e3 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -38,7 +38,10 @@ CERTIFICATES_CONF="${CERTIFICATES_LIVE_FOLDER}/certificates.conf" [ -z "${PROXY_HTTPS_PORT}" ] && export PROXY_HTTPS_PORT=443 [ -z "${WITH_APP}" ] && export WITH_APP=true [ -z "${SUPPORT_DEPRECATED_API}" ] && export SUPPORT_DEPRECATED_API=true +[ -z "${REDIRECT_WWW}" ] && export REDIRECT_WWW=false [ -z "${PROXY_MODE}" ] && export PROXY_MODE=CE +[ -z "${WORKER_CONNECTIONS}" ] && export WORKER_CONNECTIONS=10240 +[ -z "${PUBLIC_IP}" ] && export PUBLIC_IP=auto-ipv4 [ -z "${ALLOWED_ACCESS_TO_DASHBOARD}" ] && export ALLOWED_ACCESS_TO_DASHBOARD=all [ -z "${ALLOWED_ACCESS_TO_RESTAPI}" ] && export ALLOWED_ACCESS_TO_RESTAPI=all @@ -51,8 +54,10 @@ printf "\n" printf "\n Config NGINX:" printf "\n - Http Port: %s" "${PROXY_HTTP_PORT}" printf "\n - Https Port: %s" "${PROXY_HTTPS_PORT}" +printf "\n - Worker Connections: %s" "${WORKER_CONNECTIONS}" printf "\n - Allowed Access in Openvidu Dashboard: %s" "${ALLOWED_ACCESS_TO_DASHBOARD}" printf "\n - Allowed Access in Openvidu API: %s" "${ALLOWED_ACCESS_TO_RESTAPI}" +printf "\n - Redirect www to non-www: %s" "${REDIRECT_WWW}" printf "\n" printf "\n Config Openvidu Application:" printf "\n - Domain name: %s" "${DOMAIN_OR_PUBLIC_IP}" @@ -67,6 +72,9 @@ printf "\n = CONFIGURATION NGINX =" printf "\n =======================================" printf "\n" +# Override worker connections +sed -i "s/{worker_connections}/${WORKER_CONNECTIONS}/g" /etc/nginx/nginx.conf + printf "\n Configure %s domain..." "${DOMAIN_OR_PUBLIC_IP}" OLD_DOMAIN_OR_PUBLIC_IP=$(head -n 1 "${CERTIFICATES_CONF}" | cut -f1 -d$'\t') CERTIFICATED_OLD_CONFIG=$(head -n 1 "${CERTIFICATES_CONF}" | cut -f2 -d$'\t') @@ -74,9 +82,9 @@ CERTIFICATED_OLD_CONFIG=$(head -n 1 "${CERTIFICATES_CONF}" | cut -f2 -d$'\t') printf "\n - New configuration: %s %s" "${CERTIFICATE_TYPE}" "${DOMAIN_OR_PUBLIC_IP}" if [ -z "${CERTIFICATED_OLD_CONFIG}" ]; then - printf "\n - Old configuration: none" + printf "\n - Old configuration: none\n" else - printf "\n - Old configuration: %s %s" "${CERTIFICATED_OLD_CONFIG}" "${OLD_DOMAIN_OR_PUBLIC_IP}" + printf "\n - Old configuration: %s %s\n" "${CERTIFICATED_OLD_CONFIG}" "${OLD_DOMAIN_OR_PUBLIC_IP}" if [ "${CERTIFICATED_OLD_CONFIG}" != "${CERTIFICATE_TYPE}" ] || \ [ "${OLD_DOMAIN_OR_PUBLIC_IP}" != "${DOMAIN_OR_PUBLIC_IP}" ]; then @@ -161,34 +169,14 @@ chmod -R 777 /etc/letsencrypt # Use certificates in folder '/default_nginx_conf' if [ "${PROXY_MODE}" == "CE" ]; then - if [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then - mv /default_nginx_conf/ce/support_deprecated_api/default-app.conf /default_nginx_conf/default-app.conf - elif [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then - mv /default_nginx_conf/ce/default-app.conf /default_nginx_conf/default-app.conf - elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then - mv /default_nginx_conf/ce/support_deprecated_api/default-app-without-demos.conf /default_nginx_conf/default-app.conf - elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then - mv /default_nginx_conf/ce/default-app-without-demos.conf /default_nginx_conf/default-app.conf - fi - mv /default_nginx_conf/ce/default.conf /default_nginx_conf/default.conf - - rm -rf /default_nginx_conf/ce - rm -rf /default_nginx_conf/pro + # Remove previous configuration + [[ -f /default_nginx_conf/default.conf ]] && rm /default_nginx_conf/default.conf + cp /default_nginx_conf/ce/default.conf /default_nginx_conf/default.conf fi if [ "${PROXY_MODE}" == "PRO" ]; then - if [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then - mv /default_nginx_conf/pro/support_deprecated_api/default.conf /default_nginx_conf/default.conf - elif [ "${WITH_APP}" == "true" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then - mv /default_nginx_conf/pro/default.conf /default_nginx_conf/default.conf - elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "true" ]; then - mv /default_nginx_conf/pro/support_deprecated_api/default-app-without-demos.conf /default_nginx_conf/default.conf - elif [ "${WITH_APP}" == "false" ] && [ "${SUPPORT_DEPRECATED_API}" == "false" ]; then - mv /default_nginx_conf/pro/default-app-without-demos.conf /default_nginx_conf/default.conf - fi - - rm -rf /default_nginx_conf/ce - rm -rf /default_nginx_conf/pro +[[ -f /default_nginx_conf/default.conf ]] && rm /default_nginx_conf/default.conf + cp /default_nginx_conf/pro/default.conf /default_nginx_conf/default.conf fi # Create index.html @@ -199,7 +187,50 @@ EOF # Load nginx conf files rm /etc/nginx/conf.d/* -cp /default_nginx_conf/* /etc/nginx/conf.d +cp /default_nginx_conf/default* /etc/nginx/conf.d + +# Replace config files +sed -e '/{ssl_config}/{r default_nginx_conf/global/ssl_config.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{proxy_config}/{r default_nginx_conf/global/proxy_config.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{nginx_status}/{r default_nginx_conf/global/nginx_status.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{common_api_ce}/{r default_nginx_conf/global/ce/common_api_ce.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{new_api_ce}/{r default_nginx_conf/global/ce/new_api_ce.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{common_api_pro}/{r default_nginx_conf/global/pro/common_api_pro.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{new_api_pro}/{r default_nginx_conf/global/pro/new_api_pro.conf' -e 'd}' -i /etc/nginx/conf.d/* + +if [[ "${WITH_APP}" == "true" ]]; then + sed -e '/{app_upstream}/{r default_nginx_conf/global/app_upstream.conf' -e 'd}' -i /etc/nginx/conf.d/* + sed -e '/{app_config}/{r default_nginx_conf/global/app_config.conf' -e 'd}' -i /etc/nginx/conf.d/* +elif [[ "${WITH_APP}" == "false" ]]; then + sed -i '/{app_upstream}/d' /etc/nginx/conf.d/* + sed -e '/{app_config}/{r default_nginx_conf/global/app_config_default.conf' -e 'd}' -i /etc/nginx/conf.d/* +fi + +if [[ "${SUPPORT_DEPRECATED_API}" == "true" ]]; then + sed -e '/{deprecated_api_ce}/{r default_nginx_conf/global/ce/deprecated_api_ce.conf' -e 'd}' -i /etc/nginx/conf.d/* + sed -e '/{deprecated_api_pro}/{r default_nginx_conf/global/pro/deprecated_api_pro.conf' -e 'd}' -i /etc/nginx/conf.d/* +elif [[ "${SUPPORT_DEPRECATED_API}" == "false" ]]; then + sed -i '/{deprecated_api_ce}/d' /etc/nginx/conf.d/* + sed -i '/{deprecated_api_pro}/d' /etc/nginx/conf.d/* +fi + +if [[ "${REDIRECT_WWW}" == "true" ]]; then + sed -e '/{redirect_www_ssl}/{r default_nginx_conf/global/redirect_www_ssl.conf' -e 'd}' -i /etc/nginx/conf.d/* + if [[ "${PROXY_MODE}" == "CE" ]]; then + sed -e '/{redirect_www}/{r default_nginx_conf/global/ce/redirect_www.conf' -e 'd}' -i /etc/nginx/conf.d/* + fi + + if [ "${PROXY_MODE}" == "PRO" ]; then + sed -e '/{redirect_www}/{r default_nginx_conf/global/pro/redirect_www.conf' -e 'd}' -i /etc/nginx/conf.d/* + fi +elif [[ "${REDIRECT_WWW}" == "false" ]]; then + sed -i '/{redirect_www}/d' /etc/nginx/conf.d/* + sed -i '/{redirect_www_ssl}/d' /etc/nginx/conf.d/* +fi + +# Process main configs +sed -e '/{ssl_config}/{r default_nginx_conf/global/ssl_config.conf' -e 'd}' -i /etc/nginx/conf.d/* +sed -e '/{proxy_config}/{r default_nginx_conf/global/proxy_config.conf' -e 'd}' -i /etc/nginx/conf.d/* sed -i "s/{domain_name}/${DOMAIN_OR_PUBLIC_IP}/g" /etc/nginx/conf.d/* sed -i "s/{http_port}/${PROXY_HTTP_PORT}/g" /etc/nginx/conf.d/* sed -i "s/{https_port}/${PROXY_HTTPS_PORT}/g" /etc/nginx/conf.d/* @@ -212,8 +243,6 @@ printf "\n =======================================" printf "\n" printf "\n Adding rules..." -LOCAL_NETWORKS=$(ip route list | grep -Eo '([0-9]*\.){3}[0-9]*/[0-9]*') -PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) valid_ip_v4() { @@ -237,6 +266,23 @@ valid_ip_v6() fi } +LOCAL_NETWORKS=$(ip route list | grep -Eo '([0-9]*\.){3}[0-9]*/[0-9]*') +if [[ "${PUBLIC_IP}" == "auto-ipv4" ]]; then + PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh) + printf "\n - Public IPv4 for rules: %s" "$PUBLIC_IP" +elif [[ "${PUBLIC_IP}" == "auto-ipv6" ]]; then + PUBLIC_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) + printf "\n - Public IPv6 for rules: %s" "$PUBLIC_IP" +else + if valid_ip_v4 "$PUBLIC_IP"; then + printf "\n - Valid defined public IPv4: %s" "$PUBLIC_IP" + elif valid_ip_v6 "$PUBLIC_IP"; then + printf "\n - Valid defined public IPv6: %s" "$PUBLIC_IP" + else + printf "\n - Not valid defined IP Address: %s" "$PUBLIC_IP" + fi +fi + if [ "${ALLOWED_ACCESS_TO_DASHBOARD}" != "all" ]; then IFS=',' for IP in $(echo "${ALLOWED_ACCESS_TO_DASHBOARD}" | tr -d '[:space:]') @@ -302,7 +348,7 @@ else fi if [ "${RULES_DASHBOARD}" != "allow all;" ]; then - if ! echo "${RULES_DASHBOARD}" | grep -q "$PUBLIC_IP" && valid_ip_v4 "$PUBLIC_IP" || valid_ip_v6 "$IP"; then + if ! echo "${RULES_DASHBOARD}" | grep -q "$PUBLIC_IP" && valid_ip_v4 "$PUBLIC_IP" || valid_ip_v6 "$PUBLIC_IP"; then RULES_DASHBOARD="${RULES_DASHBOARD}{new_line}allow $PUBLIC_IP;" fi @@ -320,7 +366,7 @@ if [ "${RULES_DASHBOARD}" != "allow all;" ]; then fi if [ "${RULES_RESTAPI}" != "allow all;" ]; then - if ! echo "${RULES_RESTAPI}" | grep -q "$PUBLIC_IP" && valid_ip_v4 "$PUBLIC_IP" || valid_ip_v6 "$IP"; then + if ! echo "${RULES_RESTAPI}" | grep -q "$PUBLIC_IP" && valid_ip_v4 "$PUBLIC_IP" || valid_ip_v6 "$PUBLIC_IP"; then RULES_RESTAPI="${RULES_RESTAPI}{new_line}allow $PUBLIC_IP;" fi diff --git a/openvidu-server/docker/openvidu-proxy/nginx.conf b/openvidu-server/docker/openvidu-proxy/nginx.conf new file mode 100644 index 00000000..8e1d6549 --- /dev/null +++ b/openvidu-server/docker/openvidu-proxy/nginx.conf @@ -0,0 +1,32 @@ +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + + +events { + worker_connections {worker_connections}; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/vhost.d/*.conf; +} \ No newline at end of file diff --git a/openvidu-server/docker/openvidu-proxy/test.sh b/openvidu-server/docker/openvidu-proxy/test.sh deleted file mode 100644 index e69de29b..00000000 diff --git a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh index 468e4812..6aca96dc 100755 --- a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh @@ -23,6 +23,14 @@ printf "\n = LAUNCH OPENVIDU-SERVER =" printf "\n =======================================" printf "\n" +# Get coturn public ip +[[ -z ${COTURN_IP} ]] && export COTURN_IP=auto-ipv4 +if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then + COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) +elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then + COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) +fi + if [ ! -z "${JAVA_OPTIONS}" ]; then printf "\n Using java options: %s" "${JAVA_OPTIONS}" fi diff --git a/openvidu-server/docker/openvidu-server/entrypoint.sh b/openvidu-server/docker/openvidu-server/entrypoint.sh index be6b71d0..624fe7f8 100644 --- a/openvidu-server/docker/openvidu-server/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server/entrypoint.sh @@ -6,6 +6,14 @@ printf "\n = LAUNCH OPENVIDU-SERVER =" printf "\n =======================================" printf "\n" +# Get coturn public ip +[[ -z ${COTURN_IP} ]] && export COTURN_IP=auto-ipv4 +if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then + COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) +elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then + COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) +fi + if [ ! -z "${JAVA_OPTIONS}" ]; then printf "\n Using java options: %s" "${JAVA_OPTIONS}" fi diff --git a/openvidu-server/docker/utils/discover_my_public_ip.sh b/openvidu-server/docker/utils/discover_my_public_ip.sh index b42b3a97..e8227993 100755 --- a/openvidu-server/docker/utils/discover_my_public_ip.sh +++ b/openvidu-server/docker/utils/discover_my_public_ip.sh @@ -1,47 +1,116 @@ -#!/bin/bash +#!/usr/bin/env bash -# Check if a txt is a valid ip -function valid_ip() -{ - local ip=$1 - local stat=1 +#/ Use DNS to find out about the external IP of the running system. +#/ +#/ This script is useful when running from a machine that sits behind a NAT. +#/ Due to how NAT works, machines behind it belong to an internal or private +#/ subnet, with a different address space than the external or public side. +#/ +#/ Typically it is possible to make an HTTP request to a number of providers +#/ that offer the external IP in their response body (eg: ifconfig.me). However, +#/ why do a slow and heavy HTTP request, when DNS exists and is much faster? +#/ Well established providers such as OpenDNS or Google offer special hostnames +#/ that, when resolved, will actually return the IP address of the caller. +#/ +#/ https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script/81699#81699 +#/ +#/ +#/ Arguments +#/ --------- +#/ +#/ --ipv4 +#/ +#/ Find the external IPv4 address. +#/ Optional. Default: Enabled. +#/ +#/ --ipv6 +#/ +#/ Find the external IPv6 address. +#/ Optional. Default: Disabled. - if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then - OIFS=$IFS - IFS='.' - ip=($ip) - IFS=$OIFS - [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ - && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] - stat=$? - fi - return $stat + + +# Shell setup +# =========== + +# Bash options for strict error checking. +set -o errexit -o errtrace -o pipefail -o nounset + +# Trace all commands (to stderr). +#set -o xtrace + +# Trap function for unhandled errors. +function on_error() { + echo "[getmyip] ERROR ($?)" >&2 + exit 1 } +trap on_error ERR -# Services to get public ip -SERVICES=( - "curl --silent -sw :%{http_code} ipv4.icanhazip.com" - "curl --silent -sw :%{http_code} ifconfig.me" - "curl --silent -sw :%{http_code} -4 ifconfig.co" - "curl --silent -sw :%{http_code} ipecho.net/plain" - "curl --silent -sw :%{http_code} ipinfo.io/ip" - "curl --silent -sw :%{http_code} checkip.amazonaws.com" - "curl --silent -sw :%{http_code} v4.ident.me" -) -# Get public ip -for service in "${SERVICES[@]}"; do - RUN_COMMAND=$($service | tr -d '[:space:]') - IP=$(echo "$RUN_COMMAND" | cut -d':' -f1) - HTTP_CODE=$(echo "$RUN_COMMAND" | cut -d':' -f2) - if [ "$HTTP_CODE" == "200" ]; then - if valid_ip "$IP"; then - printf "%s" "$IP" - exit 0 - fi +# Parse call arguments +# ==================== + +CFG_IPV4="true" +CFG_IPV6="false" + +while [[ $# -gt 0 ]]; do + case "${1-}" in + --ipv4) + CFG_IPV4="true" + CFG_IPV6="false" + ;; + --ipv6) + CFG_IPV4="false" + CFG_IPV6="true" + ;; + *) + echo "Invalid argument: '${1-}'" >&2 + exit 1 + ;; + esac + shift +done + + + +# Obtain the external IP address +# ============================== + +if [[ "$CFG_IPV4" == "true" ]]; then + COMMANDS=( + 'dig @resolver1.opendns.com myip.opendns.com A -4 +short' + 'dig @ns1.google.com o-o.myaddr.l.google.com TXT -4 +short | tr -d \"' + 'dig @1.1.1.1 whoami.cloudflare TXT CH -4 +short | tr -d \"' + 'dig @ns1-1.akamaitech.net whoami.akamai.net A -4 +short' + ) + + function is_valid_ip() { + # Check if the input looks like an IPv4 address. + # Doesn't check if the actual values are valid; assumes they are. + echo "$1" | grep --perl-regexp --quiet '^(\d{1,3}\.){3}\d{1,3}$' + } +elif [[ "$CFG_IPV6" == "true" ]]; then + COMMANDS=( + 'dig @resolver1.opendns.com myip.opendns.com AAAA -6 +short' + 'dig @ns1.google.com o-o.myaddr.l.google.com TXT -6 +short | tr -d \"' + 'dig @2606:4700:4700::1111 whoami.cloudflare TXT CH -6 +short | tr -d \"' + ) + + function is_valid_ip() { + # Check if the input looks like an IPv6 address. + # It's almost impossible to check the IPv6 representation because it + # varies wildly, so just check that there are at least 2 colons. + [[ "$(echo "$1" | awk -F':' '{print NF-1}')" -ge 2 ]] + } +fi + +for COMMAND in "${COMMANDS[@]}"; do + if IP="$(eval "$COMMAND")" && is_valid_ip "$IP"; then + echo "$IP" + exit 0 fi done -printf "error" -exit 0 \ No newline at end of file +echo "[getmyip] All providers failed" >&2 +exit 1 \ No newline at end of file From b9de4f38befbe9cb7112e99e96152fe105b83cd9 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 20:30:36 +0100 Subject: [PATCH 190/435] openvidu-deployment: Typo entrypoint.sh --- openvidu-server/docker/openvidu-server-pro/entrypoint.sh | 2 +- openvidu-server/docker/openvidu-server/entrypoint.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh index 6aca96dc..91fc95ef 100755 --- a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh @@ -24,7 +24,7 @@ printf "\n =======================================" printf "\n" # Get coturn public ip -[[ -z ${COTURN_IP} ]] && export COTURN_IP=auto-ipv4 +[[ -z "${COTURN_IP}" ]] && export COTURN_IP=auto-ipv4 if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then diff --git a/openvidu-server/docker/openvidu-server/entrypoint.sh b/openvidu-server/docker/openvidu-server/entrypoint.sh index 624fe7f8..c69bd68e 100644 --- a/openvidu-server/docker/openvidu-server/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server/entrypoint.sh @@ -7,7 +7,7 @@ printf "\n =======================================" printf "\n" # Get coturn public ip -[[ -z ${COTURN_IP} ]] && export COTURN_IP=auto-ipv4 +[[ -z "${COTURN_IP}" ]] && export COTURN_IP=auto-ipv4 if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then From 553e63513c8ccde2865a593f8ac47b13774766fe Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 20:41:13 +0100 Subject: [PATCH 191/435] openvidu-deployment: install dnsutils in openvidu-server, openvidu-server-pro and coturn to use dig --- openvidu-server/docker/openvidu-coturn/Dockerfile | 2 +- openvidu-server/docker/openvidu-server-pro/Dockerfile | 1 + openvidu-server/docker/openvidu-server/Dockerfile | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/openvidu-server/docker/openvidu-coturn/Dockerfile b/openvidu-server/docker/openvidu-coturn/Dockerfile index dbd24bc5..bcaf1acd 100644 --- a/openvidu-server/docker/openvidu-coturn/Dockerfile +++ b/openvidu-server/docker/openvidu-coturn/Dockerfile @@ -1,7 +1,7 @@ FROM ubuntu:16.04 RUN apt-get update \ - && apt-get install -y coturn curl + && apt-get install -y coturn curl dnsutils COPY ./configuration-files.sh /tmp/ COPY ./entrypoint.sh /usr/local/bin diff --git a/openvidu-server/docker/openvidu-server-pro/Dockerfile b/openvidu-server/docker/openvidu-server-pro/Dockerfile index 24be405c..ed71196b 100644 --- a/openvidu-server/docker/openvidu-server-pro/Dockerfile +++ b/openvidu-server/docker/openvidu-server-pro/Dockerfile @@ -11,6 +11,7 @@ RUN apt-get update && apt-get install -y \ jq \ docker.io \ ethtool \ + dnsutils \ && rm -rf /var/lib/apt/lists/* RUN mkdir -p /opt/openvidu /usr/local/bin/ diff --git a/openvidu-server/docker/openvidu-server/Dockerfile b/openvidu-server/docker/openvidu-server/Dockerfile index 506a88f7..8b23b3a7 100644 --- a/openvidu-server/docker/openvidu-server/Dockerfile +++ b/openvidu-server/docker/openvidu-server/Dockerfile @@ -8,6 +8,7 @@ RUN apt-get update && apt-get install -y \ openjdk-8-jre \ coturn \ redis-tools \ + dnsutils \ && rm -rf /var/lib/apt/lists/* # Copy OpenVidu Server From 76805ff54354e2409ca05706f59fecc04c5bef05 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 21:15:18 +0100 Subject: [PATCH 192/435] Minor fix entrypoint openvidu-server and openvidu-server-pro docker images --- openvidu-server/docker/openvidu-server-pro/entrypoint.sh | 4 ++-- openvidu-server/docker/openvidu-server/entrypoint.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh index 91fc95ef..3f94b5ee 100755 --- a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh @@ -25,9 +25,9 @@ printf "\n" # Get coturn public ip [[ -z "${COTURN_IP}" ]] && export COTURN_IP=auto-ipv4 -if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then +if [[ "${COTURN_IP}" == "auto-ipv4" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) -elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then +elif [[ "${COTURN_IP}" == "auto-ipv6" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) fi diff --git a/openvidu-server/docker/openvidu-server/entrypoint.sh b/openvidu-server/docker/openvidu-server/entrypoint.sh index c69bd68e..5ba7d1c9 100644 --- a/openvidu-server/docker/openvidu-server/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server/entrypoint.sh @@ -8,9 +8,9 @@ printf "\n" # Get coturn public ip [[ -z "${COTURN_IP}" ]] && export COTURN_IP=auto-ipv4 -if [[ -z "${COTURN_IP}" == "auto-ipv4" ]]; then +if [[ "${COTURN_IP}" == "auto-ipv4" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh) -elif [[ -z "${COTURN_IP}" == "auto-ipv6" ]]; then +elif [[ "${COTURN_IP}" == "auto-ipv6" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) fi From fd1d7bc31313552fcb8af37ad350051c06c6ffa2 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 22:48:33 +0100 Subject: [PATCH 193/435] Change call version to 2.16.0-dev1 --- .../deployments/ce/docker-compose/docker-compose.override.yml | 2 +- .../openvidu-server-pro/docker-compose.override.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml index c52129f9..d1f07b76 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml @@ -13,7 +13,7 @@ services: # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.15.0 + image: openvidu/openvidu-call:2.16.0-dev1 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml index c52129f9..d1f07b76 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml @@ -13,7 +13,7 @@ services: # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.15.0 + image: openvidu/openvidu-call:2.16.0-dev1 restart: on-failure network_mode: host environment: From 3d3c2242a8f6be635966ea353a2a4030a8b57419 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 2 Nov 2020 23:00:25 +0100 Subject: [PATCH 194/435] openvidu-deployment: Let configure public ip via env variable in .env --- openvidu-server/deployments/ce/docker-compose/.env | 7 +++++++ .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/.env | 8 ++++++++ .../docker-compose/openvidu-server-pro/docker-compose.yml | 6 ++++-- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 86cba267..85e642ad 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -68,6 +68,13 @@ LETSENCRYPT_EMAIL=user@example.com # ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1, 198.51.100.0/24 # ALLOWED_ACCESS_TO_RESTAPI= +# Public IP used by coturn, nginx and openvidu-server +# Possible values: +# - auto-ipv4: Auto discover public IPv4 using dns services (Default) +# - auto-ipv6: Auto discover public IPv6 using dns services +# - Any valid IPv4 and IPv6 value +# PUBLIC_IP=auto-ipv4 + # Whether to enable recording module or not OPENVIDU_RECORDING=false diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 9bdc7081..95abdc28 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -39,7 +39,7 @@ services: - KMS_URIS=["ws://localhost:8888/kurento"] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} - - COTURN_IP=${COTURN_IP:-auto-ipv4} + - COTURN_IP=${PUBLIC_IP:-auto-ipv4} kms: image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index cb4e985a..74786e85 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -71,6 +71,14 @@ LETSENCRYPT_EMAIL=user@example.com # ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1, 198.51.100.0/24 # ALLOWED_ACCESS_TO_RESTAPI= +# Public IP used by coturn, nginx and openvidu-server +# Possible values: +# - auto-ipv4: Auto discover public IPv4 using dns services (Default) +# - auto-ipv6: Auto discover public IPv6 using dns services +# - Any valid IPv4 and IPv6 value +# PUBLIC_IP=auto-ipv4 + + # Mode of cluster management. Can be auto (OpenVidu manages Media Nodes on its own. # Parameter KMS_URIS is ignored) or manual (user must manage Media Nodes. Parameter # KMS_URIS is used: if any uri is provided it must be valid) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 71c0ac62..f6ff3cf7 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -41,7 +41,7 @@ services: - KMS_URIS=[] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} - - COTURN_IP=${COTURN_IP:-auto-ipv4} + - COTURN_IP=${PUBLIC_IP:-auto-ipv4} - OPENVIDU_PRO_CLUSTER=true - OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana} - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} @@ -66,7 +66,7 @@ services: - DB_PASSWORD=${OPENVIDU_SECRET} - MIN_PORT=40000 - MAX_PORT=65535 - - TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4} + - TURN_PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} nginx: image: openvidu/openvidu-proxy:4.0.0-dev4 @@ -90,6 +90,8 @@ services: - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} - REDIRECT_WWW=${REDIRECT_WWW:-false} - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} + - PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} + elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.8.0 From f54ebc285181f724efa9886b2dfff77cd1b38a06 Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 12:38:00 +0100 Subject: [PATCH 195/435] openvidu-deployment-pro: New media-node-controller 2.0.0-dev1 --- .../pro/docker-compose/media-node/.env | 30 ------------ .../media-node/beats/filebeat.yml | 16 ++++-- .../media-node/docker-compose.yml | 10 ++-- .../media-node/install_media_node.sh | 49 ++++++++++++------- 4 files changed, 47 insertions(+), 58 deletions(-) delete mode 100644 openvidu-server/deployments/pro/docker-compose/media-node/.env diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/.env b/openvidu-server/deployments/pro/docker-compose/media-node/.env deleted file mode 100644 index fd244380..00000000 --- a/openvidu-server/deployments/pro/docker-compose/media-node/.env +++ /dev/null @@ -1,30 +0,0 @@ -# KMS Configuration -# -------------------------- - -# NOTE: This file doesn't need to quote assignment values, like most shells do. -# All values are stored as-is, even if they contain spaces, so don't quote them. - -# Kurento Media Server image -# -------------------------- -# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server-dev -# Uncomment the next line and define this variable with KMS image that you want use -# KMS_IMAGE=kurento/kurento-media-server-dev:6.14.0 - -# Kurento Media Server Level logs -# ------------------------------- -# Uncomment the next line and define this variable to change -# the verbosity level of the logs of KMS -# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html -# KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4 - -# Metricbeat ElasticSearch Image -# ------------------------------- -# Docker hub kurento media server: https://www.docker.elastic.co/ -# Uncomment the next line and define this variable with METRICBEAT_IMAGE image that you want use -# METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0 - -# FileBeat ElasticSearch Image -# ------------------------------- -# Docker hub kurento media server: https://www.docker.elastic.co/ -# Uncomment the next line and define this variable with FILEBEAT_IMAGE image that you want use -# FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0 \ No newline at end of file diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml index 5a2f4f59..7a54ffaf 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/beats/filebeat.yml @@ -5,6 +5,14 @@ filebeat.inputs: multiline.pattern: '^\d*:\d*:\d*' multiline.negate: true multiline.match: after + - type: log + paths: + - /opt/openvidu/kurento-logs/*.log + fields: + kurento-media-server: true + ip: ${MEDIA_NODE_IP} + cluster-id: ${CLUSTER_ID} + fields_under_root: true processors: - add_docker_metadata: @@ -26,13 +34,13 @@ output: indices: - index: "filebeat-kurento-%{+yyyy.MM.dd}" when.or: - - contains: - container.image.name: kurento/kurento-media-server + - equals: + kurento-media-server: true pipelines: - pipeline: kurento-pipeline when.or: - - contains: - container.image.name: kurento/kurento-media-server + - equals: + kurento-media-server: true logging.json: true logging.metrics.enabled: false diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index 5e568d0b..7eb17be9 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -16,7 +16,7 @@ version: '3.1' services: media-node-controller: - image: openvidu/media-node-controller:1.0.0 + image: openvidu/media-node-controller:2.0.0-dev1 restart: always ulimits: core: -1 @@ -24,14 +24,14 @@ services: env_file: - .env environment: - - KMS_IMAGE=${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} - - KMS_DEBUG_LEVEL=${KMS_DEBUG_LEVEL:-} - - METRICBEAT_IMAGE=${METRICBEAT_IMAGE:-docker.elastic.co/beats/metricbeat-oss:7.8.0} - - FILEBEAT_IMAGE=${FILEBEAT_IMAGE:-docker.elastic.co/beats/filebeat-oss:7.8.0} + - KMS_IMAGE=kurento/kurento-media-server:6.14.0 + - METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0 + - FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0 ports: - 3000:3000 volumes: - /opt/openvidu/recordings:/opt/openvidu/recordings - /opt/openvidu/beats:/opt/openvidu/beats - /var/run/docker.sock:/var/run/docker.sock + - /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs - ./beats:/beats diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index 45e0eb89..693dc485 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -33,10 +33,6 @@ new_media_node_installation() { --output "${MEDIA_NODE_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'" printf '\n - docker-compose.yml' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/.env \ - --output "${MEDIA_NODE_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'" - printf '\n - .env' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/media_node \ --output "${MEDIA_NODE_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'" printf '\n - media_node' @@ -68,9 +64,9 @@ new_media_node_installation() { # Pull images printf "\n => Pulling images...\n" cd "${MEDIA_NODE_FOLDER}" || fatal_error "Error when moving to '${MEDIA_NODE_FOLDER}' folder" - KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') - METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') - FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') + KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | cut -d"=" -f2) + METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2) + FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | cut -d"=" -f2) docker pull $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE" docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_IMAGE" docker pull $FILEBEAT_IMAGE || fatal "Error while pulling docker image: $FILEBEAT_IMAGE" @@ -81,13 +77,25 @@ new_media_node_installation() { printf '\n =======================================' printf "\n Media Node successfully installed." printf '\n =======================================' - printf "\n" + printf '\n' printf '\n 1. Go to kms folder:' printf '\n $ cd kms' - printf "\n" + printf '\n' printf '\n 2. Start Media Node Controller' printf '\n $ ./media_node start' printf '\n' + printf '\n 3. Add the private ip of this media node in `KMS_URIS=[]` in OpenVidu Pro machine' + printf '\n in the file located at "/opt/openvidu/.env" with this format:' + printf '\n ...' + printf '\n KMS_URIS=["ws://:8888/kurento"]' + printf '\n ...' + printf '\n You can also add this node from inspector' + printf '\n After that start or restart OpenVidu Pro and all containers will be provisioned in all media nodes' + printf '\n automatically to all the media nodes configured in "KMS_URIS"' + printf '\n More info about Media Nodes deployment here:' + printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup" + printf '\n' + printf '\n' printf "\n For more information, check:" printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions" printf '\n' @@ -151,10 +159,6 @@ upgrade_media_node() { --output "${TMP_FOLDER}/docker-compose.yml" || fatal_error "Error when downloading the file 'docker-compose.yml'" printf '\n - docker-compose.yml' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/.env \ - --output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'" - printf '\n - .env' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/media-node/media_node \ --output "${TMP_FOLDER}/media_node" || fatal_error "Error when downloading the file 'media_node'" printf '\n - media_node' @@ -231,9 +235,6 @@ upgrade_media_node() { mv "${TMP_FOLDER}/docker-compose.yml" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'docker-compose.yml'" printf '\n - docker-compose.yml' - mv "${TMP_FOLDER}/.env" "${MEDIA_NODE_PREVIOUS_FOLDER}/.env-${MEDIA_NODE_VERSION}" || fatal_error "Error while moving previous '.env'" - printf '\n - .env-%s' "${MEDIA_NODE_VERSION}" - mv "${TMP_FOLDER}/media_node" "${MEDIA_NODE_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'media_node'" printf '\n - media_node' @@ -275,13 +276,23 @@ upgrade_media_node() { printf '\n' printf "\n 1. A new file 'docker-compose.yml' has been created with the new OpenVidu %s services" "${OPENVIDU_VERSION}" printf '\n' - printf "\n 2. The previous file '.env' remains intact, but a new file '.env-%s' has been created." "${OPENVIDU_VERSION}" - printf "\n Transfer any configuration you wish to keep in the upgraded version from '.env' to '.env-%s'." "${OPENVIDU_VERSION}" - printf "\n When you are OK with it, rename and leave as the only '.env' file of the folder the new '.env-%s'." "${OPENVIDU_VERSION}" + printf "\n 2. This new version %s does not need any .env file. Everything is configured from OpenVidu Pro" "${OPENVIDU_VERSION}" printf '\n' printf '\n 3. Start new version of Media Node' printf '\n $ ./media_node start' printf '\n' + printf '\n 4. Add the private ip of this media node in `KMS_URIS=[]` in OpenVidu Pro machine' + printf '\n in the file located at "/opt/openvidu/.env" with this format:' + printf '\n ...' + printf '\n KMS_URIS=["ws://:8888/kurento"]' + printf '\n ...' + printf '\n You can also add this node from inspector' + printf '\n After that start or restart OpenVidu Pro and all containers will be provisioned' + printf '\n automatically to all the media nodes configured in "KMS_URIS"' + printf '\n More info about Media Nodes deployment here:' + printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup" + printf '\n' + printf '\n' printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}" printf '\n' printf '\n' From 031aa1bf6134dd2cfae1d56028d0e89e077ba19b Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 12:56:06 +0100 Subject: [PATCH 196/435] Remove .env file from media-node docker-compose --- .../pro/docker-compose/media-node/docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index 7eb17be9..1129dd39 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -21,8 +21,6 @@ services: ulimits: core: -1 entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh'] - env_file: - - .env environment: - KMS_IMAGE=kurento/kurento-media-server:6.14.0 - METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0 From 89f2069791b10acb69f52a8c1eaea53592caa207 Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 13:50:50 +0100 Subject: [PATCH 197/435] deployment-openvidu-pro: Bumb coturn and nginx images --- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index f6ff3cf7..bc43a802 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -56,7 +56,7 @@ services: - REDIS_PASSWORD=${OPENVIDU_SECRET} coturn: - image: openvidu/openvidu-coturn:2.0.0-dev2 + image: openvidu/openvidu-coturn:2.0.0-dev3 restart: on-failure network_mode: host environment: @@ -69,7 +69,7 @@ services: - TURN_PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} nginx: - image: openvidu/openvidu-proxy:4.0.0-dev4 + image: openvidu/openvidu-proxy:4.0.0-dev5 restart: on-failure network_mode: host volumes: From be69c7e52a0633f9cef18f36704180835e8ac773 Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 16:33:35 +0100 Subject: [PATCH 198/435] deployment-openvidu: delete unnecessary env variables and add media node env variables --- .../deployments/ce/docker-compose/.env | 7 ----- .../ce/docker-compose/docker-compose.yml | 4 +-- .../docker-compose/openvidu-server-pro/.env | 27 +++++++++++++------ .../openvidu-server-pro/docker-compose.yml | 6 ++--- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 85e642ad..86cba267 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -68,13 +68,6 @@ LETSENCRYPT_EMAIL=user@example.com # ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1, 198.51.100.0/24 # ALLOWED_ACCESS_TO_RESTAPI= -# Public IP used by coturn, nginx and openvidu-server -# Possible values: -# - auto-ipv4: Auto discover public IPv4 using dns services (Default) -# - auto-ipv6: Auto discover public IPv6 using dns services -# - Any valid IPv4 and IPv6 value -# PUBLIC_IP=auto-ipv4 - # Whether to enable recording module or not OPENVIDU_RECORDING=false diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 95abdc28..12ef3c85 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -39,7 +39,7 @@ services: - KMS_URIS=["ws://localhost:8888/kurento"] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} - - COTURN_IP=${PUBLIC_IP:-auto-ipv4} + - COTURN_IP=${COTURN_IP:-auto-ipv4} kms: image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} @@ -96,4 +96,4 @@ services: - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} - REDIRECT_WWW=${REDIRECT_WWW:-false} - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} - - PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} + - PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4} diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 74786e85..afb615de 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -71,14 +71,6 @@ LETSENCRYPT_EMAIL=user@example.com # ALLOWED_ACCESS_TO_RESTAPI=198.51.100.1, 198.51.100.0/24 # ALLOWED_ACCESS_TO_RESTAPI= -# Public IP used by coturn, nginx and openvidu-server -# Possible values: -# - auto-ipv4: Auto discover public IPv4 using dns services (Default) -# - auto-ipv6: Auto discover public IPv6 using dns services -# - Any valid IPv4 and IPv6 value -# PUBLIC_IP=auto-ipv4 - - # Mode of cluster management. Can be auto (OpenVidu manages Media Nodes on its own. # Parameter KMS_URIS is ignored) or manual (user must manage Media Nodes. Parameter # KMS_URIS is used: if any uri is provided it must be valid) @@ -279,6 +271,25 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr ELASTICSEARCH_USERNAME=elasticadmin ELASTICSEARCH_PASSWORD= +# Media Node Configuration +# -------------------------- +# You can add any KMS environment variable as described in the +# documentation of the docker image: https://hub.docker.com/r/kurento/kurento-media-server +# If you want to add an environment variable to KMS, you must add a variable using this prefix: 'KMS_DOCKER_ENV_', +# followed by the environment variable you want to setup. +# For example if you want to setup KMS_MIN_PORT to 50000, it would be KMS_DOCKER_ENV_KMS_MIN_PORT=50000 + +# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server +# Uncomment the next line and define this variable with KMS image that you want use +# By default, KMS_IMAGE is defined in media nodes and it does not need to be specified unless +# you want to use an specific version of KMS +# KMS_IMAGE=kurento/kurento-media-server:6.14.0 + +# Uncomment the next line and define this variable to change +# the verbosity level of the logs of KMS +# Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html +# KMS_DOCKER_ENV_KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4 + # Cloudformation configuration # -------------------------- # If you're working outside AWS ignore this section diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index bc43a802..d7d4f7f0 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -41,7 +41,7 @@ services: - KMS_URIS=[] - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} - - COTURN_IP=${PUBLIC_IP:-auto-ipv4} + - COTURN_IP=${COTURN_IP:-auto-ipv4} - OPENVIDU_PRO_CLUSTER=true - OPENVIDU_PRO_KIBANA_HOST=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana} - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} @@ -66,7 +66,7 @@ services: - DB_PASSWORD=${OPENVIDU_SECRET} - MIN_PORT=40000 - MAX_PORT=65535 - - TURN_PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} + - TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4} nginx: image: openvidu/openvidu-proxy:4.0.0-dev5 @@ -90,7 +90,7 @@ services: - SUPPORT_DEPRECATED_API=${SUPPORT_DEPRECATED_API:-true} - REDIRECT_WWW=${REDIRECT_WWW:-false} - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} - - PUBLIC_IP=${PUBLIC_IP:-auto-ipv4} + - PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4} elasticsearch: From 2f00bc74ae38f6c99550c3809dffa71ec5558d6b Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 16:54:13 +0100 Subject: [PATCH 199/435] deployment-openvidu: Typo --- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index afb615de..de4e73ac 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -282,7 +282,7 @@ ELASTICSEARCH_PASSWORD= # Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server # Uncomment the next line and define this variable with KMS image that you want use # By default, KMS_IMAGE is defined in media nodes and it does not need to be specified unless -# you want to use an specific version of KMS +# you want to use a specific version of KMS # KMS_IMAGE=kurento/kurento-media-server:6.14.0 # Uncomment the next line and define this variable to change From 0710a5732f77a1219ebe1b567e118e9bab01d61c Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 17:26:32 +0100 Subject: [PATCH 200/435] Change KMS_DEBUG_LEVEL to KMS_DOCKER_ENV_GST_DEBUG --- openvidu-server/deployments/ce/docker-compose/.env | 2 +- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 86cba267..a5922a27 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -165,7 +165,7 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr # Uncomment the next line and define this variable to change # the verbosity level of the logs of KMS # Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html -# KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4 +# KMS_DOCKER_ENV_GST_DEBUG= # Openvidu Server Level logs # -------------------------- diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 12ef3c85..6fdef6bb 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -53,7 +53,7 @@ services: environment: - KMS_MIN_PORT=40000 - KMS_MAX_PORT=57000 - - GST_DEBUG=${KMS_DEBUG_LEVEL:-} + - GST_DEBUG=${KMS_DOCKER_ENV_GST_DEBUG:-} redis: image: openvidu/openvidu-redis:1.0.0 diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index de4e73ac..60e8cc7f 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -288,7 +288,7 @@ ELASTICSEARCH_PASSWORD= # Uncomment the next line and define this variable to change # the verbosity level of the logs of KMS # Documentation: https://doc-kurento.readthedocs.io/en/stable/features/logging.html -# KMS_DOCKER_ENV_KMS_DEBUG_LEVEL=3,Kurento*:4,kms*:4,sdp*:4,webrtc*:4,*rtpendpoint:4,rtp*handler:4,rtpsynchronizer:4,agnosticbin:4 +# KMS_DOCKER_ENV_GST_DEBUG= # Cloudformation configuration # -------------------------- From 1ace424d8977e3a6bc4daf07ad08dbd7bc824ef9 Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 17:30:58 +0100 Subject: [PATCH 201/435] openvidu-deployment: Don't use dev repository for kms image in .env --- openvidu-server/deployments/ce/docker-compose/.env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index a5922a27..080b267f 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -156,9 +156,9 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr # Kurento Media Server image # -------------------------- -# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server-dev +# Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server # Uncomment the next line and define this variable with KMS image that you want use -# KMS_IMAGE=kurento/kurento-media-server-dev:6.14.0 +# KMS_IMAGE=kurento/kurento-media-server:6.14.0 # Kurento Media Server Level logs # ------------------------------- From f6a63e92df4a4b94a28fe1b8d9587e13464b1af0 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 3 Nov 2020 18:31:36 +0100 Subject: [PATCH 202/435] openvidu-server: remove userInfo from IP cameras identifiers --- .../io/openvidu/server/kurento/core/KurentoSessionManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java index 61e9e971..39a1ce36 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/kurento/core/KurentoSessionManager.java @@ -1012,7 +1012,8 @@ public class KurentoSessionManager extends SessionManager { } String rtspConnectionId = kMediaOptions.getTypeOfVideo() + "_" + protocol + "_" - + RandomStringUtils.randomAlphanumeric(4).toUpperCase() + "_" + url.getAuthority() + url.getPath(); + + RandomStringUtils.randomAlphanumeric(4).toUpperCase() + "_" + url.getHost() + + (url.getPort() != -1 ? (":" + url.getPort()) : "") + url.getPath(); rtspConnectionId = rtspConnectionId.replace("/", "_").replace("-", "").replace(".", "_").replace(":", "_"); rtspConnectionId = IdentifierPrefixes.IPCAM_ID + rtspConnectionId; From 5dfc8714c1a0ecd52746d540738ce5d32d170746 Mon Sep 17 00:00:00 2001 From: cruizba Date: Tue, 3 Nov 2020 19:01:41 +0100 Subject: [PATCH 203/435] deployment-openvidu: bump openvidu-server and openvidu-server-pro versions --- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 6fdef6bb..8c7b8316 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server:2.16.0-dev2 + image: openvidu/openvidu-server:2.16.0-dev3 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index d7d4f7f0..f0de5eb6 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server-pro:2.16.0-dev4 + image: openvidu/openvidu-server-pro:2.16.0-dev6 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] From 944f0ac8b45e3dd9c7a9dd8bac236d1d2c01d1fc Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 12:31:51 +0100 Subject: [PATCH 204/435] openvidu-server: support openvidu-browser 2.15.0 --- .../openvidu/server/core/TokenGenerator.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 7aac70ab..a39101b0 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -47,6 +47,11 @@ public class TokenGenerator { token += "?sessionId=" + sessionId; token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); + + // REMOVE AFTER RELEASE 2.16.0 + token = compatibilityWithOpenViduBrowser2150(token, role); + // REMOVE AFTER RELEASE 2.16.0 + TurnCredentials turnCredentials = null; if (this.openviduConfig.isTurnadminAvailable()) { turnCredentials = coturnCredentialsService.createUser(); @@ -55,4 +60,24 @@ public class TokenGenerator { .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); return new Token(token, sessionId, connectionProperties, turnCredentials); } + + // REMOVE AFTER RELEASE 2.16.0 + private String compatibilityWithOpenViduBrowser2150(String token, OpenViduRole role) { + token += "&role=" + role.name(); + token += "&version=" + openviduBuildConfig.getOpenViduServerVersion(); + TurnCredentials turnCredentials = null; + if (this.openviduConfig.isTurnadminAvailable()) { + try { + turnCredentials = coturnCredentialsService.createUser(); + } catch (Exception e) { + e.printStackTrace(); + } + if (turnCredentials != null) { + token += "&coturnIp=" + openviduConfig.getCoturnIp(); + token += "&turnUsername=" + turnCredentials.getUsername(); + token += "&turnCredential=" + turnCredentials.getCredential(); + } + } + return token; + } } From b06ad1d951a1c4f38160e351371badb4eb7ceb86 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 12:36:47 +0100 Subject: [PATCH 205/435] openvidu-server: fix openvidu-browser 2.15.0 compatibility --- .../openvidu/server/core/TokenGenerator.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index a39101b0..8ef7dbdc 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -47,36 +47,29 @@ public class TokenGenerator { token += "?sessionId=" + sessionId; token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(15); - - // REMOVE AFTER RELEASE 2.16.0 - token = compatibilityWithOpenViduBrowser2150(token, role); - // REMOVE AFTER RELEASE 2.16.0 - TurnCredentials turnCredentials = null; if (this.openviduConfig.isTurnadminAvailable()) { turnCredentials = coturnCredentialsService.createUser(); } + + // REMOVE AFTER RELEASE 2.16.0 + token = compatibilityWithOpenViduBrowser2150(token, role, turnCredentials); + // REMOVE AFTER RELEASE 2.16.0 + ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); return new Token(token, sessionId, connectionProperties, turnCredentials); } // REMOVE AFTER RELEASE 2.16.0 - private String compatibilityWithOpenViduBrowser2150(String token, OpenViduRole role) { + private String compatibilityWithOpenViduBrowser2150(String token, OpenViduRole role, + TurnCredentials turnCredentials) { token += "&role=" + role.name(); token += "&version=" + openviduBuildConfig.getOpenViduServerVersion(); - TurnCredentials turnCredentials = null; - if (this.openviduConfig.isTurnadminAvailable()) { - try { - turnCredentials = coturnCredentialsService.createUser(); - } catch (Exception e) { - e.printStackTrace(); - } - if (turnCredentials != null) { - token += "&coturnIp=" + openviduConfig.getCoturnIp(); - token += "&turnUsername=" + turnCredentials.getUsername(); - token += "&turnCredential=" + turnCredentials.getCredential(); - } + if (turnCredentials != null) { + token += "&coturnIp=" + openviduConfig.getCoturnIp(); + token += "&turnUsername=" + turnCredentials.getUsername(); + token += "&turnCredential=" + turnCredentials.getCredential(); } return token; } From d36db205709db85ddedc8f4abe20208cbc66c36d Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 12:50:07 +0100 Subject: [PATCH 206/435] Jenkinsfile: configure openvidu-testapp commit --- openvidu-test-e2e/jenkins/Jenkinsfile | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index b715e462..dd958b6f 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -10,7 +10,7 @@ node('container') { docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() - mycontainer.inside("--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged") { + mycontainer.inside('--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged') { stage('Preparation') { sh 'rm -rf ~/.m2 || true' sh 'rm -rf openvidu || true' @@ -66,7 +66,19 @@ node('container') { '''.stripIndent()) } stage('OpenVidu TestApp build') { - sh 'cd openvidu/openvidu-testapp && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && npm install /opt/openvidu/openvidu-node-client-*.tgz && export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod' + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then + git checkout $OPENVIDU_TESTAPP_COMMIT + fi + cd openvidu-testapp + npm install --unsafe-perm + npm install /opt/openvidu/openvidu-browser-*.tgz + npm install /opt/openvidu/openvidu-node-client-*.tgz + export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod + cd .. + git checkout $OPENVIDU_COMMIT + '''.stripIndent()) } stage('OpenVidu parent build') { sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' From a38f3e087e225f75f22f80662749261b92b9f1e9 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 13:10:00 +0100 Subject: [PATCH 207/435] Jenkinsfile: output testapp in /opt path --- openvidu-test-e2e/jenkins/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index dd958b6f..6a155569 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -75,7 +75,7 @@ node('container') { npm install --unsafe-perm npm install /opt/openvidu/openvidu-browser-*.tgz npm install /opt/openvidu/openvidu-node-client-*.tgz - export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod + export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp cd .. git checkout $OPENVIDU_COMMIT '''.stripIndent()) @@ -100,7 +100,7 @@ node('container') { } stage ('Environment Launch') { sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' - sh 'cd openvidu/openvidu-testapp/dist && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' + sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' sh(script: '''#!/bin/bash From f687d269be2cb6f9c22f83ec3b25c099e2c16997 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 13:31:55 +0100 Subject: [PATCH 208/435] Jenkinsfile fixed (testapp keys location) --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 6a155569..31534636 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -99,7 +99,7 @@ node('container') { '''.stripIndent()) } stage ('Environment Launch') { - sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout openvidu/openvidu-testapp/dist/key.pem -out openvidu/openvidu-testapp/dist/cert.pem' + sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' From f5daa6877a580dbf1135086935157e86df423737 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 14:15:56 +0100 Subject: [PATCH 209/435] Jenkinsfile: force checkout to master --- openvidu-test-e2e/jenkins/Jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 31534636..d5033e9e 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -49,7 +49,7 @@ node('container') { npm install --unsafe-perm && npm run build && npm pack cp openvidu-browser-*.tgz /opt/openvidu cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu Node Client build') { @@ -62,7 +62,7 @@ node('container') { npm install --unsafe-perm && npm run build && npm pack cp openvidu-node-client-*.tgz /opt/openvidu cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu TestApp build') { @@ -77,7 +77,7 @@ node('container') { npm install /opt/openvidu/openvidu-node-client-*.tgz export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp cd .. - git checkout $OPENVIDU_COMMIT + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu parent build') { From 5caa51a5e7965b3b65d1da9f517ebf5d16d6fe73 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 15:32:32 +0100 Subject: [PATCH 210/435] Jenkinsfile: parameterized OPENVIDU_TESTE2E_COMMIT --- openvidu-test-e2e/jenkins/Jenkinsfile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index d5033e9e..b9b49fe9 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -116,7 +116,15 @@ node('container') { } stage ('OpenVidu E2E tests') { try { - sh 'cd openvidu/openvidu-test-e2e && sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test' + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then + git checkout $OPENVIDU_TESTE2E_COMMIT + fi + cd openvidu-test-e2e + sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) } finally { junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' From e7938aa1b982e951fb71885a7729bfd1e64b86d3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 16:37:21 +0100 Subject: [PATCH 211/435] Jenkinsfile fixed --- openvidu-test-e2e/jenkins/Jenkinsfile | 1 - 1 file changed, 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index b9b49fe9..d508f161 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -123,7 +123,6 @@ node('container') { fi cd openvidu-test-e2e sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test - git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } finally { From 14453e57043048a27981c8997cd05a67292ee25f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 16:40:33 +0100 Subject: [PATCH 212/435] Jenkinsfile: force checkout --- openvidu-test-e2e/jenkins/Jenkinsfile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index d508f161..8a5222a1 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -43,7 +43,7 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout $OPENVIDU_BROWSER_COMMIT + git checkout -f $OPENVIDU_BROWSER_COMMIT fi cd openvidu-browser npm install --unsafe-perm && npm run build && npm pack @@ -56,7 +56,7 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout $OPENVIDU_NODE_CLIENT_COMMIT + git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT fi cd openvidu-node-client npm install --unsafe-perm && npm run build && npm pack @@ -69,7 +69,7 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then - git checkout $OPENVIDU_TESTAPP_COMMIT + git checkout -f $OPENVIDU_TESTAPP_COMMIT fi cd openvidu-testapp npm install --unsafe-perm @@ -119,10 +119,11 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then - git checkout $OPENVIDU_TESTE2E_COMMIT + git checkout -f $OPENVIDU_TESTE2E_COMMIT fi cd openvidu-test-e2e sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test + git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } finally { From 8715d2109c5a6b81fef06f55fe19b2d45bd885dd Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 17:00:16 +0100 Subject: [PATCH 213/435] Jenkinsfile: openvidu-java-client local installation --- openvidu-test-e2e/jenkins/Jenkinsfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 8a5222a1..3d35b4c5 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -82,6 +82,7 @@ node('container') { } stage('OpenVidu parent build') { sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' + sh 'cd openvidu/openvidu-java-client && mvn clean compile package && cp target/openvidu-java-client*.jar /opt/openvidu/openvidu-java-client.jar' sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=1.0.0-TEST' sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } @@ -94,7 +95,9 @@ node('container') { stage('OpenVidu Server build') { sh(script: '''#!/bin/bash cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod - cd ../.. && mvn --batch-mode clean compile package + cd ../.. + mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar + mvn --batch-mode package cp target/openvidu-server*.jar /opt/openvidu '''.stripIndent()) } @@ -122,6 +125,7 @@ node('container') { git checkout -f $OPENVIDU_TESTE2E_COMMIT fi cd openvidu-test-e2e + mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) From 8543ee2e493f0226efe6c0c1fee4c89a38360618 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 17:19:21 +0100 Subject: [PATCH 214/435] Jenkinsfile fixed --- openvidu-test-e2e/jenkins/Jenkinsfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 3d35b4c5..a378b83a 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -83,6 +83,7 @@ node('container') { stage('OpenVidu parent build') { sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' sh 'cd openvidu/openvidu-java-client && mvn clean compile package && cp target/openvidu-java-client*.jar /opt/openvidu/openvidu-java-client.jar' + sh 'cd openvidu/openvidu-test-browsers && mvn clean compile package && cp target/penvidu-test-browsers*.jar /opt/openvidu/penvidu-test-browsers.jar' sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=1.0.0-TEST' sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } @@ -97,6 +98,7 @@ node('container') { cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar + mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-test-browsers.jar mvn --batch-mode package cp target/openvidu-server*.jar /opt/openvidu '''.stripIndent()) @@ -126,6 +128,7 @@ node('container') { fi cd openvidu-test-e2e mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar + mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-test-browsers.jar sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) From d9bbe3c3b11e0a6f5a4684ea04831481b14cdd9a Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 17:51:19 +0100 Subject: [PATCH 215/435] Jenkinsfile: openvidu-java-client commit parameterized --- openvidu-test-e2e/jenkins/Jenkinsfile | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index a378b83a..b4b83335 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -80,11 +80,21 @@ node('container') { git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } + stage('OpenVidu Java Client build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT + fi + cd openvidu-java-client + mvn --batch-mode versions:set -DnewVersion=TEST + mvn clean compile package + mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } stage('OpenVidu parent build') { - sh 'cd openvidu/openvidu-java-client && mvn --batch-mode versions:set -DnewVersion=1.0.0-TEST' - sh 'cd openvidu/openvidu-java-client && mvn clean compile package && cp target/openvidu-java-client*.jar /opt/openvidu/openvidu-java-client.jar' - sh 'cd openvidu/openvidu-test-browsers && mvn clean compile package && cp target/penvidu-test-browsers*.jar /opt/openvidu/penvidu-test-browsers.jar' - sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=1.0.0-TEST' + sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } stage('OpenVidu Server unit tests') { @@ -97,8 +107,6 @@ node('container') { sh(script: '''#!/bin/bash cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. - mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar - mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-test-browsers.jar mvn --batch-mode package cp target/openvidu-server*.jar /opt/openvidu '''.stripIndent()) @@ -126,8 +134,8 @@ node('container') { if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTE2E_COMMIT fi - cd openvidu-test-e2e - mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-java-client.jar + cd openvidu-test-browsers && mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean compile package && cp target/openvidu-test-browsers*.jar /opt/openvidu/openvidu-test-browsers.jar + cd ../openvidu-test-e2e mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-test-browsers.jar sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT From eb0593ec02c4c5d9756ba50c90f016b086fa2dc5 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 4 Nov 2020 18:59:54 +0100 Subject: [PATCH 216/435] openvidu-deployment: Update ubuntu AMIs to 18.04 and kurento 6.15.0 in deployments --- openvidu-server/deployments/ce/aws/createAMI.sh | 2 +- openvidu-server/deployments/ce/docker-compose/.env | 2 +- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- openvidu-server/deployments/pro/aws/createAMIs.sh | 2 +- .../pro/docker-compose/media-node/docker-compose.yml | 2 +- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/createAMI.sh b/openvidu-server/deployments/ce/aws/createAMI.sh index 06474c41..a257b46d 100755 --- a/openvidu-server/deployments/ce/aws/createAMI.sh +++ b/openvidu-server/deployments/ce/aws/createAMI.sh @@ -19,7 +19,7 @@ TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json) getUbuntuAmiId() { local AMI_ID=$( aws --region ${1} ec2 describe-images \ - --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \ + --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64* \ --query 'Images[*].[ImageId,CreationDate]' \ --output text \ | sort -k2 -r | head -n1 | cut -d$'\t' -f1 diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index 080b267f..cc5e3395 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -158,7 +158,7 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr # -------------------------- # Docker hub kurento media server: https://hub.docker.com/r/kurento/kurento-media-server # Uncomment the next line and define this variable with KMS image that you want use -# KMS_IMAGE=kurento/kurento-media-server:6.14.0 +# KMS_IMAGE=kurento/kurento-media-server:6.15.0 # Kurento Media Server Level logs # ------------------------------- diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 8c7b8316..f62ef01c 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -42,7 +42,7 @@ services: - COTURN_IP=${COTURN_IP:-auto-ipv4} kms: - image: ${KMS_IMAGE:-kurento/kurento-media-server:6.14.0} + image: ${KMS_IMAGE:-kurento/kurento-media-server:6.15.0} restart: always network_mode: host ulimits: diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index 3b3fe9af..055ba0ff 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -18,7 +18,7 @@ TEMPJSON=$(mktemp -t cloudformation-XXX --suffix .json) getUbuntuAmiId() { local AMI_ID=$( aws --region ${1} ec2 describe-images \ - --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64* \ + --filters Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64* \ --query 'Images[*].[ImageId,CreationDate]' \ --output text \ | sort -k2 -r | head -n1 | cut -d$'\t' -f1 diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index 1129dd39..1dc3fcc5 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -22,7 +22,7 @@ services: core: -1 entrypoint: ['/bin/sh', '-c', '/beats/copy_config_files.sh && /usr/local/bin/entrypoint.sh'] environment: - - KMS_IMAGE=kurento/kurento-media-server:6.14.0 + - KMS_IMAGE=kurento/kurento-media-server:6.15.0 - METRICBEAT_IMAGE=docker.elastic.co/beats/metricbeat-oss:7.8.0 - FILEBEAT_IMAGE=docker.elastic.co/beats/filebeat-oss:7.8.0 ports: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 60e8cc7f..62496325 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -283,7 +283,7 @@ ELASTICSEARCH_PASSWORD= # Uncomment the next line and define this variable with KMS image that you want use # By default, KMS_IMAGE is defined in media nodes and it does not need to be specified unless # you want to use a specific version of KMS -# KMS_IMAGE=kurento/kurento-media-server:6.14.0 +# KMS_IMAGE=kurento/kurento-media-server:6.15.0 # Uncomment the next line and define this variable to change # the verbosity level of the logs of KMS From b3f9fa3a403aa58f5be9b272db419f726fd69e13 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 19:08:01 +0100 Subject: [PATCH 217/435] Jenkinsfile fixed --- openvidu-test-e2e/jenkins/Jenkinsfile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index b4b83335..f7f7f33f 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -134,9 +134,12 @@ node('container') { if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTE2E_COMMIT fi - cd openvidu-test-browsers && mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean compile package && cp target/openvidu-test-browsers*.jar /opt/openvidu/openvidu-test-browsers.jar - cd ../openvidu-test-e2e - mvn --batch-mode org.apache.maven.plugins:maven-install-plugin:3.0.0-M1:install-file -Dfile=/opt/openvidu/openvidu-test-browsers.jar + cd openvidu-test-browsers + mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean compile package + mvn install:install-file -Dfile=target/openvidu-test-browsers-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-test-browsers -Dversion=TEST -Dpackaging=jar + cd .. + mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST + cd openvidu-test-e2e sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) From 242b023c2cd4d9dc389b791b826cdb4e087102e3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 19:27:58 +0100 Subject: [PATCH 218/435] Network quality level new value and old value --- openvidu-browser/src/OpenVidu/Session.ts | 4 ++-- .../Events/NetworkQualityLevelChangedEvent.ts | 12 +++++++++--- .../openvidu/client/internal/ProtocolElements.java | 3 ++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index c83eea6c..95b9de7c 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -957,11 +957,11 @@ export class Session extends EventDispatcher { */ onNetworkQualityLevelChangedChanged(msg): void { if (msg.connectionId === this.connection.connectionId) { - this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, this.connection)]); + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.newValue, msg.oldValue, this.connection)]); } else { this.getConnection(msg.connectionId, 'Connection not found for connectionId ' + msg.connectionId) .then((connection: Connection) => { - this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.qualityLevel, connection)]); + this.ee.emitEvent('networkQualityLevelChanged', [new NetworkQualityLevelChangedEvent(this, msg.newValue, msg.oldValue, connection)]); }) .catch(openViduError => { logger.error(openViduError); diff --git a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts index 0dbfdc95..592e62a7 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/NetworkQualityLevelChangedEvent.ts @@ -30,7 +30,12 @@ export class NetworkQualityLevelChangedEvent extends Event { /** * New value of the network quality level */ - qualityLevel: number; + newValue: number; + + /** + * Old value of the network quality level + */ + oldValue: number; /** * Connection for whom the network quality level changed @@ -40,9 +45,10 @@ export class NetworkQualityLevelChangedEvent extends Event { /** * @hidden */ - constructor(target: Session, qualityLevel: number, connection: Connection) { + constructor(target: Session, newValue: number, oldValue: number, connection: Connection) { super(false, target, 'networkQualityLevelChanged'); - this.qualityLevel = qualityLevel; + this.newValue = newValue; + this.oldValue = oldValue; this.connection = connection; } diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java index f347c2cf..1638425d 100644 --- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java +++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java @@ -99,7 +99,8 @@ public class ProtocolElements { public static final String NETWORKQUALITYLEVELCHANGED_METHOD = "networkQualityLevelChanged"; public static final String NETWORKQUALITYCHANGED_CONNECTIONID_PARAM = "connectionId"; - public static final String NETWORKQUALITYCHANGED_QUALITYLEVEL_PARAM = "qualityLevel"; + public static final String NETWORKQUALITYCHANGED_NEWVALUE_PARAM = "newValue"; + public static final String NETWORKQUALITYCHANGED_OLDVALUE_PARAM = "oldValue"; public static final String FORCEDISCONNECT_METHOD = "forceDisconnect"; public static final String FORCEDISCONNECT_CONNECTIONID_PARAM = "connectionId"; From 88840adb8ea32f598bb4f890a9b986a8edab622c Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 4 Nov 2020 19:57:31 +0100 Subject: [PATCH 219/435] Updated CE installation and upgrading script: - Don't download readme.md and reference webpage - Forbid updates from other versions except 2.15.0 --- .../ce/docker-compose/install_openvidu.sh | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh index fdaa61cb..e9b64864 100755 --- a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh +++ b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh @@ -42,10 +42,6 @@ new_ov_installation() { --output "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'" printf '\n - openvidu' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/ce/docker-compose/readme.md \ - --output "${OPENVIDU_FOLDER}/readme.md" || fatal_error "Error when downloading the file 'readme.md'" - printf '\n - readme.md' - # Add execution permissions printf "\n => Adding permission to 'openvidu' program..." chmod +x "${OPENVIDU_FOLDER}/openvidu" || fatal_error "Error while adding permission to 'openvidu' program" @@ -109,7 +105,11 @@ upgrade_ov() { # Uppgrade Openvidu OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }') - [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.13.0 + [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version" + + if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "2.15.0" ]]; then + fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions." + fi # In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is # posible or not. If it is not posible launch a warning and stop the upgrade. @@ -150,10 +150,6 @@ upgrade_ov() { --output "${TMP_FOLDER}/openvidu" || fatal_error "Error when downloading the file 'openvidu'" printf '\n - openvidu' - curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/ce/docker-compose/readme.md \ - --output "${TMP_FOLDER}/readme.md" || fatal_error "Error when downloading the file 'readme.md'" - printf '\n - readme.md' - # Dowloading new images and stoped actual Openvidu printf '\n => Dowloading new images...' printf '\n' @@ -217,9 +213,6 @@ upgrade_ov() { mv "${TMP_FOLDER}/openvidu" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'openvidu'" printf '\n - openvidu' - mv "${TMP_FOLDER}/readme.md" "${OPENVIDU_PREVIOUS_FOLDER}" || fatal_error "Error while updating 'readme.md'" - printf '\n - readme.md' - printf "\n => Deleting 'tmp' folder" rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder" @@ -253,7 +246,9 @@ upgrade_ov() { printf '\n' printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}" printf '\n' - printf '\n For more information, check readme.md' + printf '\n For more information, check:' + printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/deploying-on-premises/" + printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/upgrading/ printf '\n' printf '\n' } From bb194b750b45098d615104ac015eabc49b23acaf Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 20:32:43 +0100 Subject: [PATCH 220/435] Jenkinsfile update --- openvidu-test-e2e/jenkins/Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index f7f7f33f..67f491c4 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -135,8 +135,7 @@ node('container') { git checkout -f $OPENVIDU_TESTE2E_COMMIT fi cd openvidu-test-browsers - mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean compile package - mvn install:install-file -Dfile=target/openvidu-test-browsers-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-test-browsers -Dversion=TEST -Dpackaging=jar + mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean install cd .. mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST cd openvidu-test-e2e From 5eff6df41aff83c6150dfb09b8f27b01425c1322 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 4 Nov 2020 20:43:29 +0100 Subject: [PATCH 221/435] openvidu-deployment: Typo install script --- .../deployments/ce/docker-compose/install_openvidu.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh index e9b64864..bda4109a 100755 --- a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh +++ b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh @@ -248,7 +248,7 @@ upgrade_ov() { printf '\n' printf '\n For more information, check:' printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/deploying-on-premises/" - printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/upgrading/ + printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/deployment/upgrading/" printf '\n' printf '\n' } From 42e14a961074c368fee09e7d621138c52b7b488f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 4 Nov 2020 21:23:39 +0100 Subject: [PATCH 222/435] Jenkinsfile: use local openvidu-java-client in openvidu-test-e2e --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 67f491c4..e8aa5064 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -137,8 +137,10 @@ node('container') { cd openvidu-test-browsers mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean install cd .. + mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST cd openvidu-test-e2e + mvn -DskipTests=true clean compile sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) From c9235e64cf04b7b96123eae4fd85fc8a6666c2fe Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 4 Nov 2020 22:42:04 +0100 Subject: [PATCH 223/435] openvidu-deployment: Don't rely on aws http endpoint to update KMS AMI --- .../openvidu-server-pro/install_openvidu_pro.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index 232ca29e..3f6b61ac 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -315,16 +315,15 @@ upgrade_ov() { [ ! -z "${OLD_MODE}" ] && sed -i -r "s/Installation Mode:.+/Installation Mode: ${OLD_MODE}/" "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" # In Aws, update AMI ID - CHECK_AWS=$(curl -s -o /dev/null -w "%{http_code}" http://169.254.169.254) - if [[ ${CHECK_AWS} == "200" ]]; then - AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2) - [[ -z ${AWS_REGION} ]] && fatal_error "Error while getting AWS_REGION" + AWS_REGION=$(grep -E "AWS_DEFAULT_REGION=.*$" "${OPENVIDU_PREVIOUS_FOLDER}/.env" | cut -d'=' -f2) + if [[ ! -z ${AWS_REGION} ]]; then NEW_AMI_ID=$(curl https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/CF-OpenVidu-Pro-${OPENVIDU_VERSION//v}.yaml --silent | sed -n -e '/KMSAMIMAP:/,/Metadata:/ p' | grep -A 1 ${AWS_REGION} | grep AMI | tr -d " " | cut -d":" -f2) [[ -z ${NEW_AMI_ID} ]] && fatal_error "Error while getting new AWS_IMAGE_ID for Media Nodes" sed -i "s/.*AWS_IMAGE_ID=.*/AWS_IMAGE_ID=${NEW_AMI_ID}/" "${OPENVIDU_PREVIOUS_FOLDER}/.env" || fatal_error "Error while updating new AWS_IMAGE_ID for Media Nodes" fi + # Ready to use printf '\n' From 9bd044a98bdacea50bafa639c0e6b368db827b72 Mon Sep 17 00:00:00 2001 From: cruizba Date: Wed, 4 Nov 2020 23:59:00 +0100 Subject: [PATCH 224/435] deployment-openvidu: Stop containers of media-node properly --- .../media-node/install_media_node.sh | 58 ++++++++++++++----- .../pro/docker-compose/media-node/media_node | 27 +++++++-- 2 files changed, 65 insertions(+), 20 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index 693dc485..ecdb8503 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -84,25 +84,49 @@ new_media_node_installation() { printf '\n 2. Start Media Node Controller' printf '\n $ ./media_node start' printf '\n' - printf '\n 3. Add the private ip of this media node in `KMS_URIS=[]` in OpenVidu Pro machine' - printf '\n in the file located at "/opt/openvidu/.env" with this format:' + printf '\n 3. This will run a service at port 3000 wich OpenVidu will use to deploy necessary containers.' + printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' + printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' printf '\n KMS_URIS=["ws://:8888/kurento"]' printf '\n ...' printf '\n You can also add this node from inspector' - printf '\n After that start or restart OpenVidu Pro and all containers will be provisioned in all media nodes' + printf '\n' + printf '\n 4. Start or restart OpenVidu Pro and all containers will be provisioned' printf '\n automatically to all the media nodes configured in "KMS_URIS"' printf '\n More info about Media Nodes deployment here:' printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup" printf '\n' printf '\n' - printf "\n For more information, check:" - printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions" - printf '\n' + printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}" printf '\n' exit 0 } +stop_and_remove_container_by_image() { + IMAGE_NAME=$1 + if [[ ! -z "${IMAGE_NAME}" ]]; then + CONTAINER_ID=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') + if [[ ! -z "${CONTAINER_ID}" ]]; then + docker rm -f "${CONTAINER_ID}" + fi + fi +} + +stop_and_remove_containers() { + IMAGES=( + "kurento-media-server", + "docker.elastic.co/beats/filebeat", + "docker.elastic.co/beats/metricbeat", + "openvidu/media-node-controller" + ) + + for image in ${IMAGES[@]} + do + stop_container_by_image "${image}" + done +} + upgrade_media_node() { # Search local Openvidu installation printf '\n' @@ -186,10 +210,16 @@ upgrade_media_node() { printf "\n => Moving to 'tmp' folder..." printf '\n' + cd "${TMP_FOLDER}" || fatal_error "Error when moving to '${TMP_FOLDER}' folder" + + printf '\n => Stoping Media Node containers...' + printf '\n' + sleep 1 + + stop_and_remove_containers # Pull images printf "\n => Pulling images...\n" - cd "${TMP_FOLDER}" || fatal_error "Error when moving to '${TMP_FOLDER}' folder" KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') @@ -226,7 +256,7 @@ upgrade_media_node() { mv "${MEDIA_NODE_PREVIOUS_FOLDER}/nginx_conf" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'nginx_conf'" printf '\n - nginx_conf' - cp "${MEDIA_NODE_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'" + mv "${MEDIA_NODE_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'" printf '\n - .env' # Move tmp files to Openvidu @@ -281,13 +311,15 @@ upgrade_media_node() { printf '\n 3. Start new version of Media Node' printf '\n $ ./media_node start' printf '\n' - printf '\n 4. Add the private ip of this media node in `KMS_URIS=[]` in OpenVidu Pro machine' - printf '\n in the file located at "/opt/openvidu/.env" with this format:' + printf '\n 4. This will run a service at port 3000 wich OpenVidu will use to deploy necessary containers.' + printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' + printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' printf '\n KMS_URIS=["ws://:8888/kurento"]' printf '\n ...' - printf '\n You can also add this node from inspector' - printf '\n After that start or restart OpenVidu Pro and all containers will be provisioned' + printf '\n You can also add Media Nodes from inspector' + printf '\n' + printf '\n 5. Start or restart OpenVidu Pro and all containers will be provisioned' printf '\n automatically to all the media nodes configured in "KMS_URIS"' printf '\n More info about Media Nodes deployment here:' printf "\n --> https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#set-the-number-of-media-nodes-on-startup" @@ -295,8 +327,6 @@ upgrade_media_node() { printf '\n' printf "\n If you want to rollback, all the files from the previous installation have been copied to folder '.old-%s'" "${OPENVIDU_PREVIOUS_VERSION}" printf '\n' - printf '\n' - printf '\n' } # Check docker and docker-compose installation diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index b55a4122..f4d3866c 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -179,13 +179,28 @@ usage() { printf "\n" } -stop_containers() { - CONTAINERS=$(docker ps | awk '{if(NR>1) print $NF}') - for CONTAINER in $CONTAINERS - do - [ "$(docker ps -a | grep ${CONTAINER})" ] && docker stop ${CONTAINER} - done +stop_container_by_image() { + IMAGE_NAME=$1 + if [[ ! -z "${IMAGE_NAME}" ]]; then + CONTAINER_ID=$(docker ps | grep "${IMAGE_NAME}" | awk '{print $1}') + if [[ ! -z "${CONTAINER_ID}" ]]; then + docker stop "${CONTAINER_ID}" + fi + fi +} +stop_containers() { + IMAGES=( + "kurento-media-server", + "docker.elastic.co/beats/filebeat", + "docker.elastic.co/beats/metricbeat", + "openvidu/media-node-controller" + ) + + for image in ${IMAGES[@]} + do + stop_container_by_image "${image}" + done } case $1 in From 3ecd9885d6ba6d6a7b279b83af747bd34300fdf4 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 00:18:27 +0100 Subject: [PATCH 225/435] Only upgrade from previous version --- .../deployments/ce/docker-compose/install_openvidu.sh | 8 ++++---- .../pro/docker-compose/media-node/install_media_node.sh | 6 +++++- .../openvidu-server-pro/install_openvidu_pro.sh | 6 +++++- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh index bda4109a..07b7155a 100755 --- a/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh +++ b/openvidu-server/deployments/ce/docker-compose/install_openvidu.sh @@ -3,6 +3,7 @@ # Global variables OPENVIDU_FOLDER=openvidu OPENVIDU_VERSION=master +OPENVIDU_UPGRADABLE_VERSION="2.15" DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${OPENVIDU_VERSION} fatal_error() { @@ -107,12 +108,11 @@ upgrade_ov() { OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }') [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version" - if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "2.15.0" ]]; then - fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions." - fi - # In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is # posible or not. If it is not posible launch a warning and stop the upgrade. + if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then + fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions." + fi printf '\n' printf '\n =======================================' diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index ecdb8503..eba906d8 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -2,6 +2,7 @@ MEDIA_NODE_FOLDER=kms MEDIA_NODE_VERSION=master +OPENVIDU_UPGRADABLE_VERSION="2.15" BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION} fatal_error() { @@ -155,10 +156,13 @@ upgrade_media_node() { # Uppgrade Media Node OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${MEDIA_NODE_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }') - [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.14.0 + [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version" # In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is # posible or not. If it is not posible launch a warning and stop the upgrade. + if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then + fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions." + fi printf '\n' printf '\n =======================================' diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index 3f6b61ac..c6792a9f 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -3,6 +3,7 @@ # Global variables OPENVIDU_FOLDER=openvidu OPENVIDU_VERSION=master +OPENVIDU_UPGRADABLE_VERSION="2.15" AWS_SCRIPTS_FOLDER=${OPENVIDU_FOLDER}/cluster/aws ELASTICSEARCH_FOLDER=${OPENVIDU_FOLDER}/elasticsearch BEATS_FOLDER=${OPENVIDU_FOLDER}/beats @@ -151,10 +152,13 @@ upgrade_ov() { # Uppgrade Openvidu OPENVIDU_PREVIOUS_VERSION=$(grep 'Openvidu Version:' "${OPENVIDU_PREVIOUS_FOLDER}/docker-compose.yml" | awk '{ print $4 }') - [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && OPENVIDU_PREVIOUS_VERSION=2.13.0 + [ -z "${OPENVIDU_PREVIOUS_VERSION}" ] && fatal_error "Can't find previous OpenVidu version" # In this point using the variable 'OPENVIDU_PREVIOUS_VERSION' we can verify if the upgrade is # posible or not. If it is not posible launch a warning and stop the upgrade. + if [[ "${OPENVIDU_PREVIOUS_VERSION}" != "${OPENVIDU_UPGRADABLE_VERSION}."* ]]; then + fatal_error "You can't update from version ${OPENVIDU_PREVIOUS_VERSION} to ${OPENVIDU_VERSION}.\nNever upgrade across multiple major versions." + fi printf '\n' printf '\n =======================================' From a4c8e02a3ffc5c0c4d984baa9df75565401b4161 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 11:57:29 +0100 Subject: [PATCH 226/435] openvidu-deployment Improve media node scripts --- .../media-node/install_media_node.sh | 54 +++++++------ .../pro/docker-compose/media-node/media_node | 80 +++++++++++++------ 2 files changed, 83 insertions(+), 51 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index eba906d8..8bdd8fa2 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -5,6 +5,13 @@ MEDIA_NODE_VERSION=master OPENVIDU_UPGRADABLE_VERSION="2.15" BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION} +IMAGES=( + "kurento-media-server", + "docker.elastic.co/beats/filebeat", + "docker.elastic.co/beats/metricbeat", + "openvidu/media-node-controller" +) + fatal_error() { printf "\n =======¡ERROR!=======" printf "\n %s" "$1" @@ -12,6 +19,27 @@ fatal_error() { exit 0 } +docker_command_by_container_image() { + IMAGE_NAME=$1 + COMMAND=$2 + if [[ ! -z "${IMAGE_NAME}" ]]; then + CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') + for CONTAINER_ID in ${CONTAINERS[@]}; do + if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then + docker "${COMMAND}" "${CONTAINER_ID}" + fi + done + fi +} + + +stop_containers() { + printf "Stopping containers..." + for IMAGE in ${IMAGES[@]}; do + docker_command_by_container_image "${IMAGE}" "rm -f" + done +} + new_media_node_installation() { printf '\n' printf '\n =======================================' @@ -104,30 +132,6 @@ new_media_node_installation() { exit 0 } -stop_and_remove_container_by_image() { - IMAGE_NAME=$1 - if [[ ! -z "${IMAGE_NAME}" ]]; then - CONTAINER_ID=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') - if [[ ! -z "${CONTAINER_ID}" ]]; then - docker rm -f "${CONTAINER_ID}" - fi - fi -} - -stop_and_remove_containers() { - IMAGES=( - "kurento-media-server", - "docker.elastic.co/beats/filebeat", - "docker.elastic.co/beats/metricbeat", - "openvidu/media-node-controller" - ) - - for image in ${IMAGES[@]} - do - stop_container_by_image "${image}" - done -} - upgrade_media_node() { # Search local Openvidu installation printf '\n' @@ -220,7 +224,7 @@ upgrade_media_node() { printf '\n' sleep 1 - stop_and_remove_containers + stop_containers # Pull images printf "\n => Pulling images...\n" diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index f4d3866c..22ae4709 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -1,5 +1,41 @@ #!/bin/bash +# Deployed images in media-node +IMAGES=( + "kurento-media-server", + "docker.elastic.co/beats/filebeat", + "docker.elastic.co/beats/metricbeat", + "openvidu/media-node-controller" +) + +docker_command_by_container_image() { + IMAGE_NAME=$1 + COMMAND=$2 + if [[ ! -z "${IMAGE_NAME}" ]]; then + CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') + for CONTAINER_ID in ${CONTAINERS[@]}; do + if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then + docker "${COMMAND}" "${CONTAINER_ID}" + fi + done + fi +} + + +stop_containers() { + printf "Stopping containers..." + for IMAGE in ${IMAGES[@]}; do + docker_command_by_container_image "${IMAGE}" "rm -f" + done +} + +tail_latest_kurento_logs() { + LATEST_LOG_FILE=$(find /opt/openvidu/kurento-logs/* -printf '%T+ %p\n' | sort -r | head -1 | awk '{print $2}') + if [[ ! -z "${LATEST_LOG_FILE}" ]]; then + tail -f "${LATEST_LOG_FILE}" + fi +} + upgrade_media_node() { UPGRADE_SCRIPT_URL="https://s3-eu-west-1.amazonaws.com/aws.openvidu.io/install_media_node_OVVERSION.sh" HTTP_STATUS=$(curl -s -o /dev/null -I -w "%{http_code}" ${UPGRADE_SCRIPT_URL//OVVERSION/$1}) @@ -140,6 +176,16 @@ generate_report() { printf '\n' done + printf '\n' + printf "\n ---------------------------------------" + printf "\n KMS" + printf "\n ---------------------------------------" + printf '\n' + tail_latest_kurento_logs + printf "\n ---------------------------------------" + printf '\n' + printf '\n' + printf "\n =======================================" printf "\n = CONTAINER ENVS VARIABLES =" printf "\n =======================================" @@ -170,7 +216,7 @@ usage() { printf "\n\tstart\t\t\tStart media node service" printf "\n\tstop\t\t\tStop media node service" printf "\n\trestart\t\t\tRestart media node service" - printf "\n\tlogs\t\t\tShow media node logs" + printf "\n\tlogs \t\t\tShow logs by container name" printf "\n\tupgrade\t\t\tUpgrade to the lastest Media Node version" printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version" printf "\n\tversion\t\t\tShow version of Media Node" @@ -179,30 +225,6 @@ usage() { printf "\n" } -stop_container_by_image() { - IMAGE_NAME=$1 - if [[ ! -z "${IMAGE_NAME}" ]]; then - CONTAINER_ID=$(docker ps | grep "${IMAGE_NAME}" | awk '{print $1}') - if [[ ! -z "${CONTAINER_ID}" ]]; then - docker stop "${CONTAINER_ID}" - fi - fi -} - -stop_containers() { - IMAGES=( - "kurento-media-server", - "docker.elastic.co/beats/filebeat", - "docker.elastic.co/beats/metricbeat", - "openvidu/media-node-controller" - ) - - for image in ${IMAGES[@]} - do - stop_container_by_image "${image}" - done -} - case $1 in start) @@ -223,7 +245,13 @@ case $1 in ;; logs) - docker-compose logs -f media-node-controller + case $2 in + kms) + tail_latest_kurento_logs + ;; + *) + docker logs -f "$2" + ;; ;; upgrade) From 225f1756e261e9b3a603d3f724cd78923acd8680 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 12:10:29 +0100 Subject: [PATCH 227/435] openvidu-deployment: Better usage of logs command in media nodes --- .../deployments/pro/docker-compose/media-node/media_node | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index 22ae4709..01ff2f26 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -216,7 +216,8 @@ usage() { printf "\n\tstart\t\t\tStart media node service" printf "\n\tstop\t\t\tStop media node service" printf "\n\trestart\t\t\tRestart media node service" - printf "\n\tlogs \t\t\tShow logs by container name" + printf "\n\tlogs\t\t\tShow media-node-controller logs." + printf "\n\tlogs [container_name]\t\t\tShow logs by container name." printf "\n\tupgrade\t\t\tUpgrade to the lastest Media Node version" printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version" printf "\n\tversion\t\t\tShow version of Media Node" @@ -250,7 +251,11 @@ case $1 in tail_latest_kurento_logs ;; *) - docker logs -f "$2" + if [[ -z "$2" ]]; then + docker-compose logs -f media-node-controller + else + docker logs -f "$2" + fi ;; ;; From 35b667a083d9e42e8766ce474ded2a521d863aea Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 12:59:22 +0100 Subject: [PATCH 228/435] openvidu-deployment: Same commands to access kms logs in CE and PRO. Same directory for kms logs --- .../ce/docker-compose/docker-compose.yml | 2 ++ .../deployments/ce/docker-compose/openvidu | 21 ++++++++++++- .../pro/docker-compose/media-node/media_node | 31 ++++++++++--------- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index f62ef01c..545173c5 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -50,10 +50,12 @@ services: volumes: - /opt/openvidu/kms-crashes:/opt/openvidu/kms-crashes - ${OPENVIDU_RECORDING_PATH}:${OPENVIDU_RECORDING_PATH} + - /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs environment: - KMS_MIN_PORT=40000 - KMS_MAX_PORT=57000 - GST_DEBUG=${KMS_DOCKER_ENV_GST_DEBUG:-} + - KURENTO_LOGS_PATH=/opt/openvidu/kurento-logs redis: image: openvidu/openvidu-redis:1.0.0 diff --git a/openvidu-server/deployments/ce/docker-compose/openvidu b/openvidu-server/deployments/ce/docker-compose/openvidu index 64a67c36..267365e0 100755 --- a/openvidu-server/deployments/ce/docker-compose/openvidu +++ b/openvidu-server/deployments/ce/docker-compose/openvidu @@ -190,6 +190,9 @@ usage() { printf "\n\tstop\t\t\tStop all services" printf "\n\trestart\t\t\tRestart all stoped and running services" printf "\n\tlogs\t\t\tShow openvidu-server logs" + printf "\n\tlogs [-f]\t\t\tFollow openvidu logs" + printf "\n\tkms-logs\t\t\tShow kms logs" + printf "\n\tkms-logs [-f]\t\t\tFollow kms logs" printf "\n\tupgrade\t\t\tUpgrade to the lastest Openvidu version" printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version" printf "\n\tversion\t\t\tShow version of Openvidu Server" @@ -198,6 +201,11 @@ usage() { printf "\n" } +tail_kurento_logs() { + TAIL_ARGUMENTS=$1 + tail "${TAIL_ARGUMENTS}" /opt/openvidu/kurento-logs/* +} + case $1 in start) docker-compose up -d @@ -215,7 +223,18 @@ case $1 in ;; logs) - docker-compose logs -f openvidu-server + case $2 in + "-f") + docker-compose logs -f openvidu-server + ;; + *) + docker-compose logs openvidu-server + ;; + esac + ;; + + kms-logs) + tail_kurento_logs $2 ;; upgrade) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index 01ff2f26..5d61b466 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -29,11 +29,9 @@ stop_containers() { done } -tail_latest_kurento_logs() { - LATEST_LOG_FILE=$(find /opt/openvidu/kurento-logs/* -printf '%T+ %p\n' | sort -r | head -1 | awk '{print $2}') - if [[ ! -z "${LATEST_LOG_FILE}" ]]; then - tail -f "${LATEST_LOG_FILE}" - fi +tail_kurento_logs() { + TAIL_ARGUMENTS=$1 + tail "${TAIL_ARGUMENTS}" /opt/openvidu/kurento-logs/* } upgrade_media_node() { @@ -217,7 +215,9 @@ usage() { printf "\n\tstop\t\t\tStop media node service" printf "\n\trestart\t\t\tRestart media node service" printf "\n\tlogs\t\t\tShow media-node-controller logs." - printf "\n\tlogs [container_name]\t\t\tShow logs by container name." + printf "\n\tlogs [-f]\t\t\tFollow media-node-controller logs." + printf "\n\tkms-logs\t\t\tShow kms logs" + printf "\n\tkms-logs -f\t\t\tFollow kms logs" printf "\n\tupgrade\t\t\tUpgrade to the lastest Media Node version" printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version" printf "\n\tversion\t\t\tShow version of Media Node" @@ -247,16 +247,17 @@ case $1 in logs) case $2 in - kms) - tail_latest_kurento_logs - ;; + "-f") + docker-compose logs -f media-node-controller + ;; *) - if [[ -z "$2" ]]; then - docker-compose logs -f media-node-controller - else - docker logs -f "$2" - fi - ;; + docker-compose logs media-node-controller + ;; + esac + ;; + + kms-logs) + tail_kurento_logs $2 ;; upgrade) From 9b3f5792138d4f34bb3aa6b714f453b833641b62 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 13:06:20 +0100 Subject: [PATCH 229/435] openvidu-deployment: Max log size for Kurento Media Server in CE --- openvidu-server/deployments/ce/docker-compose/docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 545173c5..d0b44e33 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -55,6 +55,7 @@ services: - KMS_MIN_PORT=40000 - KMS_MAX_PORT=57000 - GST_DEBUG=${KMS_DOCKER_ENV_GST_DEBUG:-} + - KURENTO_LOG_FILE_SIZE=${KMS_DOCKER_ENV_KURENTO_LOG_FILE_SIZE:-100} - KURENTO_LOGS_PATH=/opt/openvidu/kurento-logs redis: From 67167b33784e778885d6039cf7ce93bc72d7ef48 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 14:58:44 +0100 Subject: [PATCH 230/435] openvidu-deployment: Fix kms-logs command --- .../deployments/ce/docker-compose/openvidu | 17 +++++++++-------- .../pro/docker-compose/media-node/media_node | 19 ++++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/openvidu b/openvidu-server/deployments/ce/docker-compose/openvidu index 267365e0..93b5f4ba 100755 --- a/openvidu-server/deployments/ce/docker-compose/openvidu +++ b/openvidu-server/deployments/ce/docker-compose/openvidu @@ -189,10 +189,8 @@ usage() { printf "\n\tstart\t\t\tStart all services" printf "\n\tstop\t\t\tStop all services" printf "\n\trestart\t\t\tRestart all stoped and running services" - printf "\n\tlogs\t\t\tShow openvidu-server logs" - printf "\n\tlogs [-f]\t\t\tFollow openvidu logs" - printf "\n\tkms-logs\t\t\tShow kms logs" - printf "\n\tkms-logs [-f]\t\t\tFollow kms logs" + printf "\n\tlogs [-f]\t\tShow openvidu logs." + printf "\n\tkms-logs [-f]\t\tShow kms logs" printf "\n\tupgrade\t\t\tUpgrade to the lastest Openvidu version" printf "\n\tupgrade [version]\tUpgrade to the specific Openvidu version" printf "\n\tversion\t\t\tShow version of Openvidu Server" @@ -201,9 +199,12 @@ usage() { printf "\n" } -tail_kurento_logs() { - TAIL_ARGUMENTS=$1 - tail "${TAIL_ARGUMENTS}" /opt/openvidu/kurento-logs/* +kurento_logs() { + if [[ "$1" == "-f" ]]; then + tail -f /opt/openvidu/kurento-logs/*.log + else + cat /opt/openvidu/kurento-logs/*.log + fi } case $1 in @@ -234,7 +235,7 @@ case $1 in ;; kms-logs) - tail_kurento_logs $2 + kurento_logs $2 ;; upgrade) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index 5d61b466..2a95e523 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -29,9 +29,12 @@ stop_containers() { done } -tail_kurento_logs() { - TAIL_ARGUMENTS=$1 - tail "${TAIL_ARGUMENTS}" /opt/openvidu/kurento-logs/* +kurento_logs() { + if [[ "$1" == "-f" ]]; then + tail -f /opt/openvidu/kurento-logs/*.log + else + cat /opt/openvidu/kurento-logs/*.log + fi } upgrade_media_node() { @@ -179,7 +182,7 @@ generate_report() { printf "\n KMS" printf "\n ---------------------------------------" printf '\n' - tail_latest_kurento_logs + kurento_logs printf "\n ---------------------------------------" printf '\n' printf '\n' @@ -214,10 +217,8 @@ usage() { printf "\n\tstart\t\t\tStart media node service" printf "\n\tstop\t\t\tStop media node service" printf "\n\trestart\t\t\tRestart media node service" - printf "\n\tlogs\t\t\tShow media-node-controller logs." - printf "\n\tlogs [-f]\t\t\tFollow media-node-controller logs." - printf "\n\tkms-logs\t\t\tShow kms logs" - printf "\n\tkms-logs -f\t\t\tFollow kms logs" + printf "\n\tlogs [-f]\t\tShow media-node-controller logs." + printf "\n\tkms-logs [-f]\t\tShow kms logs" printf "\n\tupgrade\t\t\tUpgrade to the lastest Media Node version" printf "\n\tupgrade [version]\tUpgrade to the specific Media Node version" printf "\n\tversion\t\t\tShow version of Media Node" @@ -257,7 +258,7 @@ case $1 in ;; kms-logs) - tail_kurento_logs $2 + kurento_logs $2 ;; upgrade) From 2f10170fc7d63d89209e08488e4d15128c899b4e Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 15:18:47 +0100 Subject: [PATCH 231/435] Add all kurento logs saved on generating report in CE --- openvidu-server/deployments/ce/docker-compose/openvidu | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openvidu-server/deployments/ce/docker-compose/openvidu b/openvidu-server/deployments/ce/docker-compose/openvidu index 93b5f4ba..3e607918 100755 --- a/openvidu-server/deployments/ce/docker-compose/openvidu +++ b/openvidu-server/deployments/ce/docker-compose/openvidu @@ -159,6 +159,16 @@ generate_report() { printf '\n' done + printf '\n' + printf "\n ---------------------------------------" + printf "\n KMS" + printf "\n ---------------------------------------" + printf '\n' + kurento_logs + printf "\n ---------------------------------------" + printf '\n' + printf '\n' + printf "\n =======================================" printf "\n = CONTAINER ENVS VARIABLES =" printf "\n =======================================" From 641a48af8d6b589c3c213bab3de3225fb46bc7e6 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 15:55:33 +0100 Subject: [PATCH 232/435] openvidu-deployment: Default max log file size to 100M. Parametrizable with DOCKER_LOGS_MAX_SIZE --- .../docker-compose.override.yml | 3 +++ .../ce/docker-compose/docker-compose.yml | 15 +++++++++++++ .../media-node/docker-compose.yml | 3 +++ .../docker-compose.override.yml | 3 +++ .../openvidu-server-pro/docker-compose.yml | 21 +++++++++++++++++++ 5 files changed, 45 insertions(+) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml index d1f07b76..ec6a4795 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml @@ -21,3 +21,6 @@ services: - OPENVIDU_URL=http://localhost:5443 - OPENVIDU_SECRET=${OPENVIDU_SECRET} - CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index d0b44e33..054f6535 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -40,6 +40,9 @@ services: - COTURN_REDIS_IP=127.0.0.1 - COTURN_REDIS_PASSWORD=${OPENVIDU_SECRET} - COTURN_IP=${COTURN_IP:-auto-ipv4} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" kms: image: ${KMS_IMAGE:-kurento/kurento-media-server:6.15.0} @@ -57,6 +60,9 @@ services: - GST_DEBUG=${KMS_DOCKER_ENV_GST_DEBUG:-} - KURENTO_LOG_FILE_SIZE=${KMS_DOCKER_ENV_KURENTO_LOG_FILE_SIZE:-100} - KURENTO_LOGS_PATH=/opt/openvidu/kurento-logs + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" redis: image: openvidu/openvidu-redis:1.0.0 @@ -64,6 +70,9 @@ services: network_mode: host environment: - REDIS_PASSWORD=${OPENVIDU_SECRET} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" coturn: image: openvidu/openvidu-coturn:2.0.0-dev3 @@ -76,6 +85,9 @@ services: - DB_PASSWORD=${OPENVIDU_SECRET} - MIN_PORT=57001 - MAX_PORT=65535 + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: image: openvidu/openvidu-proxy:4.0.0-dev5 @@ -100,3 +112,6 @@ services: - REDIRECT_WWW=${REDIRECT_WWW:-false} - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} - PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index 1dc3fcc5..b1ca536f 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -33,3 +33,6 @@ services: - /var/run/docker.sock:/var/run/docker.sock - /opt/openvidu/kurento-logs:/opt/openvidu/kurento-logs - ./beats:/beats + logging: + options: + max-size: "100M" diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml index d1f07b76..ec6a4795 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml @@ -21,3 +21,6 @@ services: - OPENVIDU_URL=http://localhost:5443 - OPENVIDU_SECRET=${OPENVIDU_SECRET} - CALL_OPENVIDU_CERTTYPE=${CERTIFICATE_TYPE} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index f0de5eb6..50c7e5c3 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -47,6 +47,9 @@ services: - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} - WAIT_KIBANA_URL=${OPENVIDU_PRO_KIBANA_HOST:-http://127.0.0.1/kibana} - DOTENV_PATH=${PWD} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" redis: image: openvidu/openvidu-redis:1.0.0 @@ -54,6 +57,9 @@ services: network_mode: host environment: - REDIS_PASSWORD=${OPENVIDU_SECRET} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" coturn: image: openvidu/openvidu-coturn:2.0.0-dev3 @@ -67,6 +73,9 @@ services: - MIN_PORT=40000 - MAX_PORT=65535 - TURN_PUBLIC_IP=${TURN_PUBLIC_IP:-auto-ipv4} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: image: openvidu/openvidu-proxy:4.0.0-dev5 @@ -91,6 +100,9 @@ services: - REDIRECT_WWW=${REDIRECT_WWW:-false} - WORKER_CONNECTIONS=${WORKER_CONNECTIONS:-10240} - PUBLIC_IP=${PROXY_PUBLIC_IP:-auto-ipv4} + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" elasticsearch: @@ -107,6 +119,9 @@ services: /bin/bash -c "elasticsearch-users useradd ${ELASTICSEARCH_USERNAME} -p ${ELASTICSEARCH_PASSWORD} -r superuser; docker-entrypoint.sh" + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" kibana: image: docker.elastic.co/kibana/kibana:7.8.0 @@ -118,6 +133,9 @@ services: - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_PASSWORD} ports: - 5601:5601 + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" filebeat: image: docker.elastic.co/beats/filebeat-oss:7.8.0 @@ -136,3 +154,6 @@ services: /bin/bash -c "filebeat -e -strict.perms=false `if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi` `if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`" + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" From 21d606cd14989bfac9fdce7c78ce6f6a348aa6da Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 16:30:34 +0100 Subject: [PATCH 233/435] Heap Memory parametrizable --- .../pro/docker-compose/openvidu-server-pro/.env | 9 ++++++++- .../openvidu-server-pro/docker-compose.yml | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 62496325..1d2974de 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -258,12 +258,19 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr # RECOMENDED VALUES: INFO for normal logs DEBUG for more verbose logs # OV_CE_DEBUG_LEVEL=INFO -# Java Options +# OpenVidu Java Options # -------------------------- # Uncomment the next line and define this to add options to java command # Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058 # JAVA_OPTIONS=-Xms2048m -Xmx4096m +# ElasticSearch Java Options +# -------------------------- +# Uncomment the next line and define this to add options to java command of Elasticsearch +# Documentation: https://docs.oracle.com/cd/E37116_01/install.111210/e23737/configuring_jvm.htm#OUDIG00058 +# By default ElasticSearch is configured to use "-Xms2g -Xmx2g" as Java Min and Max memory heap allocation +# ES_JAVA_OPTS=-Xms2048m -Xmx4096m + # Kibana And ElasticSearch Configuration # -------------------------- # Kibana And ElasticSearch Basic Auth configuration (Credentials) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 50c7e5c3..830eecad 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -111,6 +111,7 @@ services: environment: - discovery.type=single-node - xpack.security.enabled=true + - "ES_JAVA_OPTS=${ES_JAVA_OPTS:--Xms2g -Xmx2g}" ports: - 9200:9200 volumes: From 40b0c524f0dec54154a6b69d09bd3751b9aa3cab Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 16:39:22 +0100 Subject: [PATCH 234/435] openvidu-deployment: Check secret in cloudformation yml --- openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template | 4 ++-- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template index d5e3a147..4dac94cc 100644 --- a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template +++ b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template @@ -46,9 +46,9 @@ Parameters: OpenViduSecret: Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed" Type: String - AllowedPattern: ^((?!")(?! ).)+$ + AllowedPattern: ^[a-zA-Z0-9_-]+$ NoEcho: true - ConstraintDescription: OpenVidu Secret is mandatory + ConstraintDescription: "Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')" # EC2 Instance configuration diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 9b913da4..14f4211f 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -70,9 +70,9 @@ Parameters: OpenViduSecret: Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed" Type: String - AllowedPattern: ^((?!")(?! ).)+$ + AllowedPattern: ^[a-zA-Z0-9_-]+$ NoEcho: true - ConstraintDescription: OpenVidu Secret is mandatory (no whitespaces or quotations allowed) + ConstraintDescription: "Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')" MediaNodesStartNumber: Description: "How many Media Nodes do you want on startup (EC2 instances will be launched)" From c3d9fbb60e6c6922d9b3ff5b6abae991c41cff93 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 16:57:24 +0100 Subject: [PATCH 235/435] openvidu-deployment: Default value for instances: c5.xlarge --- openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template | 2 +- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template index 4dac94cc..f0f92cc5 100644 --- a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template +++ b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template @@ -55,7 +55,7 @@ Parameters: InstanceType: Description: "Specifies the EC2 instance type for your OpenVidu instance" Type: String - Default: t2.xlarge + Default: c5.xlarge AllowedValues: - t2.large - t2.xlarge diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 14f4211f..5d8f0651 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -99,7 +99,7 @@ Parameters: AwsInstanceTypeOV: Description: "Specifies the EC2 instance type for your OpenVidu Server Pro Node" Type: String - Default: t2.xlarge + Default: c5.xlarge AllowedValues: - t2.large - t2.xlarge @@ -139,7 +139,7 @@ Parameters: AwsInstanceTypeKMS: Description: "Specifies the EC2 instance type for your Media Nodes" Type: String - Default: t2.xlarge + Default: c5.xlarge AllowedValues: - t2.large - t2.xlarge From df0530d0a8132d0460a4375f8f6ec83edc6acc8e Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 5 Nov 2020 17:33:25 +0100 Subject: [PATCH 236/435] openvidu-test-e2e: new network quality e2e test --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- .../test/e2e/OpenViduEventManager.java | 3 +- .../test/e2e/OpenViduProTestAppE2eTest.java | 134 ++++++++++++++++++ .../openvidu-instance.component.html | 54 ++++--- .../openvidu-instance.component.ts | 15 +- .../test-sessions/test-sessions.component.ts | 38 ++--- 6 files changed, 194 insertions(+), 52 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index e8aa5064..43e499cb 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -140,7 +140,7 @@ node('container') { mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST cd openvidu-test-e2e - mvn -DskipTests=true clean compile + mvn -DskipTests=true clean install sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java index db1a8d22..be49e3b1 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduEventManager.java @@ -283,9 +283,8 @@ public class OpenViduEventManager { } String[] events = rawEvents.replaceFirst("^
          ", "").split("
          "); - JsonParser parser = new JsonParser(); for (String e : events) { - JsonObject event = (JsonObject) parser.parse(e); + JsonObject event = JsonParser.parseString(e).getAsJsonObject(); final String eventType = event.get("type").getAsString(); this.eventQueue.add(event); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 01df4abc..e9eb3f90 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -1,13 +1,22 @@ package io.openvidu.test.e2e; +import static org.junit.Assert.fail; + import java.io.File; import java.io.FileReader; +import java.util.Iterator; import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.http.HttpStatus; import org.junit.Assert; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -36,6 +45,8 @@ import io.openvidu.test.browsers.utils.Unzipper; public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { + protected volatile static boolean isNetworkQualityTest; + @BeforeAll() protected static void setupAll() { checkFfmpegInstallation(); @@ -44,6 +55,29 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { cleanFoldersAndSetUpOpenViduJavaClient(); } + @Override + @AfterEach + protected void dispose() { + super.dispose(); + if (isNetworkQualityTest) { + // Disable network quality API + try { + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + if (restClient.rest(HttpMethod.GET, "/openvidu/api/config", 200).get("OPENVIDU_PRO_NETWORK_QUALITY") + .getAsBoolean()) { + String body = "{'OPENVIDU_PRO_NETWORK_QUALITY':false}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/restart", body, 200); + waitUntilOpenViduRestarted(30); + } + } catch (Exception e) { + log.error(e.getMessage()); + Assert.fail("Error restarting OpenVidu Server to disable Network quality API"); + } finally { + isNetworkQualityTest = false; + } + } + } + @Test @DisplayName("Individual dynamic record") void individualDynamicRecordTest() throws Exception { @@ -449,6 +483,9 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { @Test @DisplayName("openvidu-java-client PRO test") void openViduJavaClientProTest() throws Exception { + + log.info("openvidu-java-client PRO test"); + Session session = OV.createSession(); Assert.assertFalse(session.fetch()); Connection connection = session.createConnection(); @@ -462,4 +499,101 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { Assert.assertFalse(session.fetch()); } + @Test + @DisplayName("Network quality test") + void networkQualityTest() throws Exception { + + isNetworkQualityTest = true; + + log.info("Network quality test"); + + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + String body = "{'OPENVIDU_PRO_NETWORK_QUALITY':true, 'OPENVIDU_PRO_NETWORK_QUALITY_INTERVAL':5}"; + restClient.rest(HttpMethod.POST, "/openvidu/api/restart", body, 200); + waitUntilOpenViduRestarted(30); + + setupBrowser("chrome"); + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.className("join-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 1); + user.getEventManager().waitUntilEventReaches("streamPlaying", 1); + JsonObject res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/TestSession/connection", + HttpStatus.SC_OK); + final String connectionId = res.getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject() + .get("id").getAsString(); + + user.getDriver().findElement(By.id("add-user-btn")).click(); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .publish-checkbox")).click(); + user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); + + final CountDownLatch latch1 = new CountDownLatch(1); + Queue threadAssertions = new ConcurrentLinkedQueue(); + user.getEventManager().on("networkQualityLevelChanged", (event) -> { + try { + threadAssertions.add("networkQualityLevelChanged".equals(event.get("type").getAsString())); + threadAssertions.add(event.get("oldValue") == null); + threadAssertions.add(event.has("newValue") && event.get("newValue").getAsInt() > 0 + && event.get("newValue").getAsInt() < 6); + latch1.countDown(); + } catch (Exception e) { + log.error("Error analysing NetworkQualityLevelChangedEvent: {}. {}", e.getCause(), e.getMessage()); + fail("Error analysing NetworkQualityLevelChangedEvent: " + e.getCause() + ". " + e.getMessage()); + } + }); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("streamPlaying", 2); + user.getEventManager().waitUntilEventReaches("networkQualityLevelChanged", 2); + + if (!latch1.await(30000, TimeUnit.MILLISECONDS)) { + gracefullyLeaveParticipants(1); + fail(); + return; + } + + user.getEventManager().off("networkQualityLevelChanged"); + log.info("Thread assertions: {}", threadAssertions.toString()); + for (Iterator iter = threadAssertions.iterator(); iter.hasNext();) { + Assert.assertTrue("Some Event property was wrong", iter.next()); + iter.remove(); + } + + // Both events should have publisher's connection ID + Assert.assertTrue("Wrong connectionId in event NetworkQualityLevelChangedEvent", user.getDriver() + .findElement(By.cssSelector("#openvidu-instance-0 .mat-expansion-panel:last-child .event-content")) + .getAttribute("textContent").contains(connectionId)); + Assert.assertTrue("Wrong connectionId in event NetworkQualityLevelChangedEvent", user.getDriver() + .findElement(By.cssSelector("#openvidu-instance-1 .mat-expansion-panel:last-child .event-content")) + .getAttribute("textContent").contains(connectionId)); + + gracefullyLeaveParticipants(1); + } + + private void waitUntilOpenViduRestarted(int maxSecondsWait) throws Exception { + boolean restarted = false; + int msInterval = 500; + int attempts = 0; + final int maxAttempts = maxSecondsWait * 1000 / msInterval; + Thread.sleep(500); + while (!restarted && attempts < maxAttempts) { + try { + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + restClient.rest(HttpMethod.GET, "/openvidu/api/health", 200); + restarted = true; + } catch (Exception e) { + try { + log.warn("Waiting for OpenVidu Server..."); + Thread.sleep(msInterval); + } catch (InterruptedException e1) { + log.error("Sleep interrupted"); + } + attempts++; + } + } + if (!restarted && attempts == maxAttempts) { + throw new TimeoutException(); + } + } + } diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html index 4e1e16ef..471988a5 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.html @@ -18,16 +18,16 @@
          - -
          @@ -36,8 +36,8 @@
          - + Publish
          @@ -48,26 +48,32 @@

          Send

          - Audio - Video + Audio + + Video +

          Enter active

          - Audio - Video + Audio + Video
      - +
      Video
      @@ -75,15 +81,16 @@ Screen
      -
      -
      - + diff --git a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts index 5cfb392f..41578430 100644 --- a/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts +++ b/openvidu-testapp/src/app/components/openvidu-instance/openvidu-instance.component.ts @@ -6,7 +6,7 @@ import { import { OpenVidu, Session, Subscriber, Publisher, Event, StreamEvent, ConnectionEvent, SessionDisconnectedEvent, SignalEvent, RecordingEvent, - PublisherSpeakingEvent, PublisherProperties, StreamPropertyChangedEvent, ConnectionPropertyChangedEvent, OpenViduError + PublisherSpeakingEvent, PublisherProperties, StreamPropertyChangedEvent, ConnectionPropertyChangedEvent, OpenViduError, NetworkQualityLevelChangedEvent } from 'openvidu-browser'; import { OpenVidu as OpenViduAPI, @@ -116,6 +116,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamDestroyed: true, streamPropertyChanged: true, connectionPropertyChanged: true, + networkQualityLevelChanged: true, recordingStarted: true, recordingStopped: true, signal: true, @@ -225,6 +226,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamDestroyed: false, streamPropertyChanged: false, connectionPropertyChanged: false, + networkQualityLevelChanged: false, recordingStarted: false, recordingStopped: false, signal: false, @@ -383,6 +385,15 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { } } + if (this.sessionEvents.networkQualityLevelChanged !== oldValues.networkQualityLevelChanged || firstTime) { + this.session.off('networkQualityLevelChanged'); + if (this.sessionEvents.networkQualityLevelChanged) { + this.session.on('networkQualityLevelChanged', (event: NetworkQualityLevelChangedEvent) => { + this.updateEventList('networkQualityLevelChanged', event.connection.connectionId + ' [new:' + event.newValue + ',old:' + event.oldValue + ']', event); + }); + } + } + if (this.sessionEvents.connectionCreated !== oldValues.connectionCreated || firstTime) { this.session.off('connectionCreated'); if (this.sessionEvents.connectionCreated) { @@ -638,6 +649,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamDestroyed: this.sessionEvents.streamDestroyed, streamPropertyChanged: this.sessionEvents.streamPropertyChanged, connectionPropertyChanged: this.sessionEvents.connectionPropertyChanged, + networkQualityLevelChanged: this.sessionEvents.networkQualityLevelChanged, recordingStarted: this.sessionEvents.recordingStarted, recordingStopped: this.sessionEvents.recordingStopped, signal: this.sessionEvents.signal, @@ -671,6 +683,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy { streamDestroyed: result.streamDestroyed, streamPropertyChanged: result.streamPropertyChanged, connectionPropertyChanged: result.connectionPropertyChanged, + networkQualityLevelChanged: result.networkQualityLevelChanged, recordingStarted: result.recordingStarted, recordingStopped: result.recordingStopped, signal: result.signal, diff --git a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts index 6db82d6c..4bff8df3 100644 --- a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts +++ b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts @@ -38,7 +38,19 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.eventsInfoSubscription = this.testFeedService.newLastEvent$.subscribe( newEvent => { - (window as any).myEvents += ('
      ' + this.stringifyEventNoCircularDependencies(newEvent)); + const getCircularReplacer = () => { + const seen = new WeakSet(); + return (key, value) => { + if (typeof value === "object" && value !== null) { + if (seen.has(value)) { + return; + } + seen.add(value); + } + return value; + }; + }; + (window as any).myEvents += ('
      ' + JSON.stringify(newEvent, getCircularReplacer())); }); } @@ -100,28 +112,4 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.loadSubs(subs); } - stringifyEventNoCircularDependencies(event: Event): string { - const cache = []; - return JSON.stringify(event, function (key, value) { - if (key !== 'ee' && key !== 'openvidu') { - if (typeof value === 'object' && value !== null) { - if (cache.indexOf(value) !== -1) { - // Duplicate reference found - try { - // If this value does not reference a parent - return JSON.parse(JSON.stringify(value)); - } catch (error) { - return; - } - } - // Store value in our collection - cache.push(value); - } - return value; - } else { - return; - } - }); - } - } From 1879bc81b5284183b07b7125a9a8b67e761c1248 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 18:08:20 +0100 Subject: [PATCH 237/435] Comment default value of 'OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE' --- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 1d2974de..d6f93ab1 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -135,6 +135,7 @@ OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams # Max days until delete indexes in state of rollover on Elasticsearch # Type number >= 0 +# Default Value is 15 # OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE= # Private IP of OpenVidu Server Pro From bae71aa837d72a571bf2a4d1f5c8a4272c826eb6 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 5 Nov 2020 18:12:01 +0100 Subject: [PATCH 238/435] Bump openvidu pro version --- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 830eecad..33faf4a4 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server-pro:2.16.0-dev6 + image: openvidu/openvidu-server-pro:2.16.0-dev7 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] From 090164ece9ac566e84508909265bc56c1575faa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Fuente=20P=C3=A9rez?= Date: Thu, 5 Nov 2020 19:02:31 +0100 Subject: [PATCH 239/435] Update .env --- .../docker-compose/openvidu-server-pro/.env | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index d6f93ab1..05527602 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -133,14 +133,21 @@ OPENVIDU_PRO_CLUSTER_AUTOSCALING=false # (and therefore distribution of load) among all available Media Nodes OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams -# Max days until delete indexes in state of rollover on Elasticsearch -# Type number >= 0 -# Default Value is 15 -# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE= +# What parameter should be used to distribute the creation of new sessions +# (and therefore distribution of load) among all available Media Nodes +OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams -# Private IP of OpenVidu Server Pro -# For example 192.168.1.101 -# OPENVIDU_PRO_PRIVATE_IP= +# What parameter should be used to distribute the creation of new sessions +# (and therefore distribution of load) among all available Media Nodes +OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams + +# Whether to enable or disable Network Quality API. You can monitor and +# warn users about the quality of their networks with this feature +# OPENVIDU_PRO_NETWORK_QUALITY=false + +# If OPENVIDU_PRO_NETWORK_QUALITY=true, how often the network quality +# algorithm will be invoked for each user, in seconds +# OPENVIDU_PRO_NETWORK_QUALITY_INTERVAL=5 # Where to store recording files. Can be “local” (local storage) or “s3” (AWS bucket). # You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it. From c9eeef958fb67b1d35940401eb219b7bfbbff7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Fuente=20P=C3=A9rez?= Date: Thu, 5 Nov 2020 19:04:45 +0100 Subject: [PATCH 240/435] Update .env --- .../pro/docker-compose/openvidu-server-pro/.env | 8 -------- 1 file changed, 8 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 05527602..064b9577 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -133,14 +133,6 @@ OPENVIDU_PRO_CLUSTER_AUTOSCALING=false # (and therefore distribution of load) among all available Media Nodes OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams -# What parameter should be used to distribute the creation of new sessions -# (and therefore distribution of load) among all available Media Nodes -OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams - -# What parameter should be used to distribute the creation of new sessions -# (and therefore distribution of load) among all available Media Nodes -OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams - # Whether to enable or disable Network Quality API. You can monitor and # warn users about the quality of their networks with this feature # OPENVIDU_PRO_NETWORK_QUALITY=false From af3ed0ed5e83e422a03686bbcadffa0f8deba58c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 5 Nov 2020 19:08:28 +0100 Subject: [PATCH 241/435] .env rollback --- .../pro/docker-compose/openvidu-server-pro/.env | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 064b9577..4490998a 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -141,6 +141,15 @@ OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams # algorithm will be invoked for each user, in seconds # OPENVIDU_PRO_NETWORK_QUALITY_INTERVAL=5 +# Max days until delete indexes in state of rollover on Elasticsearch +# Type number >= 0 +# Default Value is 15 +# OPENVIDU_PRO_ELASTICSEARCH_MAX_DAYS_DELETE= + +# Private IP of OpenVidu Server Pro +# For example 192.168.1.101 +# OPENVIDU_PRO_PRIVATE_IP= + # Where to store recording files. Can be “local” (local storage) or “s3” (AWS bucket). # You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it. #OPENVIDU_PRO_RECORDING_STORAGE= From 70de481fef6a6b700d2fbd14251d8f73a74f59ea Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 5 Nov 2020 23:50:55 +0100 Subject: [PATCH 242/435] openvidu-testapp: rollback event circular dependency --- .../test-sessions/test-sessions.component.ts | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts index 4bff8df3..bdb486ed 100644 --- a/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts +++ b/openvidu-testapp/src/app/components/test-sessions/test-sessions.component.ts @@ -38,19 +38,7 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.eventsInfoSubscription = this.testFeedService.newLastEvent$.subscribe( newEvent => { - const getCircularReplacer = () => { - const seen = new WeakSet(); - return (key, value) => { - if (typeof value === "object" && value !== null) { - if (seen.has(value)) { - return; - } - seen.add(value); - } - return value; - }; - }; - (window as any).myEvents += ('
      ' + JSON.stringify(newEvent, getCircularReplacer())); + (window as any).myEvents += ('
      ' + this.stringifyEventNoCircularDependencies(newEvent)); }); } @@ -112,4 +100,28 @@ export class TestSessionsComponent implements OnInit, OnDestroy { this.loadSubs(subs); } + stringifyEventNoCircularDependencies(event: Event): string { + const cache = []; + return JSON.stringify(event, function (key, value) { + if (key !== 'ee' && key !== 'openvidu') { + if (typeof value === 'object' && value !== null) { + if (cache.indexOf(value) !== -1) { + // Duplicate reference found + try { + // If this value does not reference a parent + return JSON.parse(JSON.stringify(value)); + } catch (error) { + return; + } + } + // Store value in our collection + cache.push(value); + } + return value; + } else { + return; + } + }); + } + } From 5319c0a77b5be758fd841f0169c9555929576817 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 00:03:12 +0100 Subject: [PATCH 243/435] openvidu-deployment: Fix some typos --- .../deployments/ce/aws/CF-OpenVidu.yaml.template | 2 +- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 2 +- .../pro/docker-compose/media-node/install_media_node.sh | 4 ++-- .../openvidu-server-pro/install_openvidu_pro.sh | 6 ++++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template index f0f92cc5..7a1baf28 100644 --- a/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template +++ b/openvidu-server/deployments/ce/aws/CF-OpenVidu.yaml.template @@ -44,7 +44,7 @@ Parameters: # OpenVidu configuration OpenViduSecret: - Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed" + Description: "Secret to connect to this OpenVidu Platform. Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')" Type: String AllowedPattern: ^[a-zA-Z0-9_-]+$ NoEcho: true diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 5d8f0651..21b82e5d 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -68,7 +68,7 @@ Parameters: ConstraintDescription: OpenVidu Pro License is mandatory OpenViduSecret: - Description: "Secret to connect to this OpenVidu Platform. No whitespaces or quotations allowed" + Description: "Secret to connect to this OpenVidu Platform. Cannot be empty and must contain only alphanumeric characters [a-zA-Z0-9], hypens ('-') and underscores ('_')" Type: String AllowedPattern: ^[a-zA-Z0-9_-]+$ NoEcho: true diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index 8bdd8fa2..5b7aa25e 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -117,7 +117,7 @@ new_media_node_installation() { printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' - printf '\n KMS_URIS=["ws://:8888/kurento"]' + printf '\n KMS_URIS=["ws://:8888/kurento"]' printf '\n ...' printf '\n You can also add this node from inspector' printf '\n' @@ -323,7 +323,7 @@ upgrade_media_node() { printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' - printf '\n KMS_URIS=["ws://:8888/kurento"]' + printf '\n KMS_URIS=["ws://:8888/kurento"]' printf '\n ...' printf '\n You can also add Media Nodes from inspector' printf '\n' diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index c6792a9f..27268ba9 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -110,13 +110,15 @@ new_ov_installation() { printf '\n 1. Go to openvidu folder:' printf '\n $ cd openvidu' printf '\n' - printf '\n 2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, OPENVIDU_SECRET, and ELASTICSEARCH_PASSWORD in .env file:' + printf '\n 2. Configure OPENVIDU_DOMAIN_OR_PUBLIC_IP, OPENVIDU_PRO_LICENSE, ' + printf '\n OPENVIDU_SECRET, and ELASTICSEARCH_PASSWORD in .env file:' printf '\n $ nano .env' printf '\n' printf '\n 3. Start OpenVidu' printf '\n $ ./openvidu start' printf '\n' - printf "\n CAUTION: The folder 'openvidu/elasticsearch' use user and group 1000 permissions. This folder is necessary for store elasticsearch data." + printf "\n CAUTION: The folder 'openvidu/elasticsearch' use user and group 1000 permissions. " + printf "\n This folder is necessary for store elasticsearch data." printf "\n For more information, check:" printf "\n https://docs.openvidu.io/en/${OPENVIDU_VERSION//v}/openvidu-pro/deployment/on-premises/#deployment-instructions" printf '\n' From 8bdb5ba8be0600269c34427917bb6970d4b2966e Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 10:58:22 +0100 Subject: [PATCH 244/435] openvidu-deployment: Don't fail in CI if AWS_KEY_NAME is not defined --- openvidu-server/deployments/ce/aws/createAMI.sh | 1 + openvidu-server/deployments/pro/aws/createAMIs.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/openvidu-server/deployments/ce/aws/createAMI.sh b/openvidu-server/deployments/ce/aws/createAMI.sh index a257b46d..1f6f70a5 100755 --- a/openvidu-server/deployments/ce/aws/createAMI.sh +++ b/openvidu-server/deployments/ce/aws/createAMI.sh @@ -2,6 +2,7 @@ set -eu -o pipefail CF_RELEASE=${CF_RELEASE:-false} +AWS_KEY_NAME=${AWS_KEY_NAME:-} if [[ $CF_RELEASE == "true" ]]; then git checkout v$OPENVIDU_VERSION diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index 055ba0ff..ee4c6973 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -2,6 +2,7 @@ set -eu -o pipefail CF_RELEASE=${CF_RELEASE:-false} +AWS_KEY_NAME=${AWS_KEY_NAME:-} if [[ $CF_RELEASE == "true" ]]; then git checkout v$OPENVIDU_PRO_VERSION From 1bff7194f324020a00159088c3dec75f835abce2 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 11:48:24 +0100 Subject: [PATCH 245/435] openvidu-deployment: Increased AMI size for OpenVidu PRO AMI --- .../deployments/pro/aws/cfn-mkt-ov-ami.yaml.template | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template index e2a5fda5..8598d34e 100644 --- a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template @@ -104,6 +104,13 @@ Resources: Tags: - Key: Name Value: !Ref AWS::StackName + BlockDeviceMappings: + - DeviceName: /dev/sda1 + Ebs: + VolumeType: gp2 + Iops: 100 + DeleteOnTermination: true + VolumeSize: 10 UserData: "Fn::Base64": !Sub | From b05765dd40ab3df811e089270c37668aaa7243ff Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 11:54:52 +0100 Subject: [PATCH 246/435] Use same volume size in CE and PRO --- .../pro/aws/cfn-openvidu-server-pro-no-market.yaml.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template index 21b82e5d..a5a0c46e 100644 --- a/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-openvidu-server-pro-no-market.yaml.template @@ -641,7 +641,7 @@ Resources: VolumeType: io1 Iops: 200 DeleteOnTermination: true - VolumeSize: 50 + VolumeSize: 100 KMSSecurityGroup: Type: 'AWS::EC2::SecurityGroup' From 218c447e6b6b2b55ce3b8f82aaa9c3eef21c48c2 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 11:59:32 +0100 Subject: [PATCH 247/435] openvidu-deployment: Don't use IOPS with gp2 --- openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template | 1 - 1 file changed, 1 deletion(-) diff --git a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template index 8598d34e..af2d2af5 100644 --- a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template @@ -108,7 +108,6 @@ Resources: - DeviceName: /dev/sda1 Ebs: VolumeType: gp2 - Iops: 100 DeleteOnTermination: true VolumeSize: 10 UserData: From e2011a52cf9bb4b62f066363d1a217f515d93683 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 12:34:22 +0100 Subject: [PATCH 248/435] openvidu-deployment: Unfortunately, aws cli does not have a way to increase timeout or max retries... --- openvidu-server/deployments/ce/aws/createAMI.sh | 10 +++++++++- openvidu-server/deployments/pro/aws/createAMIs.sh | 11 ++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/createAMI.sh b/openvidu-server/deployments/ce/aws/createAMI.sh index 1f6f70a5..35e47525 100755 --- a/openvidu-server/deployments/ce/aws/createAMI.sh +++ b/openvidu-server/deployments/ce/aws/createAMI.sh @@ -80,7 +80,15 @@ echo "Cleaning up" aws cloudformation delete-stack --stack-name openvidu-ce-${DATESTAMP} # Wait for the instance -aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} +# Unfortunately, aws cli does not have a way to increase timeout +WAIT_RETRIES=0 +WAIT_MAX_RETRIES=3 +until [ "${WAIT_RETRIES}" -ge "${WAIT_MAX_RETRIES}" ] +do + aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} && break + WAIT_RETRIES=$((WAIT_RETRIES+1)) + sleep 5 +done # Updating the template sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" CF-OpenVidu.yaml.template > CF-OpenVidu-${OPENVIDU_VERSION}.yaml diff --git a/openvidu-server/deployments/pro/aws/createAMIs.sh b/openvidu-server/deployments/pro/aws/createAMIs.sh index ee4c6973..adbc6c88 100755 --- a/openvidu-server/deployments/pro/aws/createAMIs.sh +++ b/openvidu-server/deployments/pro/aws/createAMIs.sh @@ -121,7 +121,16 @@ echo "Cleaning up" aws cloudformation delete-stack --stack-name openvidu-${DATESTAMP} # Wait for the instance -aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} +# Unfortunately, aws cli does not have a way to increase timeout +WAIT_RETRIES=0 +WAIT_MAX_RETRIES=3 +until [ "${WAIT_RETRIES}" -ge "${WAIT_MAX_RETRIES}" ] +do + aws ec2 wait image-available --image-ids ${OV_RAW_AMI_ID} && break + WAIT_RETRIES=$((WAIT_RETRIES+1)) + sleep 5 +done + # Updating the template sed "s/OV_AMI_ID/${OV_RAW_AMI_ID}/" cfn-openvidu-server-pro-no-market.yaml.template > cfn-openvidu-server-pro-no-market-${OPENVIDU_PRO_VERSION}.yaml From 45f518362e1c8ec39e0feffe52f67e23a2e32039 Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 12:55:42 +0100 Subject: [PATCH 249/435] Increase timeout AMIs --- .../deployments/ce/aws/cfn-mkt-ov-ce-ami.yaml.template | 2 +- .../deployments/pro/aws/cfn-mkt-kms-ami.yaml.template | 2 +- .../deployments/pro/aws/cfn-mkt-ov-ami.yaml.template | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openvidu-server/deployments/ce/aws/cfn-mkt-ov-ce-ami.yaml.template b/openvidu-server/deployments/ce/aws/cfn-mkt-ov-ce-ami.yaml.template index c1a951f9..7223023f 100644 --- a/openvidu-server/deployments/ce/aws/cfn-mkt-ov-ce-ami.yaml.template +++ b/openvidu-server/deployments/ce/aws/cfn-mkt-ov-ce-ami.yaml.template @@ -141,5 +141,5 @@ Resources: Type: AWS::CloudFormation::WaitCondition CreationPolicy: ResourceSignal: - Timeout: PT10M + Timeout: PT20M Count: 1 diff --git a/openvidu-server/deployments/pro/aws/cfn-mkt-kms-ami.yaml.template b/openvidu-server/deployments/pro/aws/cfn-mkt-kms-ami.yaml.template index 8cfb9169..d1ee758d 100644 --- a/openvidu-server/deployments/pro/aws/cfn-mkt-kms-ami.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-mkt-kms-ami.yaml.template @@ -142,5 +142,5 @@ Resources: Type: AWS::CloudFormation::WaitCondition CreationPolicy: ResourceSignal: - Timeout: PT10M + Timeout: PT20M Count: 1 diff --git a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template index af2d2af5..d27c1e1b 100644 --- a/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template +++ b/openvidu-server/deployments/pro/aws/cfn-mkt-ov-ami.yaml.template @@ -144,5 +144,5 @@ Resources: Type: AWS::CloudFormation::WaitCondition CreationPolicy: ResourceSignal: - Timeout: PT10M + Timeout: PT20M Count: 1 From bdf637229ddc603b26f33a3ad91406e4cee46af5 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Fri, 6 Nov 2020 16:46:08 +0100 Subject: [PATCH 250/435] docker-compose typo --- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 054f6535..12b6d75d 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -7,7 +7,7 @@ # Application based on OpenVidu should be specified in # docker-compose.override.yml file # -# This docker-compose file coordinates all services of OpenVidu CE Platform. +# This docker-compose file coordinates all services of OpenVidu CE Platform # # This file will be overridden when update OpenVidu Platform # diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index 33faf4a4..ca83607a 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -7,7 +7,7 @@ # Application based on OpenVidu should be specified in # docker-compose.override.yml file # -# This docker-compose file coordinates all services of OpenVidu CE Platform. +# This docker-compose file coordinates all services of OpenVidu Pro Platform # # This file will be overridden when update OpenVidu Platform # From 9e0c4aeeea23ff58b7790e53c6a015da53ae789a Mon Sep 17 00:00:00 2001 From: cruizba Date: Fri, 6 Nov 2020 17:42:00 +0100 Subject: [PATCH 251/435] Fix typo in commentary wich causes bad restarts --- .../deployments/pro/docker-compose/openvidu-server-pro/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 4490998a..4cfa7f38 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -150,7 +150,7 @@ OPENVIDU_PRO_CLUSTER_LOAD_STRATEGY=streams # For example 192.168.1.101 # OPENVIDU_PRO_PRIVATE_IP= -# Where to store recording files. Can be “local” (local storage) or “s3” (AWS bucket). +# Where to store recording files. Can be 'local' (local storage) or 's3' (AWS bucket). # You will need to define a OPENVIDU_PRO_AWS_S3_BUCKET if you use it. #OPENVIDU_PRO_RECORDING_STORAGE= From 2cdee29954df6b02ee39226240665b7122a42fe9 Mon Sep 17 00:00:00 2001 From: zvse Date: Mon, 9 Nov 2020 10:11:47 +0700 Subject: [PATCH 252/435] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95bc35ca..46a34a43 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Visit [openvidu.io](https://openvidu.io) ## Contributors This project exists thanks to all the people who contribute. - + ## Backers From 39be78b4e5cbeec70fe36be61f55e2a6fe0560f2 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 14:18:40 +0100 Subject: [PATCH 253/435] openvidu-deployment: Some minor fixes nginx and update versions docker-compose --- .../deployments/ce/docker-compose/docker-compose.override.yml | 2 +- .../deployments/ce/docker-compose/docker-compose.yml | 2 +- .../pro/docker-compose/media-node/install_media_node.sh | 4 ++-- .../openvidu-server-pro/docker-compose.override.yml | 2 +- .../pro/docker-compose/openvidu-server-pro/docker-compose.yml | 4 ++-- openvidu-server/docker/openvidu-proxy/Dockerfile | 4 +++- .../openvidu-proxy/{default.conf => default-certbot.conf} | 0 openvidu-server/docker/openvidu-proxy/entrypoint.sh | 4 +++- 8 files changed, 13 insertions(+), 9 deletions(-) rename openvidu-server/docker/openvidu-proxy/{default.conf => default-certbot.conf} (100%) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml index ec6a4795..156db956 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml @@ -13,7 +13,7 @@ services: # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.16.0-dev1 + image: openvidu/openvidu-call:2.16.0-beta1 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index 12b6d75d..a44b356a 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -90,7 +90,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: - image: openvidu/openvidu-proxy:4.0.0-dev5 + image: openvidu/openvidu-proxy:4.0.0-dev6 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index 5b7aa25e..d766159c 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -113,7 +113,7 @@ new_media_node_installation() { printf '\n 2. Start Media Node Controller' printf '\n $ ./media_node start' printf '\n' - printf '\n 3. This will run a service at port 3000 wich OpenVidu will use to deploy necessary containers.' + printf '\n 3. This will run a service at port 3000 which OpenVidu will use to deploy necessary containers.' printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' @@ -319,7 +319,7 @@ upgrade_media_node() { printf '\n 3. Start new version of Media Node' printf '\n $ ./media_node start' printf '\n' - printf '\n 4. This will run a service at port 3000 wich OpenVidu will use to deploy necessary containers.' + printf '\n 4. This will run a service at port 3000 which OpenVidu will use to deploy necessary containers.' printf '\n Add the private ip of this media node in "KMS_URIS=[]" in OpenVidu Pro machine' printf '\n in file located at "/opt/openvidu/.env" with this format:' printf '\n ...' diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml index ec6a4795..156db956 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml @@ -13,7 +13,7 @@ services: # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.16.0-dev1 + image: openvidu/openvidu-call:2.16.0-beta1 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index ca83607a..c2419af0 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server-pro:2.16.0-dev7 + image: openvidu/openvidu-server-pro:2.16.0-dev9 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] @@ -78,7 +78,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: - image: openvidu/openvidu-proxy:4.0.0-dev5 + image: openvidu/openvidu-proxy:4.0.0-dev6 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/docker/openvidu-proxy/Dockerfile b/openvidu-server/docker/openvidu-proxy/Dockerfile index 3eb033f3..7198f9aa 100644 --- a/openvidu-server/docker/openvidu-proxy/Dockerfile +++ b/openvidu-server/docker/openvidu-proxy/Dockerfile @@ -10,8 +10,10 @@ RUN apk update && \ perl pcre grep && \ rm -rf /var/cache/apk/* +# Copy certbot default config +COPY ./default-certbot.conf /default-nginx-certbot-conf/default-certbot.conf + # Default nginx conf -COPY ./default.conf /etc/nginx/conf.d/default.conf COPY ./default_nginx_conf /default_nginx_conf # Entrypoint and discover public ip scripts diff --git a/openvidu-server/docker/openvidu-proxy/default.conf b/openvidu-server/docker/openvidu-proxy/default-certbot.conf similarity index 100% rename from openvidu-server/docker/openvidu-proxy/default.conf rename to openvidu-server/docker/openvidu-proxy/default-certbot.conf diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 1b72f4e3..3c2fc897 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -102,7 +102,8 @@ fi echo -e "${DOMAIN_OR_PUBLIC_IP}\t${CERTIFICATE_TYPE}" > "${CERTIFICATES_CONF}" # Start with default certbot conf -sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/conf.d/default.conf +cp /default-nginx-certbot-conf/default-certbot.conf /etc/nginx/vhost.d/default-certbot.conf +sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/vhost.d/default-certbot.conf nginx -g "daemon on;" case ${CERTIFICATE_TYPE} in @@ -187,6 +188,7 @@ EOF # Load nginx conf files rm /etc/nginx/conf.d/* +rm /etc/nginx/vhost.d/default-certbot.conf cp /default_nginx_conf/default* /etc/nginx/conf.d # Replace config files From d61c6b89c7efcf5fe045afcd16dd075ef93c127c Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 15:20:04 +0100 Subject: [PATCH 254/435] Revert nginx --- openvidu-server/docker/openvidu-proxy/Dockerfile | 4 +--- openvidu-server/docker/openvidu-proxy/entrypoint.sh | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/openvidu-server/docker/openvidu-proxy/Dockerfile b/openvidu-server/docker/openvidu-proxy/Dockerfile index 7198f9aa..3eb033f3 100644 --- a/openvidu-server/docker/openvidu-proxy/Dockerfile +++ b/openvidu-server/docker/openvidu-proxy/Dockerfile @@ -10,10 +10,8 @@ RUN apk update && \ perl pcre grep && \ rm -rf /var/cache/apk/* -# Copy certbot default config -COPY ./default-certbot.conf /default-nginx-certbot-conf/default-certbot.conf - # Default nginx conf +COPY ./default.conf /etc/nginx/conf.d/default.conf COPY ./default_nginx_conf /default_nginx_conf # Entrypoint and discover public ip scripts diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 3c2fc897..3a4fbdb2 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -102,8 +102,7 @@ fi echo -e "${DOMAIN_OR_PUBLIC_IP}\t${CERTIFICATE_TYPE}" > "${CERTIFICATES_CONF}" # Start with default certbot conf -cp /default-nginx-certbot-conf/default-certbot.conf /etc/nginx/vhost.d/default-certbot.conf -sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/vhost.d/default-certbot.conf +sed -i "s/{http_port}/${PROXY_HTTP_PORT}/" /etc/nginx/conf.d/default.conf nginx -g "daemon on;" case ${CERTIFICATE_TYPE} in @@ -187,8 +186,7 @@ Welcome to OpenVidu Server EOF # Load nginx conf files -rm /etc/nginx/conf.d/* -rm /etc/nginx/vhost.d/default-certbot.conf +rm /etc/nginx/conf.d/default*.conf cp /default_nginx_conf/default* /etc/nginx/conf.d # Replace config files From 2113a255e039277abb3c4f64fce1f87b107dbffc Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 15:21:00 +0100 Subject: [PATCH 255/435] openvidu-deployment: Rename default.conf nginx --- .../docker/openvidu-proxy/{default-certbot.conf => default.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openvidu-server/docker/openvidu-proxy/{default-certbot.conf => default.conf} (100%) diff --git a/openvidu-server/docker/openvidu-proxy/default-certbot.conf b/openvidu-server/docker/openvidu-proxy/default.conf similarity index 100% rename from openvidu-server/docker/openvidu-proxy/default-certbot.conf rename to openvidu-server/docker/openvidu-proxy/default.conf From d499940495bb3503670b4b79a074d3e4b3325c22 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 15:33:06 +0100 Subject: [PATCH 256/435] openvidu-deployment: custom config nginx --- .../docker/openvidu-proxy/entrypoint.sh | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 3a4fbdb2..85f7e1ce 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -187,9 +187,25 @@ EOF # Load nginx conf files rm /etc/nginx/conf.d/default*.conf -cp /default_nginx_conf/default* /etc/nginx/conf.d + +# If custom config, don't generate configuration files +if [[ -f /etc/nginx/conf.d/custom-nginx.conf ]]; then + printf "\n" + printf "\n =======================================" + printf "\n = START OPENVIDU PROXY =" + printf "\n = WITH CUSTOM CONFIG =" + printf "\n =======================================" + printf "\n\n" + nginx -s reload + + # nginx logs + tail -f /var/log/nginx/*.log + exit 0 +fi # Replace config files +cp /default_nginx_conf/default* /etc/nginx/conf.d + sed -e '/{ssl_config}/{r default_nginx_conf/global/ssl_config.conf' -e 'd}' -i /etc/nginx/conf.d/* sed -e '/{proxy_config}/{r default_nginx_conf/global/proxy_config.conf' -e 'd}' -i /etc/nginx/conf.d/* sed -e '/{nginx_status}/{r default_nginx_conf/global/nginx_status.conf' -e 'd}' -i /etc/nginx/conf.d/* From 0c38d4d9b853039f3583fb2a6e62be6f0915971e Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 16:29:35 +0100 Subject: [PATCH 257/435] Custom volume to customize nginx --- openvidu-server/docker/openvidu-proxy/Dockerfile | 1 + openvidu-server/docker/openvidu-proxy/entrypoint.sh | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openvidu-server/docker/openvidu-proxy/Dockerfile b/openvidu-server/docker/openvidu-proxy/Dockerfile index 3eb033f3..9272c08d 100644 --- a/openvidu-server/docker/openvidu-proxy/Dockerfile +++ b/openvidu-server/docker/openvidu-proxy/Dockerfile @@ -25,6 +25,7 @@ COPY ./entrypoint.sh /usr/local/bin RUN mkdir -p /var/www/certbot && \ mkdir -p /etc/nginx/vhost.d/ && \ + mkdir -p /custom-nginx && \ chmod +x /usr/local/bin/entrypoint.sh && \ chmod +x /usr/local/bin/discover_my_public_ip.sh diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 85f7e1ce..9359e664 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -186,10 +186,11 @@ Welcome to OpenVidu Server EOF # Load nginx conf files -rm /etc/nginx/conf.d/default*.conf +rm /etc/nginx/conf.d/* # If custom config, don't generate configuration files -if [[ -f /etc/nginx/conf.d/custom-nginx.conf ]]; then +if [[ -f /custom-nginx/custom-nginx.conf ]]; then + cp /custom-nginx/custom-nginx.conf /etc/nginx/conf.d/custom-nginx.conf printf "\n" printf "\n =======================================" printf "\n = START OPENVIDU PROXY =" From 43c5c4b4a51d841bb30363fb31c3bfb824b62afe Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 18:04:41 +0100 Subject: [PATCH 258/435] openvidu-deployment: Print if nginx is using deprecated API --- openvidu-server/docker/openvidu-proxy/entrypoint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/openvidu-server/docker/openvidu-proxy/entrypoint.sh b/openvidu-server/docker/openvidu-proxy/entrypoint.sh index 9359e664..ebf5d8f1 100755 --- a/openvidu-server/docker/openvidu-proxy/entrypoint.sh +++ b/openvidu-server/docker/openvidu-proxy/entrypoint.sh @@ -57,6 +57,7 @@ printf "\n - Https Port: %s" "${PROXY_HTTPS_PORT}" printf "\n - Worker Connections: %s" "${WORKER_CONNECTIONS}" printf "\n - Allowed Access in Openvidu Dashboard: %s" "${ALLOWED_ACCESS_TO_DASHBOARD}" printf "\n - Allowed Access in Openvidu API: %s" "${ALLOWED_ACCESS_TO_RESTAPI}" +printf "\n - Support deprecated API: %s" "${SUPPORT_DEPRECATED_API}" printf "\n - Redirect www to non-www: %s" "${REDIRECT_WWW}" printf "\n" printf "\n Config Openvidu Application:" From da2973d28f6d57577f7f44d87c3a9b9199c79827 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 19:35:25 +0100 Subject: [PATCH 259/435] openvidu-deployment: Minor fixes. OV_CE_DEBUG_LEVEL works and move beats to rollback folder on update in openvidu pro server node --- openvidu-server/deployments/ce/docker-compose/.env | 7 +++++++ .../pro/docker-compose/openvidu-server-pro/.env | 7 +++++++ .../openvidu-server-pro/install_openvidu_pro.sh | 3 +++ openvidu-server/docker/openvidu-server-pro/entrypoint.sh | 4 ++++ openvidu-server/docker/openvidu-server/entrypoint.sh | 4 ++++ 5 files changed, 25 insertions(+) diff --git a/openvidu-server/deployments/ce/docker-compose/.env b/openvidu-server/deployments/ce/docker-compose/.env index cc5e3395..ecc25054 100644 --- a/openvidu-server/deployments/ce/docker-compose/.env +++ b/openvidu-server/deployments/ce/docker-compose/.env @@ -39,6 +39,13 @@ LETSENCRYPT_EMAIL=user@example.com # SDKs, REST clients and browsers will have to connect to this port # HTTPS_PORT=443 +# Old paths are considered now deprecated, but still supported by default. +# OpenVidu Server will log a WARN message every time a deprecated path is called, indicating +# the new path that should be used instead. You can set property SUPPORT_DEPRECATED_API=false +# to stop allowing the use of old paths. +# Default value is true +# SUPPORT_DEPRECATED_API=true + # If true request to with www will be redirected to non-www requests # Default value is false # REDIRECT_WWW=false diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env index 4cfa7f38..ccd97a47 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env @@ -42,6 +42,13 @@ LETSENCRYPT_EMAIL=user@example.com # SDKs, REST clients and browsers will have to connect to this port # HTTPS_PORT=443 +# Old paths are considered now deprecated, but still supported by default. +# OpenVidu Server will log a WARN message every time a deprecated path is called, indicating +# the new path that should be used instead. You can set property SUPPORT_DEPRECATED_API=false +# to stop allowing the use of old paths. +# Default value is true +# SUPPORT_DEPRECATED_API=true + # If true request to with www will be redirected to non-www requests # Default value is false # REDIRECT_WWW=false diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index 27268ba9..d4bdc722 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -259,6 +259,9 @@ upgrade_ov() { mv "${OPENVIDU_PREVIOUS_FOLDER}/cluster/aws" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'cluster/aws'" printf '\n - cluster/aws' + mv "${OPENVIDU_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats'" + printf '\n - beats' + cp "${OPENVIDU_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'" printf '\n - .env' diff --git a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh index 3f94b5ee..2c90656c 100755 --- a/openvidu-server/docker/openvidu-server-pro/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server-pro/entrypoint.sh @@ -31,6 +31,10 @@ elif [[ "${COTURN_IP}" == "auto-ipv6" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) fi +if [[ "${OV_CE_DEBUG_LEVEL}" == "DEBUG" ]]; then + export LOGGING_LEVEL_IO_OPENVIDU_SERVER=DEBUG +fi + if [ ! -z "${JAVA_OPTIONS}" ]; then printf "\n Using java options: %s" "${JAVA_OPTIONS}" fi diff --git a/openvidu-server/docker/openvidu-server/entrypoint.sh b/openvidu-server/docker/openvidu-server/entrypoint.sh index 5ba7d1c9..7a509808 100644 --- a/openvidu-server/docker/openvidu-server/entrypoint.sh +++ b/openvidu-server/docker/openvidu-server/entrypoint.sh @@ -14,6 +14,10 @@ elif [[ "${COTURN_IP}" == "auto-ipv6" ]]; then COTURN_IP=$(/usr/local/bin/discover_my_public_ip.sh --ipv6) fi +if [[ "${OV_CE_DEBUG_LEVEL}" == "DEBUG" ]]; then + export LOGGING_LEVEL_IO_OPENVIDU_SERVER=DEBUG +fi + if [ ! -z "${JAVA_OPTIONS}" ]; then printf "\n Using java options: %s" "${JAVA_OPTIONS}" fi From eccd4538fbbeb3e61f1df3f2b13d6254b720ecc3 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 20:39:39 +0100 Subject: [PATCH 260/435] openvidu-deployment: Pull images correctly on upgrade media-node --- .../docker-compose/media-node/install_media_node.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index d766159c..3812ffa5 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -228,9 +228,9 @@ upgrade_media_node() { # Pull images printf "\n => Pulling images...\n" - KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | sed 's/\(^.*KMS_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') - METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | sed 's/\(^.*METRICBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') - FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | sed 's/\(^.*FILEBEAT_IMAGE:-\)\(.*\)\(\}.*$\)/\2/') + KMS_IMAGE=$(cat docker-compose.yml | grep KMS_IMAGE | cut -d"=" -f2) + METRICBEAT_IMAGE=$(cat docker-compose.yml | grep METRICBEAT_IMAGE | cut -d"=" -f2) + FILEBEAT_IMAGE=$(cat docker-compose.yml | grep FILEBEAT_IMAGE | cut -d"=" -f2) docker pull $KMS_IMAGE || fatal "Error while pulling docker image: $KMS_IMAGE" docker pull $METRICBEAT_IMAGE || fatal "Error while pulling docker image: $METRICBEAT_IMAGE" docker pull $FILEBEAT_IMAGE || fatal "Error while pulling docker image: $FILEBEAT_IMAGE" @@ -261,8 +261,8 @@ upgrade_media_node() { mv "${MEDIA_NODE_PREVIOUS_FOLDER}/readme.md" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'readme.md'" printf '\n - readme.md' - mv "${MEDIA_NODE_PREVIOUS_FOLDER}/nginx_conf" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'nginx_conf'" - printf '\n - nginx_conf' + mv "${MEDIA_NODE_PREVIOUS_FOLDER}/beats" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous 'beats' folder" + printf '\n - beats' mv "${MEDIA_NODE_PREVIOUS_FOLDER}/.env" "${ROLL_BACK_FOLDER}" || fatal_error "Error while moving previous '.env'" printf '\n - .env' From 03adf7766277529bae47301907f0ace82542a7c2 Mon Sep 17 00:00:00 2001 From: cruizba Date: Mon, 9 Nov 2020 23:01:17 +0100 Subject: [PATCH 261/435] openvidu-deployment: Fix stop containers in Media Nodes --- .../pro/docker-compose/media-node/install_media_node.sh | 8 ++++---- .../deployments/pro/docker-compose/media-node/media_node | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh index 3812ffa5..1f0dc4bc 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh +++ b/openvidu-server/deployments/pro/docker-compose/media-node/install_media_node.sh @@ -6,9 +6,9 @@ OPENVIDU_UPGRADABLE_VERSION="2.15" BEATS_FOLDER=${MEDIA_NODE_FOLDER}/beats DOWNLOAD_URL=https://raw.githubusercontent.com/OpenVidu/openvidu/${MEDIA_NODE_VERSION} IMAGES=( - "kurento-media-server", - "docker.elastic.co/beats/filebeat", - "docker.elastic.co/beats/metricbeat", + "kurento-media-server" + "docker.elastic.co/beats/filebeat" + "docker.elastic.co/beats/metricbeat" "openvidu/media-node-controller" ) @@ -26,7 +26,7 @@ docker_command_by_container_image() { CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') for CONTAINER_ID in ${CONTAINERS[@]}; do if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then - docker "${COMMAND}" "${CONTAINER_ID}" + bash -c "docker ${COMMAND} ${CONTAINER_ID}" fi done fi diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/media_node b/openvidu-server/deployments/pro/docker-compose/media-node/media_node index 2a95e523..8b142871 100755 --- a/openvidu-server/deployments/pro/docker-compose/media-node/media_node +++ b/openvidu-server/deployments/pro/docker-compose/media-node/media_node @@ -2,9 +2,9 @@ # Deployed images in media-node IMAGES=( - "kurento-media-server", - "docker.elastic.co/beats/filebeat", - "docker.elastic.co/beats/metricbeat", + "kurento-media-server" + "docker.elastic.co/beats/filebeat" + "docker.elastic.co/beats/metricbeat" "openvidu/media-node-controller" ) @@ -15,7 +15,7 @@ docker_command_by_container_image() { CONTAINERS=$(docker ps -a | grep "${IMAGE_NAME}" | awk '{print $1}') for CONTAINER_ID in ${CONTAINERS[@]}; do if [[ ! -z "${CONTAINER_ID}" ]] && [[ ! -z "${COMMAND}" ]]; then - docker "${COMMAND}" "${CONTAINER_ID}" + bash -c "docker ${COMMAND} ${CONTAINER_ID}" fi done fi @@ -28,7 +28,6 @@ stop_containers() { docker_command_by_container_image "${IMAGE}" "rm -f" done } - kurento_logs() { if [[ "$1" == "-f" ]]; then tail -f /opt/openvidu/kurento-logs/*.log From da084e2b3117896c6b991a584d194fc893eda929 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 14:51:19 +0100 Subject: [PATCH 262/435] openvidu-browser: improve send videoData with interval --- openvidu-browser/src/OpenVidu/Publisher.ts | 6 +-- openvidu-browser/src/OpenVidu/Session.ts | 52 ++++++++++++++-------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/openvidu-browser/src/OpenVidu/Publisher.ts b/openvidu-browser/src/OpenVidu/Publisher.ts index b6fc847e..e4afac50 100644 --- a/openvidu-browser/src/OpenVidu/Publisher.ts +++ b/openvidu-browser/src/OpenVidu/Publisher.ts @@ -314,7 +314,7 @@ export class Publisher extends StreamManager { mediaStream.removeTrack(removedTrack); removedTrack.stop(); mediaStream.addTrack(track); - this.session.sendVideoData(this.stream.streamManager); + this.session.sendVideoData(this.stream.streamManager, 5, true, 5); } return new Promise((resolve, reject) => { @@ -613,8 +613,8 @@ export class Publisher extends StreamManager { .then(myConstraints => { if (!!myConstraints.videoTrack && !!myConstraints.audioTrack || - !!myConstraints.audioTrack && myConstraints.constraints?.video === false || - !!myConstraints.videoTrack && myConstraints.constraints?.audio === false) { + !!myConstraints.audioTrack && myConstraints.constraints?.video === false || + !!myConstraints.videoTrack && myConstraints.constraints?.audio === false) { // No need to call getUserMedia at all. MediaStreamTracks already provided successCallback(this.openvidu.addAlreadyProvidedTracks(myConstraints, new MediaStream())); // Return as we do not need to process further diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 95b9de7c..832f2e05 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -385,7 +385,7 @@ export class Session extends EventDispatcher { this.connection.addStream(publisher.stream); publisher.stream.publish() .then(() => { - this.sendVideoData(publisher, 5); + this.sendVideoData(publisher, 8, true, 5); resolve(); }) .catch(error => { @@ -399,7 +399,7 @@ export class Session extends EventDispatcher { publisher.reestablishStreamPlayingEvent(); publisher.stream.publish() .then(() => { - this.sendVideoData(publisher, 5); + this.sendVideoData(publisher, 8, true, 5); resolve(); }) .catch(error => { @@ -1162,30 +1162,46 @@ export class Session extends EventDispatcher { return joinParams; } - sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1) { + sendVideoData(streamManager: StreamManager, intervalSeconds: number = 1, doInterval: boolean = false, maxLoops: number = 1) { if ( platform.isChromeBrowser() || platform.isChromeMobileBrowser() || platform.isOperaBrowser() || platform.isOperaMobileBrowser() || platform.isElectron() || (platform.isSafariBrowser() && !platform.isIonicIos()) || platform.isAndroidBrowser() || platform.isSamsungBrowser() || platform.isIonicAndroid() || (platform.isIPhoneOrIPad() && platform.isIOSWithSafari()) ) { - setTimeout(async () => { - const statsMap = await streamManager.stream.getWebRtcPeer().pc.getStats(); - statsMap.forEach((stats) => { - if ("frameWidth" in stats) { - this.openvidu.sendRequest('videoData', { - height: stats.frameHeight, - width: stats.frameWidth, - videoActive: streamManager.stream.videoActive, - audioActive: streamManager.stream.audioActive - }, (error, response) => { - if (error) { - logger.error("Error sending 'videoData' event", error); - } - }); + const obtainAndSendVideo = async () => { + const statsMap = await streamManager.stream.getRTCPeerConnection().getStats(); + const arr: any[] = []; + statsMap.forEach(stats => { + if (("frameWidth" in stats) && ("frameHeight" in stats) && (arr.length === 0)) { + arr.push(stats); } }); - }, intervalSeconds * 1000); + if (arr.length > 0) { + this.openvidu.sendRequest('videoData', { + height: arr[0].frameHeight, + width: arr[0].frameWidth, + videoActive: streamManager.stream.videoActive != null ? streamManager.stream.videoActive : false, + audioActive: streamManager.stream.audioActive != null ? streamManager.stream.audioActive : false + }, (error, response) => { + if (error) { + logger.error("Error sending 'videoData' event", error); + } + }); + } + } + if (doInterval) { + let loops = 1; + let timer = setTimeout(async function myTimer() { + await obtainAndSendVideo(); + if (loops < maxLoops) { + loops++; + timer = setTimeout(myTimer, intervalSeconds * 1000); + } + }, intervalSeconds * 1000); + } else { + setTimeout(obtainAndSendVideo, intervalSeconds * 1000); + } } else if (platform.isFirefoxBrowser() || platform.isFirefoxMobileBrowser() || platform.isIonicIos()) { // Basic version for Firefox and Ionic iOS. They do not support stats this.openvidu.sendRequest('videoData', { From 3c1d4fd69f33a1c435ce2846b7053ae648663f8b Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 18:22:14 +0100 Subject: [PATCH 263/435] openvidu-browser: all dependencies updated --- openvidu-browser/package.json | 26 +++++++++---------- openvidu-browser/src/OpenVidu/Connection.ts | 6 ++--- openvidu-browser/src/OpenVidu/Filter.ts | 6 ++--- .../src/OpenVidu/LocalRecorder.ts | 6 ++--- openvidu-browser/src/OpenVidu/Publisher.ts | 6 ++--- openvidu-browser/src/OpenVidu/Session.ts | 12 ++++----- openvidu-browser/src/OpenVidu/Stream.ts | 20 +++++++------- .../src/OpenVidu/StreamManager.ts | 2 +- .../Events/SessionDisconnectedEvent.ts | 10 +++---- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/openvidu-browser/package.json b/openvidu-browser/package.json index a2df896b..a2da810e 100644 --- a/openvidu-browser/package.json +++ b/openvidu-browser/package.json @@ -1,31 +1,31 @@ { "author": "OpenVidu", "dependencies": { - "@types/node": "13.13.2", - "@types/platform": "1.3.2", + "@types/node": "14.14.7", + "@types/platform": "1.3.3", "freeice": "2.2.2", "hark": "1.2.3", - "platform": "1.3.5", - "uuid": "7.0.3", + "platform": "1.3.6", + "uuid": "8.3.1", "wolfy87-eventemitter": "5.2.9" }, "description": "OpenVidu Browser", "devDependencies": { - "browserify": "16.5.1", - "grunt": "1.1.0", + "browserify": "17.0.0", + "grunt": "1.3.0", "grunt-cli": "1.3.2", "grunt-contrib-copy": "1.0.0", - "grunt-contrib-sass": "1.0.0", - "grunt-contrib-uglify": "4.0.1", + "grunt-contrib-sass": "2.0.0", + "grunt-contrib-uglify": "5.0.0", "grunt-contrib-watch": "1.1.0", "grunt-postcss": "0.9.0", "grunt-string-replace": "1.3.1", "grunt-ts": "6.0.0-beta.22", - "terser": "4.6.11", - "tsify": "4.0.1", - "tslint": "6.1.1", - "typedoc": "0.17.4", - "typescript": "3.8.3" + "terser": "5.3.8", + "tsify": "5.0.2", + "tslint": "6.1.3", + "typedoc": "0.19.2", + "typescript": "4.0.5" }, "license": "Apache-2.0", "main": "lib/index.js", diff --git a/openvidu-browser/src/OpenVidu/Connection.ts b/openvidu-browser/src/OpenVidu/Connection.ts index 72ad4e32..fe9d1e32 100644 --- a/openvidu-browser/src/OpenVidu/Connection.ts +++ b/openvidu-browser/src/OpenVidu/Connection.ts @@ -71,7 +71,7 @@ export class Connection { /** * @hidden */ - stream: Stream; + stream?: Stream; /** * @hidden @@ -132,7 +132,7 @@ export class Connection { */ sendIceCandidate(candidate: RTCIceCandidate): void { - logger.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' + + logger.debug((!!this.stream!.outboundStreamOpts ? 'Local' : 'Remote') + 'candidate for' + this.connectionId, candidate); this.session.openvidu.sendRequest('onIceCandidate', { @@ -174,7 +174,7 @@ export class Connection { this.addStream(stream); }); - logger.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); + logger.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream!.inboundStreamOpts); } /** diff --git a/openvidu-browser/src/OpenVidu/Filter.ts b/openvidu-browser/src/OpenVidu/Filter.ts index 134c56c4..a7f0f760 100644 --- a/openvidu-browser/src/OpenVidu/Filter.ts +++ b/openvidu-browser/src/OpenVidu/Filter.ts @@ -119,9 +119,9 @@ export class Filter { } else { logger.info('Filter method successfully executed on Stream ' + this.stream.streamId); const oldValue = (Object).assign({}, this.stream.filter); - this.stream.filter.lastExecMethod = { method, params: JSON.parse(stringParams) }; - this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter, oldValue, 'execFilterMethod')]); - this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter, oldValue, 'execFilterMethod')]); + this.stream.filter!.lastExecMethod = { method, params: JSON.parse(stringParams) }; + this.stream.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.session, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]); + this.stream.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.stream.streamManager, this.stream, 'filter', this.stream.filter!, oldValue, 'execFilterMethod')]); resolve(); } } diff --git a/openvidu-browser/src/OpenVidu/LocalRecorder.ts b/openvidu-browser/src/OpenVidu/LocalRecorder.ts index d23085b1..fa18b95e 100644 --- a/openvidu-browser/src/OpenVidu/LocalRecorder.ts +++ b/openvidu-browser/src/OpenVidu/LocalRecorder.ts @@ -50,7 +50,7 @@ export class LocalRecorder { private connectionId: string; private mediaRecorder: any; private chunks: any[] = []; - private blob: Blob; + private blob?: Blob; private id: string; private videoPreviewSrc: string; private videoPreview: HTMLVideoElement; @@ -281,7 +281,7 @@ export class LocalRecorder { if (this.state !== LocalRecorderState.FINISHED) { throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); } else { - return this.blob; + return this.blob!; } } @@ -351,7 +351,7 @@ export class LocalRecorder { } const sendable = new FormData(); - sendable.append('file', this.blob, this.id + '.webm'); + sendable.append('file', this.blob!, this.id + '.webm'); http.onreadystatechange = () => { if (http.readyState === 4) { diff --git a/openvidu-browser/src/OpenVidu/Publisher.ts b/openvidu-browser/src/OpenVidu/Publisher.ts index e4afac50..26b45193 100644 --- a/openvidu-browser/src/OpenVidu/Publisher.ts +++ b/openvidu-browser/src/OpenVidu/Publisher.ts @@ -127,7 +127,7 @@ export class Publisher extends StreamManager { */ publishAudio(value: boolean): void { if (this.stream.audioActive !== value) { - const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); + const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream(); affectedMediaStream.getAudioTracks().forEach((track) => { track.enabled = value; }); @@ -175,7 +175,7 @@ export class Publisher extends StreamManager { */ publishVideo(value: boolean): void { if (this.stream.videoActive !== value) { - const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); + const affectedMediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream(); affectedMediaStream.getVideoTracks().forEach((track) => { track.enabled = value; }); @@ -304,7 +304,7 @@ export class Publisher extends StreamManager { replaceTrack(track: MediaStreamTrack): Promise { const replaceMediaStreamTrack = () => { - const mediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote : this.stream.getMediaStream(); + const mediaStream: MediaStream = this.stream.displayMyRemote() ? this.stream.localMediaStreamWhenSubscribedToRemote! : this.stream.getMediaStream(); let removedTrack: MediaStreamTrack; if (track.kind === 'video') { removedTrack = mediaStream.getVideoTracks()[0]; diff --git a/openvidu-browser/src/OpenVidu/Session.ts b/openvidu-browser/src/OpenVidu/Session.ts index 832f2e05..8b914619 100644 --- a/openvidu-browser/src/OpenVidu/Session.ts +++ b/openvidu-browser/src/OpenVidu/Session.ts @@ -802,12 +802,12 @@ export class Session extends EventDispatcher { .then(connection => { - const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream, msg.reason); + const streamEvent = new StreamEvent(true, this, 'streamDestroyed', connection.stream!, msg.reason); this.ee.emitEvent('streamDestroyed', [streamEvent]); streamEvent.callDefaultBehavior(); // Deleting the remote stream - const streamId: string = connection.stream.streamId; + const streamId: string = connection.stream!.streamId; delete this.remoteStreamsCreated[streamId]; if (Object.keys(this.remoteStreamsCreated).length === 0) { @@ -993,9 +993,9 @@ export class Session extends EventDispatcher { }; this.getConnection(msg.senderConnectionId, 'Connection not found for connectionId ' + msg.senderConnectionId + ' owning endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) .then(connection => { - const stream = connection.stream; + const stream: Stream = connection.stream!; stream.getWebRtcPeer().addIceCandidate(candidate).catch(error => { - logger.error('Error adding candidate for ' + stream.streamId + logger.error('Error adding candidate for ' + stream!.streamId + ' stream of endpoint ' + msg.endpointName + ': ' + error); }); }) @@ -1077,8 +1077,8 @@ export class Session extends EventDispatcher { this.getConnection(connectionId, 'No connection found for connectionId ' + connectionId) .then(connection => { logger.info('Filter event dispatched'); - const stream: Stream = connection.stream; - stream.filter.handlers[response.eventType](new FilterEvent(stream.filter, response.eventType, response.data)); + const stream: Stream = connection.stream!; + stream.filter!.handlers[response.eventType](new FilterEvent(stream.filter!, response.eventType, response.data)); }); } diff --git a/openvidu-browser/src/OpenVidu/Stream.ts b/openvidu-browser/src/OpenVidu/Stream.ts index 45702ba8..c7ae1765 100644 --- a/openvidu-browser/src/OpenVidu/Stream.ts +++ b/openvidu-browser/src/OpenVidu/Stream.ts @@ -139,10 +139,10 @@ export class Stream extends EventDispatcher { * [[Filter.execMethod]] and remove it with [[Stream.removeFilter]]. Be aware that the client calling this methods must have the * necessary permissions: the token owned by the client must have been initialized with the appropriated `allowedFilters` array. */ - filter: Filter; + filter?: Filter; protected webRtcPeer: WebRtcPeer; - protected mediaStream: MediaStream; + protected mediaStream?: MediaStream; private webRtcStats: WebRtcStats; private isSubscribeToRemote = false; @@ -206,7 +206,7 @@ export class Stream extends EventDispatcher { /** * @hidden */ - localMediaStreamWhenSubscribedToRemote: MediaStream; + localMediaStreamWhenSubscribedToRemote?: MediaStream; /** @@ -265,7 +265,7 @@ export class Stream extends EventDispatcher { } this.ee.on('mediastream-updated', () => { - this.streamManager.updateMediaStream(this.mediaStream); + this.streamManager.updateMediaStream(this.mediaStream!); logger.debug('Video srcObject [' + this.mediaStream + '] updated in stream [' + this.streamId + ']'); }); } @@ -326,7 +326,7 @@ export class Stream extends EventDispatcher { } } else { logger.info('Filter successfully applied on Stream ' + this.streamId); - const oldValue: Filter = this.filter; + const oldValue: Filter = this.filter!; this.filter = new Filter(type, options); this.filter.stream = this; this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]); @@ -359,10 +359,10 @@ export class Stream extends EventDispatcher { } } else { logger.info('Filter successfully removed from Stream ' + this.streamId); - const oldValue = this.filter; + const oldValue = this.filter!; delete this.filter; - this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter, oldValue, 'applyFilter')]); - this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.streamManager, this, 'filter', this.filter, oldValue, 'applyFilter')]); + this.session.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.session, this, 'filter', this.filter!, oldValue, 'applyFilter')]); + this.streamManager.emitEvent('streamPropertyChanged', [new StreamPropertyChangedEvent(this.streamManager, this, 'filter', this.filter!, oldValue, 'applyFilter')]); resolve(); } } @@ -385,7 +385,7 @@ export class Stream extends EventDispatcher { * @returns Native MediaStream Web API object */ getMediaStream(): MediaStream { - return this.mediaStream; + return this.mediaStream!; } /* Hidden methods */ @@ -1005,7 +1005,7 @@ export class Stream extends EventDispatcher { } private initHarkEvents(): void { - if (!!this.mediaStream.getAudioTracks()[0]) { + if (!!this.mediaStream!.getAudioTracks()[0]) { // Hark events can only be set if audio track is available if (this.streamManager.remote) { // publisherStartSpeaking/publisherStopSpeaking is only defined for remote streams diff --git a/openvidu-browser/src/OpenVidu/StreamManager.ts b/openvidu-browser/src/OpenVidu/StreamManager.ts index ae4dbc26..1318b07f 100644 --- a/openvidu-browser/src/OpenVidu/StreamManager.ts +++ b/openvidu-browser/src/OpenVidu/StreamManager.ts @@ -87,7 +87,7 @@ export class StreamManager extends EventDispatcher { /** * @hidden */ - firstVideoElement: StreamManagerVideo; + firstVideoElement?: StreamManagerVideo; /** * @hidden */ diff --git a/openvidu-browser/src/OpenViduInternal/Events/SessionDisconnectedEvent.ts b/openvidu-browser/src/OpenViduInternal/Events/SessionDisconnectedEvent.ts index 050c694e..c7eff22d 100644 --- a/openvidu-browser/src/OpenViduInternal/Events/SessionDisconnectedEvent.ts +++ b/openvidu-browser/src/OpenViduInternal/Events/SessionDisconnectedEvent.ts @@ -62,12 +62,12 @@ export class SessionDisconnectedEvent extends Event { // Dispose and delete all remote Connections for (const connectionId in session.remoteConnections) { if (!!session.remoteConnections[connectionId].stream) { - session.remoteConnections[connectionId].stream.disposeWebRtcPeer(); - session.remoteConnections[connectionId].stream.disposeMediaStream(); - if (session.remoteConnections[connectionId].stream.streamManager) { - session.remoteConnections[connectionId].stream.streamManager.removeAllVideos(); + session.remoteConnections[connectionId].stream!.disposeWebRtcPeer(); + session.remoteConnections[connectionId].stream!.disposeMediaStream(); + if (session.remoteConnections[connectionId].stream!.streamManager) { + session.remoteConnections[connectionId].stream!.streamManager.removeAllVideos(); } - delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream.streamId]; + delete session.remoteStreamsCreated[session.remoteConnections[connectionId].stream!.streamId]; session.remoteConnections[connectionId].dispose(); } delete session.remoteConnections[connectionId]; From 44317a58ae4aeca0c7cf8d607ca253481db230ed Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 18:52:21 +0100 Subject: [PATCH 264/435] openvidu-node-client: all dependencies updated --- openvidu-node-client/package-lock.json | 829 +++++++++---------------- openvidu-node-client/package.json | 20 +- 2 files changed, 299 insertions(+), 550 deletions(-) diff --git a/openvidu-node-client/package-lock.json b/openvidu-node-client/package-lock.json index 82fbaa40..9fa1c9f8 100644 --- a/openvidu-node-client/package-lock.json +++ b/openvidu-node-client/package-lock.json @@ -5,35 +5,35 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.10.1" + "@babel/highlight": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.1", + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@types/node": { - "version": "14.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", - "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "version": "14.14.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", + "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==", "dev": true }, "abbrev": { @@ -125,12 +125,6 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -161,6 +155,12 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -168,11 +168,11 @@ "dev": true }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", + "integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", "requires": { - "follow-redirects": "1.5.10" + "follow-redirects": "^1.10.0" } }, "balanced-match": { @@ -309,12 +309,12 @@ } }, "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.2.tgz", + "integrity": "sha512-XeXCUm+F7uY7fIzq4pKy+BLbZk4SgYS5xwlZOFYD3UEcAD+PwOoTaFr/SaXvhR1yRa8SKyPSZ7LNX4N65w7h8A==", "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, "buffer-from": { @@ -352,22 +352,6 @@ "unset-value": "^1.0.0" } }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -433,12 +417,6 @@ } } }, - "coffeescript": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", - "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", - "dev": true - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -507,12 +485,16 @@ "dev": true }, "cross-spawn": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.9.tgz", - "integrity": "sha1-vWf5bAfvtjA7f+lMHpefiEeOCjk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^2.5.0" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "csproj2ts": { @@ -535,48 +517,27 @@ } } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "dargs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", - "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.1.0.tgz", + "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==", + "dev": true }, "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, "requires": { "ms": "2.0.0" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -652,9 +613,9 @@ "dev": true }, "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, "error": { @@ -666,15 +627,6 @@ "string-template": "~0.2.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es6-promise": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", @@ -905,16 +857,6 @@ } } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, "findup-sync": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", @@ -959,12 +901,9 @@ "dev": true }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" }, "for-in": { "version": "1.0.2", @@ -991,14 +930,15 @@ } }, "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", "dev": true, "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" } }, "fs.realpath": { @@ -1027,12 +967,6 @@ "globule": "^1.0.0" } }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -1046,15 +980,15 @@ "dev": true }, "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -1127,48 +1061,26 @@ "dev": true }, "grunt": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.1.0.tgz", - "integrity": "sha512-+NGod0grmviZ7Nzdi9am7vuRS/h76PcWDsV635mEXF0PEQMUV6Kb+OjTdsVxbi0PZmfQOjCMKb3w8CVZcqsn1g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.3.0.tgz", + "integrity": "sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA==", "dev": true, "requires": { - "coffeescript": "~1.10.0", - "dateformat": "~1.0.12", + "dateformat": "~3.0.3", "eventemitter2": "~0.4.13", - "exit": "~0.1.1", + "exit": "~0.1.2", "findup-sync": "~0.3.0", - "glob": "~7.0.0", - "grunt-cli": "~1.2.0", + "glob": "~7.1.6", + "grunt-cli": "~1.3.2", "grunt-known-options": "~1.1.0", - "grunt-legacy-log": "~2.0.0", - "grunt-legacy-util": "~1.1.1", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.0", "iconv-lite": "~0.4.13", - "js-yaml": "~3.13.1", - "minimatch": "~3.0.2", - "mkdirp": "~1.0.3", + "js-yaml": "~3.14.0", + "minimatch": "~3.0.4", + "mkdirp": "~1.0.4", "nopt": "~3.0.6", - "path-is-absolute": "~1.0.0", - "rimraf": "~2.6.2" - }, - "dependencies": { - "grunt-cli": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", - "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", - "dev": true, - "requires": { - "findup-sync": "~0.3.0", - "grunt-known-options": "~1.1.0", - "nopt": "~3.0.6", - "resolve": "~1.1.0" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } + "rimraf": "~3.0.2" } }, "grunt-cli": { @@ -1234,55 +1146,33 @@ } }, "grunt-contrib-sass": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-sass/-/grunt-contrib-sass-1.0.0.tgz", - "integrity": "sha1-gGg4JRy8DhqU1k1RXN00z2dNcBs=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-sass/-/grunt-contrib-sass-2.0.0.tgz", + "integrity": "sha512-RxZ3dlZZTX4YBPu2zMu84NPYgJ2AYAlIdEqlBaixNVyLNbgvJBGUr5Gi0ec6IiOQbt/I/z7uZVN9HsRxgznIRw==", "dev": true, "requires": { - "async": "^0.9.0", - "chalk": "^1.0.0", - "cross-spawn": "^0.2.3", - "dargs": "^4.0.0", - "which": "^1.0.5" + "async": "^2.6.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "dargs": "^6.0.0", + "which": "^1.3.1" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "lodash": "^4.17.14" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, "grunt-contrib-uglify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz", - "integrity": "sha512-dwf8/+4uW1+7pH72WButOEnzErPGmtUvc8p08B0eQS/6ON0WdeQu0+WFeafaPTbbY1GqtS25lsHWaDeiTQNWPg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-5.0.0.tgz", + "integrity": "sha512-rIFFPJMWKnh6oxDe2b810Ysg5SKoiI0u/FvuvAVpvJ7VHILkKtGqA4jgJ1JWruWQ+1m5FtB1lVSK81YyzIgDUw==", "dev": true, "requires": { "chalk": "^2.4.1", @@ -1321,40 +1211,113 @@ "dev": true }, "grunt-legacy-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", - "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", + "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", "dev": true, "requires": { "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.0.0", + "grunt-legacy-log-utils": "~2.1.0", "hooker": "~0.2.3", - "lodash": "~4.17.5" + "lodash": "~4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "grunt-legacy-log-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", - "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", + "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", "dev": true, "requires": { - "chalk": "~2.4.1", - "lodash": "~4.17.10" + "chalk": "~4.1.0", + "lodash": "~4.17.19" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "grunt-legacy-util": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", - "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.0.tgz", + "integrity": "sha512-ZEmYFB44bblwPE2oz3q3ygfF6hseQja9tx8I3UZIwbUik32FMWewA+d1qSFicMFB+8dNXDkh35HcDCWlpRsGlA==", "dev": true, "requires": { "async": "~1.5.2", "exit": "~0.1.1", "getobject": "~0.1.0", "hooker": "~0.2.3", - "lodash": "~4.17.10", - "underscore.string": "~3.3.4", + "lodash": "~4.17.20", + "underscore.string": "~3.3.5", "which": "~1.3.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "grunt-postcss": { @@ -1519,9 +1482,9 @@ } }, "highlight.js": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.0.3.tgz", - "integrity": "sha512-9FG7SSzv9yOY5CGGxfI6NDm7xLYtMOjKtPBxw7Zff3t5UcRcUNTGEeS8lNjhceL34KeetLMoGMFTGoaa83HwyQ==", + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.2.tgz", + "integrity": "sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw==", "dev": true }, "homedir-polyfill": { @@ -1539,12 +1502,6 @@ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", "dev": true }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, "http-parser-js": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", @@ -1561,18 +1518,9 @@ } }, "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "inflight": { "version": "1.0.6", @@ -1632,12 +1580,6 @@ } } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -1803,9 +1745,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -1819,12 +1761,21 @@ "dev": true }, "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } } }, "kind-of": { @@ -1869,45 +1820,16 @@ "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", "dev": true }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, "lunr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", - "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, "make-error": { @@ -1931,12 +1853,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -1947,9 +1863,9 @@ } }, "marked": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz", - "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.3.tgz", + "integrity": "sha512-RQuL2i6I6Gn+9n81IDNGbL0VHnta4a+8ZhqvryXEniTb/hQNtf3i26hi1XWUhzb9BgVyWHKR3UO8MaHtKoYibw==", "dev": true }, "maxmin": { @@ -1991,24 +1907,6 @@ } } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -2075,7 +1973,8 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "nan": { "version": "2.14.1", @@ -2110,9 +2009,15 @@ "dev": true }, "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "nopt": { @@ -2124,18 +2029,6 @@ "abbrev": "1" } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2267,15 +2160,6 @@ "path-root": "^0.1.1" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -2294,21 +2178,18 @@ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2330,38 +2211,6 @@ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -2424,27 +2273,6 @@ "string_decoder": "0.10" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -2497,16 +2325,6 @@ "resolve": "^1.1.6" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -2576,28 +2394,12 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "safe-buffer": { @@ -2662,6 +2464,21 @@ } } }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, "shelljs": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", @@ -2673,12 +2490,6 @@ "rechoir": "^0.6.2" } }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -2838,38 +2649,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -2936,15 +2715,6 @@ "is-utf8": "^0.2.0" } }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3010,16 +2780,10 @@ "repeat-string": "^1.6.1" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, "ts-node": { - "version": "8.10.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", - "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", "dev": true, "requires": { "arg": "^4.1.0", @@ -3038,15 +2802,15 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, "tslint": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.1.tgz", - "integrity": "sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", + "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -3060,7 +2824,7 @@ "mkdirp": "^0.5.3", "resolve": "^1.3.2", "semver": "^5.3.0", - "tslib": "^1.10.0", + "tslib": "^1.13.0", "tsutils": "^2.29.0" }, "dependencies": { @@ -3070,20 +2834,6 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -3105,46 +2855,55 @@ } }, "typedoc": { - "version": "0.17.7", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.7.tgz", - "integrity": "sha512-PEnzjwQAGjb0O8a6VDE0lxyLAadqNujN5LltsTUhZETolRMiIJv6Ox+Toa8h0XhKHqAOh8MOmB0eBVcWz6nuAw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.19.2.tgz", + "integrity": "sha512-oDEg1BLEzi1qvgdQXc658EYgJ5qJLVSeZ0hQ57Eq4JXy6Vj2VX4RVo18qYxRWz75ifAaYuYNBUCnbhjd37TfOg==", "dev": true, "requires": { - "fs-extra": "^8.1.0", + "fs-extra": "^9.0.1", "handlebars": "^4.7.6", - "highlight.js": "^10.0.0", - "lodash": "^4.17.15", - "lunr": "^2.3.8", - "marked": "1.0.0", + "highlight.js": "^10.2.0", + "lodash": "^4.17.20", + "lunr": "^2.3.9", + "marked": "^1.1.1", "minimatch": "^3.0.0", "progress": "^2.0.3", + "semver": "^7.3.2", "shelljs": "^0.8.4", - "typedoc-default-themes": "^0.10.1" + "typedoc-default-themes": "^0.11.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } } }, "typedoc-default-themes": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.1.tgz", - "integrity": "sha512-SuqAQI0CkwhqSJ2kaVTgl37cWs733uy9UGUqwtcds8pkFK8oRF4rZmCq+FXTGIb9hIUOu40rf5Kojg0Ha6akeg==", - "dev": true, - "requires": { - "lunr": "^2.3.8" - } + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.11.4.tgz", + "integrity": "sha512-Y4Lf+qIb9NTydrexlazAM46SSLrmrQRqWiD52593g53SsmUFioAsMWt8m834J6qsp+7wHRjxCXSZeiiW5cMUdw==", + "dev": true }, "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", + "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", "dev": true }, "uglify-js": { - "version": "3.9.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz", - "integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==", - "dev": true, - "requires": { - "commander": "~2.20.3" - } + "version": "3.11.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.5.tgz", + "integrity": "sha512-btvv/baMqe7HxP7zJSF7Uc16h1mSfuuSplT0/qdjxseesDU+yYzH33eHBH+eMdeRXwujXspaCTooWHQVVBh09w==", + "dev": true }, "unc-path-regex": { "version": "0.1.2", @@ -3175,9 +2934,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", "dev": true }, "unset-value": { @@ -3259,16 +3018,6 @@ "homedir-polyfill": "^1.0.1" } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", diff --git a/openvidu-node-client/package.json b/openvidu-node-client/package.json index 9958fe5a..f3302c39 100644 --- a/openvidu-node-client/package.json +++ b/openvidu-node-client/package.json @@ -1,25 +1,25 @@ { "author": "OpenVidu", "dependencies": { - "axios": "0.19.2", - "buffer": "5.6.0" + "axios": "0.21.0", + "buffer": "6.0.2" }, "description": "OpenVidu Node Client", "devDependencies": { - "@types/node": "14.0.13", - "grunt": "1.1.0", + "@types/node": "14.14.7", + "grunt": "1.3.0", "grunt-cli": "1.3.2", "grunt-contrib-copy": "1.0.0", - "grunt-contrib-sass": "1.0.0", - "grunt-contrib-uglify": "4.0.1", + "grunt-contrib-sass": "2.0.0", + "grunt-contrib-uglify": "5.0.0", "grunt-contrib-watch": "1.1.0", "grunt-postcss": "0.9.0", "grunt-string-replace": "1.3.1", "grunt-ts": "6.0.0-beta.22", - "ts-node": "8.10.2", - "tslint": "6.1.1", - "typedoc": "0.17.7", - "typescript": "3.8.3" + "ts-node": "9.0.0", + "tslint": "6.1.3", + "typedoc": "0.19.2", + "typescript": "4.0.5" }, "license": "Apache-2.0", "main": "lib/index.js", From 5e85ebd9d14ca34bdde921ecdea6241660ef9412 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 19:04:17 +0100 Subject: [PATCH 265/435] openvidu-parent: updated openvidu-java-client dependencies --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9bf1c69d..a599d8af 100644 --- a/pom.xml +++ b/pom.xml @@ -44,14 +44,14 @@ 6.14.0 2.2.4.RELEASE - 4.12 + 4.13.1 5.6.0 1.6.0 3.141.59 2.23.4 2.0.5 2.2 - 4.5.11 + 4.5.13 3.1.0 3.10 3.1.5 @@ -72,7 +72,7 @@ 1.6 1.6.8 1.6.0 - 3.1.1 + 3.2.0 1.8 1.8 From d1dd6a27cbe4628cfea351d2817cb6e3cdf50f80 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 19:29:45 +0100 Subject: [PATCH 266/435] openvidu-recording image to 2.16.0 --- openvidu-server/docker/openvidu-recording/create_image.sh | 2 ++ openvidu-server/src/main/resources/application.properties | 2 +- openvidu-server/src/test/resources/integration-test.properties | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openvidu-server/docker/openvidu-recording/create_image.sh b/openvidu-server/docker/openvidu-recording/create_image.sh index b85144a8..46f1c62a 100755 --- a/openvidu-server/docker/openvidu-recording/create_image.sh +++ b/openvidu-server/docker/openvidu-recording/create_image.sh @@ -1,4 +1,6 @@ #!/bin/bash -x + +# eg: $ ./create_image.sh ubuntu-20-04 86.0.4240.193-1 2.16.0 OPENVIDU_RECORDING_UBUNTU_VERSION=$1 OPENVIDU_RECORDING_CHROME_VERSION=$2 # https://www.ubuntuupdates.org/package_logs?noppa=&page=1&type=ppas&vals=8# OPENVIDU_RECORDING_DOCKER_TAG=$3 diff --git a/openvidu-server/src/main/resources/application.properties b/openvidu-server/src/main/resources/application.properties index d82ef7ee..45a69b5c 100644 --- a/openvidu-server/src/main/resources/application.properties +++ b/openvidu-server/src/main/resources/application.properties @@ -28,7 +28,7 @@ OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined" OPENVIDU_RECORDING=false OPENVIDU_RECORDING_DEBUG=false -OPENVIDU_RECORDING_VERSION=2.15.0 +OPENVIDU_RECORDING_VERSION=2.16.0 OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings OPENVIDU_RECORDING_PUBLIC_ACCESS=false OPENVIDU_RECORDING_NOTIFICATION=publisher_moderator diff --git a/openvidu-server/src/test/resources/integration-test.properties b/openvidu-server/src/test/resources/integration-test.properties index 5846edd0..5747263f 100644 --- a/openvidu-server/src/test/resources/integration-test.properties +++ b/openvidu-server/src/test/resources/integration-test.properties @@ -24,7 +24,7 @@ OPENVIDU_WEBHOOK_HEADERS=[] OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined","participantLeft","webrtcConnectionCreated","webrtcConnectionDestroyed","recordingStatusChanged","filterEventDispatched","mediaNodeStatusChanged"] OPENVIDU_RECORDING=false -OPENVIDU_RECORDING_VERSION=2.9.0 +OPENVIDU_RECORDING_VERSION=2.16.0 OPENVIDU_RECORDING_PATH=/opt/openvidu/recordings OPENVIDU_RECORDING_PUBLIC_ACCESS=false OPENVIDU_RECORDING_NOTIFICATION=publisher_moderator From d4eac2c895faf77076686f592a33b2aa1ef99d09 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 20:12:34 +0100 Subject: [PATCH 267/435] Jenkinsfile: fix root permissions --- openvidu-test-e2e/jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 43e499cb..a07f47fe 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -112,7 +112,7 @@ node('container') { '''.stripIndent()) } stage ('Environment Launch') { - sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' + sh 'sudo openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' From 339a89468225cabced87c854aedee8c1e04aa1ee Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 20:51:33 +0100 Subject: [PATCH 268/435] Jenkinsfile updated with try-catchs --- openvidu-test-e2e/jenkins/Jenkinsfile | 252 +++++++++++++++----------- 1 file changed, 146 insertions(+), 106 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index a07f47fe..77ffb17c 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -11,121 +11,161 @@ node('container') { def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() mycontainer.inside('--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged') { - stage('Preparation') { - sh 'rm -rf ~/.m2 || true' - sh 'rm -rf openvidu || true' - sh 'rm -rf kurento-java || true' - sh 'git clone https://github.com/OpenVidu/openvidu.git' - sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' - sh(script: '''#!/bin/bash - if $KURENTO_JAVA_SNAPSHOT ; then - git clone https://github.com/Kurento/kurento-java.git - cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION - fi - '''.stripIndent()) - sh(script: '''#!/bin/bash - if $KURENTO_MEDIA_SERVER_DEV ; then - echo "Upgrading KMS to dev version" - sudo apt-get update && sudo apt-get install -y aptitude - sudo aptitude remove -y kurento-media-server - DISTRO=`lsb_release --codename | cut -f2` - sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list - sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server - fi - '''.stripIndent()) + try { + stage('Preparation') { + sh 'rm -rf ~/.m2 || true' + sh 'rm -rf openvidu || true' + sh 'rm -rf kurento-java || true' + sh 'git clone https://github.com/OpenVidu/openvidu.git' + sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' + sh(script: '''#!/bin/bash + if $KURENTO_JAVA_SNAPSHOT ; then + git clone https://github.com/Kurento/kurento-java.git + cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION + fi + '''.stripIndent()) + sh(script: '''#!/bin/bash + if $KURENTO_MEDIA_SERVER_DEV ; then + echo "Upgrading KMS to dev version" + sudo apt-get update && sudo apt-get install -y aptitude + sudo aptitude remove -y kurento-media-server + DISTRO=`lsb_release --codename | cut -f2` + sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list + sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server + fi + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Browser build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_BROWSER_COMMIT - fi - cd openvidu-browser - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-browser-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) + try { + stage('OpenVidu Browser build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_BROWSER_COMMIT + fi + cd openvidu-browser + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-browser-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Node Client build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT - fi - cd openvidu-node-client - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-node-client-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) + try { + stage('OpenVidu Node Client build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT + fi + cd openvidu-node-client + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-node-client-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu TestApp build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_TESTAPP_COMMIT - fi - cd openvidu-testapp - npm install --unsafe-perm - npm install /opt/openvidu/openvidu-browser-*.tgz - npm install /opt/openvidu/openvidu-node-client-*.tgz - export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) + try { + stage('OpenVidu TestApp build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_TESTAPP_COMMIT + fi + cd openvidu-testapp + npm install --unsafe-perm + npm install /opt/openvidu/openvidu-browser-*.tgz + npm install /opt/openvidu/openvidu-node-client-*.tgz + export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Java Client build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT - fi - cd openvidu-java-client - mvn --batch-mode versions:set -DnewVersion=TEST - mvn clean compile package - mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) + try { + stage('OpenVidu Java Client build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT + fi + cd openvidu-java-client + mvn --batch-mode versions:set -DnewVersion=TEST + mvn clean compile package + mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu parent build') { - sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' - sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' + try { + stage('OpenVidu parent build') { + sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' + sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Server unit tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' + try { + stage('OpenVidu Server unit tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Server integration tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' + try { + stage('OpenVidu Server integration tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage('OpenVidu Server build') { - sh(script: '''#!/bin/bash - cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod - cd ../.. - mvn --batch-mode package - cp target/openvidu-server*.jar /opt/openvidu - '''.stripIndent()) + try { + stage('OpenVidu Server build') { + sh(script: '''#!/bin/bash + cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod + cd ../.. + mvn --batch-mode package + cp target/openvidu-server*.jar /opt/openvidu + '''.stripIndent()) + } + } catch (error) { + currentBuild.result = 'FAILURE' } - stage ('Environment Launch') { - sh 'sudo openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' - sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' - sh '/usr/bin/kurento-media-server &> /kms.log &' - sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' - sh(script: '''#!/bin/bash - if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then - echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - else - echo "Using default openvidu-recording tag" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - fi - '''.stripIndent()) - sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' + try { + stage ('Environment Launch') { + sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' + sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' + sh '/usr/bin/kurento-media-server &> /kms.log &' + sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' + sh(script: '''#!/bin/bash + if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then + echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + else + echo "Using default openvidu-recording tag" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + fi + '''.stripIndent()) + sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' + } + } catch (error) { + currentBuild.result = 'FAILURE' } stage ('OpenVidu E2E tests') { try { From 67ea4f0491aa7aadf28710a364d45f0fd1b75c5e Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 21:13:38 +0100 Subject: [PATCH 269/435] openvidu-node-client: rollback to typescript 3.8.3 --- openvidu-node-client/package-lock.json | 538 ++++++++++++++++++------- openvidu-node-client/package.json | 2 +- 2 files changed, 387 insertions(+), 153 deletions(-) diff --git a/openvidu-node-client/package-lock.json b/openvidu-node-client/package-lock.json index 9fa1c9f8..156a3e01 100644 --- a/openvidu-node-client/package-lock.json +++ b/openvidu-node-client/package-lock.json @@ -28,6 +28,58 @@ "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@types/node": { @@ -49,12 +101,12 @@ "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "anymatch": { @@ -353,14 +405,13 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "chokidar": { @@ -428,18 +479,18 @@ } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "colors": { @@ -530,9 +581,9 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -672,15 +723,6 @@ "to-regex": "^3.0.1" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -958,6 +1000,12 @@ "nan": "^2.12.1" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", @@ -1036,22 +1084,6 @@ "glob": "~7.1.1", "lodash": "~4.17.10", "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "graceful-fs": { @@ -1158,6 +1190,15 @@ "which": "^1.3.1" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -1166,6 +1207,47 @@ "requires": { "lodash": "^4.17.14" } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -1179,6 +1261,58 @@ "maxmin": "^2.1.0", "uglify-js": "^3.5.0", "uri-path": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "grunt-contrib-watch": { @@ -1220,14 +1354,6 @@ "grunt-legacy-log-utils": "~2.1.0", "hooker": "~0.2.3", "lodash": "~4.17.19" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - } } }, "grunt-legacy-log-utils": { @@ -1238,63 +1364,6 @@ "requires": { "chalk": "~4.1.0", "lodash": "~4.17.19" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "grunt-legacy-util": { @@ -1310,14 +1379,6 @@ "lodash": "~4.17.20", "underscore.string": "~3.3.5", "which": "~1.3.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - } } }, "grunt-postcss": { @@ -1329,6 +1390,58 @@ "chalk": "^2.1.0", "diff": "^3.0.0", "postcss": "^6.0.11" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "grunt-string-replace": { @@ -1434,6 +1547,15 @@ } } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -1444,9 +1566,9 @@ } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "has-value": { @@ -1595,6 +1717,15 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-core-module": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz", + "integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -1821,9 +1952,9 @@ "dev": true }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, "lunr": { @@ -1977,9 +2108,9 @@ "dev": true }, "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", "dev": true, "optional": true }, @@ -2228,11 +2359,61 @@ "supports-color": "^5.4.0" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -2363,11 +2544,12 @@ } }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", "dev": true, "requires": { + "is-core-module": "^2.0.0", "path-parse": "^1.0.6" } }, @@ -2506,15 +2688,6 @@ "use": "^3.1.0" }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -2716,12 +2889,12 @@ } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "tiny-lr": { @@ -2736,6 +2909,23 @@ "livereload-js": "^2.3.0", "object-assign": "^4.1.0", "qs": "^6.4.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, "to-object-path": { @@ -2828,12 +3018,53 @@ "tsutils": "^2.29.0" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", @@ -2842,6 +3073,15 @@ "requires": { "minimist": "^1.2.5" } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -2873,12 +3113,6 @@ "typedoc-default-themes": "^0.11.4" }, "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", @@ -2894,9 +3128,9 @@ "dev": true }, "typescript": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz", - "integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, "uglify-js": { diff --git a/openvidu-node-client/package.json b/openvidu-node-client/package.json index f3302c39..aa346f8c 100644 --- a/openvidu-node-client/package.json +++ b/openvidu-node-client/package.json @@ -19,7 +19,7 @@ "ts-node": "9.0.0", "tslint": "6.1.3", "typedoc": "0.19.2", - "typescript": "4.0.5" + "typescript": "3.8.3" }, "license": "Apache-2.0", "main": "lib/index.js", From b7f492feadcc4c88a7816cf27d08b9947745080c Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 21:25:25 +0100 Subject: [PATCH 270/435] Jenkinsfile: return if error in script --- openvidu-node-client/package.json | 2 +- openvidu-test-e2e/jenkins/Jenkinsfile | 264 ++++++++++++-------------- 2 files changed, 119 insertions(+), 147 deletions(-) diff --git a/openvidu-node-client/package.json b/openvidu-node-client/package.json index aa346f8c..502e76b2 100644 --- a/openvidu-node-client/package.json +++ b/openvidu-node-client/package.json @@ -19,7 +19,7 @@ "ts-node": "9.0.0", "tslint": "6.1.3", "typedoc": "0.19.2", - "typescript": "3.8.3" + "typescript": "3.9.2" }, "license": "Apache-2.0", "main": "lib/index.js", diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 77ffb17c..04184a16 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -11,162 +11,134 @@ node('container') { def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') mycontainer.pull() mycontainer.inside('--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged') { - try { - stage('Preparation') { - sh 'rm -rf ~/.m2 || true' - sh 'rm -rf openvidu || true' - sh 'rm -rf kurento-java || true' - sh 'git clone https://github.com/OpenVidu/openvidu.git' - sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' - sh(script: '''#!/bin/bash - if $KURENTO_JAVA_SNAPSHOT ; then - git clone https://github.com/Kurento/kurento-java.git - cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION - fi - '''.stripIndent()) - sh(script: '''#!/bin/bash - if $KURENTO_MEDIA_SERVER_DEV ; then - echo "Upgrading KMS to dev version" - sudo apt-get update && sudo apt-get install -y aptitude - sudo aptitude remove -y kurento-media-server - DISTRO=`lsb_release --codename | cut -f2` - sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list - sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server - fi - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('Preparation') { + sh 'rm -rf ~/.m2 || true' + sh 'rm -rf openvidu || true' + sh 'rm -rf kurento-java || true' + sh 'git clone https://github.com/OpenVidu/openvidu.git' + sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' + sh(script: '''#!/bin/bash + if $KURENTO_JAVA_SNAPSHOT ; then + git clone https://github.com/Kurento/kurento-java.git + cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION + mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION + fi + '''.stripIndent()) + sh(script: '''#!/bin/bash + if $KURENTO_MEDIA_SERVER_DEV ; then + echo "Upgrading KMS to dev version" + sudo apt-get update && sudo apt-get install -y aptitude + sudo aptitude remove -y kurento-media-server + DISTRO=`lsb_release --codename | cut -f2` + sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list + sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server + fi + '''.stripIndent()) } - try { - stage('OpenVidu Browser build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_BROWSER_COMMIT - fi - cd openvidu-browser - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-browser-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Browser build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_BROWSER_COMMIT + fi + cd openvidu-browser + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-browser-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) } - try { - stage('OpenVidu Node Client build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT - fi - cd openvidu-node-client - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-node-client-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Node Client build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT + fi + cd openvidu-node-client + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-node-client-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) } - try { - stage('OpenVidu TestApp build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_TESTAPP_COMMIT - fi - cd openvidu-testapp - npm install --unsafe-perm - npm install /opt/openvidu/openvidu-browser-*.tgz - npm install /opt/openvidu/openvidu-node-client-*.tgz - export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu TestApp build') { + sh(script: '''#!/bin/bash + set -e + cd openvidu + if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_TESTAPP_COMMIT + fi + cd openvidu-testapp + npm install --unsafe-perm + npm install /opt/openvidu/openvidu-browser-*.tgz + npm install /opt/openvidu/openvidu-node-client-*.tgz + export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) } - try { - stage('OpenVidu Java Client build') { - sh(script: '''#!/bin/bash - cd openvidu - if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT - fi - cd openvidu-java-client - mvn --batch-mode versions:set -DnewVersion=TEST - mvn clean compile package - mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Java Client build') { + sh(script: '''#!/bin/bash + cd openvidu + if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT + fi + cd openvidu-java-client + mvn --batch-mode versions:set -DnewVersion=TEST + mvn clean compile package + mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) } - try { - stage('OpenVidu parent build') { - sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' - sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu parent build') { + sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' + sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } - try { - stage('OpenVidu Server unit tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Server unit tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' } - try { - stage('OpenVidu Server integration tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Server integration tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' } - try { - stage('OpenVidu Server build') { - sh(script: '''#!/bin/bash - cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod - cd ../.. - mvn --batch-mode package - cp target/openvidu-server*.jar /opt/openvidu - '''.stripIndent()) - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage('OpenVidu Server build') { + sh(script: '''#!/bin/bash + cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod + cd ../.. + mvn --batch-mode package + cp target/openvidu-server*.jar /opt/openvidu + '''.stripIndent()) } - try { - stage ('Environment Launch') { - sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' - sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' - sh '/usr/bin/kurento-media-server &> /kms.log &' - sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' - sh(script: '''#!/bin/bash - if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then - echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - else - echo "Using default openvidu-recording tag" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - fi - '''.stripIndent()) - sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' - } - } catch (error) { - currentBuild.result = 'FAILURE' + + stage ('Environment Launch') { + sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' + sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' + sh '/usr/bin/kurento-media-server &> /kms.log &' + sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' + sh(script: '''#!/bin/bash + if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then + echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + else + echo "Using default openvidu-recording tag" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + fi + '''.stripIndent()) + sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' } + stage ('OpenVidu E2E tests') { try { sh(script: '''#!/bin/bash From fbb7e6ce43dd03829247a79463366bf8ad4fc9fd Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 21:33:46 +0100 Subject: [PATCH 271/435] Jenkinsfile: fail execution if error in any inline script --- openvidu-test-e2e/jenkins/Jenkinsfile | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 04184a16..4a06c7bc 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -18,7 +18,7 @@ node('container') { sh 'rm -rf kurento-java || true' sh 'git clone https://github.com/OpenVidu/openvidu.git' sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e if $KURENTO_JAVA_SNAPSHOT ; then git clone https://github.com/Kurento/kurento-java.git cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) @@ -29,7 +29,7 @@ node('container') { mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION fi '''.stripIndent()) - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e if $KURENTO_MEDIA_SERVER_DEV ; then echo "Upgrading KMS to dev version" sudo apt-get update && sudo apt-get install -y aptitude @@ -42,7 +42,7 @@ node('container') { } stage('OpenVidu Browser build') { - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_BROWSER_COMMIT @@ -56,7 +56,7 @@ node('container') { } stage('OpenVidu Node Client build') { - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT @@ -70,8 +70,7 @@ node('container') { } stage('OpenVidu TestApp build') { - sh(script: '''#!/bin/bash - set -e + sh(script: '''#!/bin/bash -e cd openvidu if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTAPP_COMMIT @@ -87,7 +86,7 @@ node('container') { } stage('OpenVidu Java Client build') { - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e cd openvidu if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT @@ -114,7 +113,7 @@ node('container') { } stage('OpenVidu Server build') { - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. mvn --batch-mode package @@ -127,7 +126,7 @@ node('container') { sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & @@ -141,7 +140,7 @@ node('container') { stage ('OpenVidu E2E tests') { try { - sh(script: '''#!/bin/bash + sh(script: '''#!/bin/bash -e cd openvidu if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTE2E_COMMIT From e9b21c9da29feb5ec20dcff5c40d132baf8f3384 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 21:40:50 +0100 Subject: [PATCH 272/435] openvidu-node-client: rollback to typescript 3.8.3 --- openvidu-node-client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-node-client/package.json b/openvidu-node-client/package.json index 502e76b2..aa346f8c 100644 --- a/openvidu-node-client/package.json +++ b/openvidu-node-client/package.json @@ -19,7 +19,7 @@ "ts-node": "9.0.0", "tslint": "6.1.3", "typedoc": "0.19.2", - "typescript": "3.9.2" + "typescript": "3.8.3" }, "license": "Apache-2.0", "main": "lib/index.js", From 05287138491189b7c204fd0f14369402b6bee897 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 10 Nov 2020 21:42:21 +0100 Subject: [PATCH 273/435] openvidu-test-e2e: KMS updated to 6.15.0 in Docker containers --- openvidu-test-e2e/docker/bionic/Dockerfile | 2 +- openvidu-test-e2e/docker/xenial/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-test-e2e/docker/bionic/Dockerfile b/openvidu-test-e2e/docker/bionic/Dockerfile index b5b2c24e..3b97196e 100644 --- a/openvidu-test-e2e/docker/bionic/Dockerfile +++ b/openvidu-test-e2e/docker/bionic/Dockerfile @@ -9,7 +9,7 @@ RUN apt-get update && apt-get -y upgrade RUN apt-get install -y software-properties-common && apt-get install -y --no-install-recommends apt-utils # Install Kurento Media Server (KMS) -RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.14.0 bionic kms6" | tee /etc/apt/sources.list.d/kurento.list \ +RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.15.0 bionic kms6" | tee /etc/apt/sources.list.d/kurento.list \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 \ && apt-get update \ && apt-get -y install kurento-media-server diff --git a/openvidu-test-e2e/docker/xenial/Dockerfile b/openvidu-test-e2e/docker/xenial/Dockerfile index 5ade8ad2..ae86cdb2 100644 --- a/openvidu-test-e2e/docker/xenial/Dockerfile +++ b/openvidu-test-e2e/docker/xenial/Dockerfile @@ -9,7 +9,7 @@ RUN apt-get update && apt-get -y upgrade RUN apt-get install -y software-properties-common && apt-get install -y --no-install-recommends apt-utils # Install Kurento Media Server (KMS) -RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.14.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \ +RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.15.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 \ && apt-get update \ && apt-get -y install kurento-media-server From 75848079085538dc6b91673c5a5f50558a38b6ba Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 10:39:25 +0100 Subject: [PATCH 274/435] Kurento updated to 6.15.0 --- openvidu-server/docker/openvidu-server-kms/Dockerfile | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-server/docker/openvidu-server-kms/Dockerfile b/openvidu-server/docker/openvidu-server-kms/Dockerfile index a4d2b0cc..47fea732 100644 --- a/openvidu-server/docker/openvidu-server-kms/Dockerfile +++ b/openvidu-server/docker/openvidu-server-kms/Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:16.04 MAINTAINER openvidu@gmail.com # Install Kurento Media Server (KMS) -RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.14.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \ +RUN echo "deb [arch=amd64] http://ubuntu.openvidu.io/6.15.0 xenial kms6" | tee /etc/apt/sources.list.d/kurento.list \ && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83 \ && apt-get update \ && apt-get -y install kurento-media-server \ diff --git a/pom.xml b/pom.xml index a599d8af..9f08f3b6 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ - 6.14.0 + 6.15.0 2.2.4.RELEASE 4.13.1 5.6.0 From 27219a967531d39130de01253b1a667994bcfbc3 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 11:29:50 +0100 Subject: [PATCH 275/435] openvidu-parent: dependencies updated --- pom.xml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 9f08f3b6..4bded85b 100644 --- a/pom.xml +++ b/pom.xml @@ -43,35 +43,35 @@ 6.15.0 - 2.2.4.RELEASE + 2.3.5.RELEASE 4.13.1 - 5.6.0 - 1.6.0 + 5.7.0 + 1.7.0 3.141.59 - 2.23.4 - 2.0.5 + 3.6.0 + 2.0.9 2.2 4.5.13 - 3.1.0 - 3.10 - 3.1.5 + 3.1.2 + 3.11 + 3.2.5 1.7.30 2.8.6 1.4.9 - 4.0.0 + 4.2.2 2.15.1 1.1.0 1.1.0 3.0.0-M3 - 1.2 + 1.3 3.2.1 - 3.0.0-M4 + 3.0.0-M5 1.6 1.6.8 - 1.6.0 + 3.0.0 3.2.0 1.8 From 5018d75142ce8c4dbef6ee3e109ca54ee6985eb1 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 12:29:35 +0100 Subject: [PATCH 276/435] Spring Boot version down to 2.3.2.RELEASE --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4bded85b..c63efe16 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 6.15.0 - 2.3.5.RELEASE + 2.3.2.RELEASE 4.13.1 5.7.0 1.7.0 From fc2b26ce832171fc06128cc04a632d30d51342d5 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 13:20:15 +0100 Subject: [PATCH 277/435] Update Spring Boot to 2.3.5.RELEASE --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c63efe16..4bded85b 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ 6.15.0 - 2.3.2.RELEASE + 2.3.5.RELEASE 4.13.1 5.7.0 1.7.0 From 958813a3220ebab57bbc73921539dd7e9d35dd43 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 13:36:40 +0100 Subject: [PATCH 278/435] Include spring-boot-starter-websocket dependency --- openvidu-server/pom.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openvidu-server/pom.xml b/openvidu-server/pom.xml index a2282893..0ab7fc23 100644 --- a/openvidu-server/pom.xml +++ b/openvidu-server/pom.xml @@ -187,6 +187,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework + spring-websocket + org.slf4j slf4j-api @@ -258,6 +262,11 @@ spring-boot-starter-logging ${version.spring-boot} + + org.springframework.boot + spring-boot-starter-websocket + ${version.spring-boot} + com.github.docker-java docker-java From 1b0f4e0d935303fc1127ab6a7246efafc541ea59 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 13:49:01 +0100 Subject: [PATCH 279/435] Jenkinsfile: fix KURENTO_JAVA_SNAPSHOT option --- openvidu-test-e2e/jenkins/Jenkinsfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index 4a06c7bc..dc8a0a80 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -22,7 +22,6 @@ node('container') { if $KURENTO_JAVA_SNAPSHOT ; then git clone https://github.com/Kurento/kurento-java.git cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION @@ -100,6 +99,12 @@ node('container') { } stage('OpenVidu parent build') { + sh(script: '''#!/bin/bash -e + if $KURENTO_JAVA_SNAPSHOT ; then + cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION + fi + '''.stripIndent()) sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' } From e56005bbc175a8a65deb96431efd2b4d47fe6655 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 15:16:17 +0100 Subject: [PATCH 280/435] Jenkinsfile: updated kurento-java build --- openvidu-test-e2e/jenkins/Jenkinsfile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index dc8a0a80..a437fea4 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -19,13 +19,11 @@ node('container') { sh 'git clone https://github.com/OpenVidu/openvidu.git' sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' sh(script: '''#!/bin/bash -e - if $KURENTO_JAVA_SNAPSHOT ; then + if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then git clone https://github.com/Kurento/kurento-java.git - cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-client:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-client-jetty:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-jsonrpc-server:$MVN_VERSION - mvn dependency:get -DrepoUrl=https://maven.openvidu.io/repository/snapshots/ -Dartifact=org.kurento:kurento-test:$MVN_VERSION + cd kurento-java + git checkout -f $KURENTO_JAVA_COMMIT + mvn clean install fi '''.stripIndent()) sh(script: '''#!/bin/bash -e @@ -94,13 +92,14 @@ node('container') { mvn --batch-mode versions:set -DnewVersion=TEST mvn clean compile package mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar + cd .. git checkout -f $OPENVIDU_COMMIT '''.stripIndent()) } stage('OpenVidu parent build') { sh(script: '''#!/bin/bash -e - if $KURENTO_JAVA_SNAPSHOT ; then + if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION fi From 5993b9f1d92f148c28b0368a8885a6a2d6900d5c Mon Sep 17 00:00:00 2001 From: jenkinsopenvidu Date: Wed, 11 Nov 2020 16:51:47 +0000 Subject: [PATCH 281/435] Update openvidu-node-client to version v2.16.0 --- openvidu-node-client/package-lock.json | 2 +- openvidu-node-client/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-node-client/package-lock.json b/openvidu-node-client/package-lock.json index 156a3e01..e6b52891 100644 --- a/openvidu-node-client/package-lock.json +++ b/openvidu-node-client/package-lock.json @@ -1,6 +1,6 @@ { "name": "openvidu-node-client", - "version": "2.15.0", + "version": "2.16.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/openvidu-node-client/package.json b/openvidu-node-client/package.json index aa346f8c..f7676ad8 100644 --- a/openvidu-node-client/package.json +++ b/openvidu-node-client/package.json @@ -33,5 +33,5 @@ "docs": "./generate-docs.sh" }, "typings": "lib/index.d.ts", - "version": "2.15.0" + "version": "2.16.0" } From b94fd5930f8675d46c4bc1a84ca4ff403b040bb9 Mon Sep 17 00:00:00 2001 From: openvidu Date: Wed, 11 Nov 2020 17:32:59 +0000 Subject: [PATCH 282/435] Update openvidu-java-client to version v2.16.0 --- openvidu-java-client/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openvidu-java-client/pom.xml b/openvidu-java-client/pom.xml index 5520e10f..e7f39c9b 100644 --- a/openvidu-java-client/pom.xml +++ b/openvidu-java-client/pom.xml @@ -10,7 +10,7 @@ openvidu-java-client - 2.15.1 + 2.16.0 jar OpenVidu Java Client diff --git a/pom.xml b/pom.xml index 4bded85b..ed5de35f 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ 4.2.2 - 2.15.1 + 2.16.0 1.1.0 1.1.0 From 03ba1578fdfa0e88e96fd1399aa0ac57878e06e4 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Wed, 11 Nov 2020 18:33:17 +0100 Subject: [PATCH 283/435] openvidu-testapp: updated to openvidu-node-client:2.16.0 --- openvidu-testapp/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-testapp/package.json b/openvidu-testapp/package.json index 65c58b8d..b6127815 100644 --- a/openvidu-testapp/package.json +++ b/openvidu-testapp/package.json @@ -16,7 +16,7 @@ "core-js": "3.4.7", "hammerjs": "2.0.8", "openvidu-browser": "2.15.0", - "openvidu-node-client": "2.15.0", + "openvidu-node-client": "2.16.0", "rxjs": "6.5.3", "zone.js": "0.10.2" }, From 70d30a5d6c017dbd66fb8059045fffd36d24a616 Mon Sep 17 00:00:00 2001 From: cruizba Date: Thu, 12 Nov 2020 10:23:46 +0100 Subject: [PATCH 284/435] deployment-pro: Add NGINX monitoring --- .../openvidu-server-pro/beats/filebeat.yml | 22 +++++++++++++++++++ .../openvidu-server-pro/beats/metricbeat.yml | 10 +++++++++ .../openvidu-server-pro/docker-compose.yml | 19 ++++++++++++++++ .../install_openvidu_pro.sh | 11 ++++++++++ 4 files changed, 62 insertions(+) create mode 100644 openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml index 24297f04..51eeab24 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/filebeat.yml @@ -1,3 +1,25 @@ +filebeat.autodiscover: + providers: + - type: docker + hints.enabled: true + templates: + - condition: + contains: + docker.container.name: "nginx" + config: + - module: nginx + access: + input: + type: docker + containers: + ids: "${data.docker.container.id}" + stream: "stdout" + error: + input: + type: docker + containers: + ids: "${data.docker.container.id}" + stream: "stderr" filebeat.inputs: - type: container paths: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml new file mode 100644 index 00000000..09a68d9a --- /dev/null +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml @@ -0,0 +1,10 @@ +metricbeat.modules: +- module: nginx + metricsets: ["stubstatus"] + enabled: true + period: 10s + hosts: ["http://127.0.0.1"] + server_status_path: "nginx_status" +output: + elasticsearch: + hosts: ["${OPENVIDU_PRO_ELASTICSEARCH_HOST}"] diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index c2419af0..c1a6744b 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -138,6 +138,25 @@ services: options: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" + metricbeat: + image: docker.elastic.co/beats/metricbeat-oss:7.8.0 + network_mode: host + restart: always + user: root + env_file: + - .env + environment: + - OPENVIDU_PRO_ELASTICSEARCH_HOST=${OPENVIDU_PRO_ELASTICSEARCH_HOST:-http://127.0.0.1:9200} + volumes: + - ./beats/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro + command: > + /bin/bash -c "metricbeat -e -strict.perms=false + `if [ ! -z $ELASTICSEARCH_USERNAME ]; then echo '-E output.elasticsearch.username=$ELASTICSEARCH_USERNAME'; fi` + `if [ ! -z $ELASTICSEARCH_PASSWORD ]; then echo '-E output.elasticsearch.password=$ELASTICSEARCH_PASSWORD'; fi`" + logging: + options: + max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" + filebeat: image: docker.elastic.co/beats/filebeat-oss:7.8.0 network_mode: host diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh index d4bdc722..67e6af64 100755 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/install_openvidu_pro.sh @@ -61,6 +61,10 @@ new_ov_installation() { --output "${BEATS_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'" printf '\n - filebeat.yml' + curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml \ + --output "${BEATS_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'" + printf '\n - metricbeat.yml' + curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env \ --output "${OPENVIDU_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'" printf '\n - .env' @@ -198,6 +202,10 @@ upgrade_ov() { --output "${TMP_FOLDER}/filebeat.yml" || fatal_error "Error when downloading the file 'filebeat.yml'" printf '\n - filebeat.yml' + curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/beats/metricbeat.yml \ + --output "${TMP_FOLDER}/metricbeat.yml" || fatal_error "Error when downloading the file 'metricbeat.yml'" + printf '\n - metricbeat.yml' + curl --silent ${DOWNLOAD_URL}/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/.env \ --output "${TMP_FOLDER}/.env" || fatal_error "Error when downloading the file '.env'" printf '\n - .env' @@ -301,6 +309,9 @@ upgrade_ov() { mv "${TMP_FOLDER}/filebeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/filebeat.yml" || fatal_error "Error while updating 'filebeat.yml'" printf '\n - filebeat.yml' + mv "${TMP_FOLDER}/metricbeat.yml" "${OPENVIDU_PREVIOUS_FOLDER}/beats/metricbeat.yml" || fatal_error "Error while updating 'metricbeat.yml'" + printf '\n - metricbeat.yml' + printf "\n => Deleting 'tmp' folder" rm -rf "${TMP_FOLDER}" || fatal_error "Error deleting 'tmp' folder" From 33831f86a7c4f71cfb190ab7ef4d3ac872a8be06 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 12 Nov 2020 11:33:56 +0100 Subject: [PATCH 285/435] Jenkinsfile: add -x flag in all bash scripts --- openvidu-test-e2e/jenkins/Jenkinsfile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index a437fea4..d673cd1e 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -18,7 +18,7 @@ node('container') { sh 'rm -rf kurento-java || true' sh 'git clone https://github.com/OpenVidu/openvidu.git' sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then git clone https://github.com/Kurento/kurento-java.git cd kurento-java @@ -26,7 +26,7 @@ node('container') { mvn clean install fi '''.stripIndent()) - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe if $KURENTO_MEDIA_SERVER_DEV ; then echo "Upgrading KMS to dev version" sudo apt-get update && sudo apt-get install -y aptitude @@ -39,7 +39,7 @@ node('container') { } stage('OpenVidu Browser build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_BROWSER_COMMIT @@ -53,7 +53,7 @@ node('container') { } stage('OpenVidu Node Client build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT @@ -67,7 +67,7 @@ node('container') { } stage('OpenVidu TestApp build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTAPP_COMMIT @@ -83,7 +83,7 @@ node('container') { } stage('OpenVidu Java Client build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT @@ -98,7 +98,7 @@ node('container') { } stage('OpenVidu parent build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION @@ -117,7 +117,7 @@ node('container') { } stage('OpenVidu Server build') { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod cd ../.. mvn --batch-mode package @@ -130,7 +130,7 @@ node('container') { sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' sh '/usr/bin/kurento-media-server &> /kms.log &' sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & @@ -144,7 +144,7 @@ node('container') { stage ('OpenVidu E2E tests') { try { - sh(script: '''#!/bin/bash -e + sh(script: '''#!/bin/bash -xe cd openvidu if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then git checkout -f $OPENVIDU_TESTE2E_COMMIT From 16d8ec80cec943a19125afa9c11a1544cf916147 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 12 Nov 2020 16:36:15 +0100 Subject: [PATCH 286/435] Update docker-compose to 2.16.0 --- .../ce/docker-compose/docker-compose.override.yml | 4 ++-- .../deployments/ce/docker-compose/docker-compose.yml | 8 ++++---- .../pro/docker-compose/media-node/docker-compose.yml | 4 ++-- .../openvidu-server-pro/docker-compose.override.yml | 4 ++-- .../docker-compose/openvidu-server-pro/docker-compose.yml | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml index 156db956..d4796d20 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.override.yml @@ -9,11 +9,11 @@ services: # # Default Application # - # Openvidu-Call Version: 2.15.0 + # Openvidu-Call Version: 2.16.0 # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.16.0-beta1 + image: openvidu/openvidu-call:2.16.0 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml index a44b356a..964251f7 100644 --- a/openvidu-server/deployments/ce/docker-compose/docker-compose.yml +++ b/openvidu-server/deployments/ce/docker-compose/docker-compose.yml @@ -11,7 +11,7 @@ # # This file will be overridden when update OpenVidu Platform # -# Openvidu Version: 2.15.0 +# Openvidu Version: 2.16.0 # # Installation Mode: On Premises # @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server:2.16.0-dev3 + image: openvidu/openvidu-server:2.16.0 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] @@ -75,7 +75,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" coturn: - image: openvidu/openvidu-coturn:2.0.0-dev3 + image: openvidu/openvidu-coturn:2.0.0 restart: on-failure network_mode: host environment: @@ -90,7 +90,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: - image: openvidu/openvidu-proxy:4.0.0-dev6 + image: openvidu/openvidu-proxy:4.0.0 restart: on-failure network_mode: host volumes: diff --git a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml index b1ca536f..9d0d1fb7 100644 --- a/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/media-node/docker-compose.yml @@ -6,7 +6,7 @@ # # This docker-compose file coordinates all services of OpenVidu CE Platform. # -# Openvidu Version: 2.15.0 +# Openvidu Version: 2.16.0 # # Installation Mode: On Premises # @@ -16,7 +16,7 @@ version: '3.1' services: media-node-controller: - image: openvidu/media-node-controller:2.0.0-dev1 + image: openvidu/media-node-controller:2.0.0 restart: always ulimits: core: -1 diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml index 156db956..d4796d20 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.override.yml @@ -9,11 +9,11 @@ services: # # Default Application # - # Openvidu-Call Version: 2.15.0 + # Openvidu-Call Version: 2.16.0 # # -------------------------------------------------------------- app: - image: openvidu/openvidu-call:2.16.0-beta1 + image: openvidu/openvidu-call:2.16.0 restart: on-failure network_mode: host environment: diff --git a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml index c1a6744b..979ca47f 100644 --- a/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml +++ b/openvidu-server/deployments/pro/docker-compose/openvidu-server-pro/docker-compose.yml @@ -11,7 +11,7 @@ # # This file will be overridden when update OpenVidu Platform # -# Openvidu Version: 2.15.1 +# Openvidu Version: 2.16.0 # # Installation Mode: On Premises # @@ -22,7 +22,7 @@ version: '3.1' services: openvidu-server: - image: openvidu/openvidu-server-pro:2.16.0-dev9 + image: openvidu/openvidu-server-pro:2.16.0 restart: on-failure network_mode: host entrypoint: ['/usr/local/bin/entrypoint.sh'] @@ -62,7 +62,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" coturn: - image: openvidu/openvidu-coturn:2.0.0-dev3 + image: openvidu/openvidu-coturn:2.0.0 restart: on-failure network_mode: host environment: @@ -78,7 +78,7 @@ services: max-size: "${DOCKER_LOGS_MAX_SIZE:-100M}" nginx: - image: openvidu/openvidu-proxy:4.0.0-dev6 + image: openvidu/openvidu-proxy:4.0.0 restart: on-failure network_mode: host volumes: From a5b5886349bed8f71b32feb14cf02ed6285a94b2 Mon Sep 17 00:00:00 2001 From: jenkinsopenvidu Date: Thu, 12 Nov 2020 15:45:57 +0000 Subject: [PATCH 287/435] Update to version v2.16.0 --- openvidu-browser/package.json | 2 +- openvidu-server/pom.xml | 2 +- .../src/dashboard/package-lock.json | 4426 +---------------- openvidu-server/src/dashboard/package.json | 2 +- openvidu-testapp/package.json | 4 +- 5 files changed, 59 insertions(+), 4377 deletions(-) diff --git a/openvidu-browser/package.json b/openvidu-browser/package.json index a2da810e..a52abc2d 100644 --- a/openvidu-browser/package.json +++ b/openvidu-browser/package.json @@ -41,5 +41,5 @@ "docs": "./generate-docs.sh" }, "types": "lib/index.d.ts", - "version": "2.15.0" + "version": "2.16.0" } diff --git a/openvidu-server/pom.xml b/openvidu-server/pom.xml index 0ab7fc23..bd2fbf0d 100644 --- a/openvidu-server/pom.xml +++ b/openvidu-server/pom.xml @@ -12,7 +12,7 @@ jar OpenVidu Server - 2.15.0 + 2.16.0 OpenVidu Server https://openvidu.io diff --git a/openvidu-server/src/dashboard/package-lock.json b/openvidu-server/src/dashboard/package-lock.json index 346a0f16..ec603b21 100644 --- a/openvidu-server/src/dashboard/package-lock.json +++ b/openvidu-server/src/dashboard/package-lock.json @@ -1628,6 +1628,11 @@ "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", "dev": true }, + "@types/platform": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.3.tgz", + "integrity": "sha512-1fuOulBHWIxAPLBtLms+UtbeRDt6rL7gP5R+Yugfzdg+poCLxXqXTE8i+FpYeiytGRLUEtnFkjsY/j+usbQBqw==" + }, "@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", @@ -5033,6 +5038,14 @@ "map-cache": "^0.2.2" } }, + "freeice": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/freeice/-/freeice-2.2.2.tgz", + "integrity": "sha512-XNoIxDHufqPIBSLpp4IrFPnoc+hv/0RwdOGhIoggIDC2ZKf5r6OoixbeoFJSmZOAq2aYiEUArhuQ8zVVrM5C4w==", + "requires": { + "normalice": "^1.0.0" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -5233,6 +5246,14 @@ "har-schema": "^2.0.0" } }, + "hark": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/hark/-/hark-1.2.3.tgz", + "integrity": "sha512-u68vz9SCa38ESiFJSDjqK8XbXqWzyot7Cj6Y2b6jk2NJ+II3MY2dIrLMg/kjtIAun4Y1DHF/20hfx4rq1G5GMg==", + "requires": { + "wildemitter": "^1.2.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -7658,6 +7679,11 @@ "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", "dev": true }, + "normalice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalice/-/normalice-1.0.1.tgz", + "integrity": "sha1-A0NcLuzVYxprygLaOTDsPjRagPc=" + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -8009,4387 +8035,28 @@ } }, "openvidu-browser": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.15.0.tgz", - "integrity": "sha512-agnyeYIf1ze5ynGqNw32zFedlov9JZzjoFQHNMwuAoFYc2/24Aajs9cyw3j0m7v8xmMkqWSOYvsu7kGc8z1mZg==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/openvidu-browser/-/openvidu-browser-2.16.0.tgz", + "integrity": "sha512-o7TWCKhEKPYYuDpYhL1u2OMvZVhzj6Kef8iD64QOTO3q3Wq6jpDGpM6J9ZxfqjE9owyJWQkDL6jdzq4tEiiQvw==", "requires": { - "@types/node": "13.13.2", - "@types/platform": "1.3.2", + "@types/node": "14.14.7", + "@types/platform": "1.3.3", "freeice": "2.2.2", "hark": "1.2.3", - "platform": "1.3.5", - "uuid": "7.0.3", + "platform": "1.3.6", + "uuid": "8.3.1", "wolfy87-eventemitter": "5.2.9" }, "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "requires": { - "@babel/highlight": "^7.8.3" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==" - }, - "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, "@types/node": { - "version": "13.13.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.2.tgz", - "integrity": "sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A==" - }, - "@types/platform": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/platform/-/platform-1.3.2.tgz", - "integrity": "sha512-Tn6OuJDAG7bJbyi4R7HqcxXp1w2lmIxVXqyNhPt1Bm0FO2EWIi3CI87JVzF7ncqK0ZMPuUycS3wTMIk85EeF1Q==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==" - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" - }, - "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", - "requires": { - "JSONStream": "^1.0.3", - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - } - }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", - "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" - } - } - }, - "browserify": { - "version": "16.5.1", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.1.tgz", - "integrity": "sha512-EQX0h59Pp+0GtSRb5rL6OTfrttlzv+uyaUVlK6GX3w11SQ0jKPKyjC/54RhPR2ib2KmfcELM06e8FxcI5XNU2A==", - "requires": { - "JSONStream": "^1.0.3", - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^1.11.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.0.0", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "requires": { - "pako": "~1.0.5" - } - }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" - }, - "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cached-path-relative": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", - "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==" - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "requires": { - "is-extglob": "^2.1.1" - } - } - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "coffeescript": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", - "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" - }, - "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", - "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" - }, - "continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=" - }, - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=" - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-0.2.9.tgz", - "integrity": "sha1-vWf5bAfvtjA7f+lMHpefiEeOCjk=", - "requires": { - "lru-cache": "^2.5.0" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "csproj2ts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/csproj2ts/-/csproj2ts-1.1.0.tgz", - "integrity": "sha512-sk0RTT51t4lUNQ7UfZrqjQx7q4g0m3iwNA6mvyh7gLsgQYvwKzfdyoAgicC9GqJvkoIkU0UmndV9c7VZ8pJ45Q==", - "requires": { - "es6-promise": "^4.1.1", - "lodash": "^4.17.4", - "semver": "^5.4.1", - "xml2js": "^0.4.19" - }, - "dependencies": { - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dargs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", - "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==" - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" - }, - "deps-sort": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", - "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", - "requires": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "^2.0.0" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" - }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "requires": { - "string-template": "~0.2.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es6-promise": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz", - "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=" - }, - "events": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", - "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=" - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "requires": { - "for-in": "^1.0.1" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "freeice": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/freeice/-/freeice-2.2.2.tgz", - "integrity": "sha512-XNoIxDHufqPIBSLpp4IrFPnoc+hv/0RwdOGhIoggIDC2ZKf5r6OoixbeoFJSmZOAq2aYiEUArhuQ8zVVrM5C4w==", - "requires": { - "normalice": "^1.0.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", - "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "bundled": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.3", - "bundled": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "needle": { - "version": "2.3.3", - "bundled": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "bundled": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "optional": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "requires": { - "globule": "^1.0.0" - } - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, - "getobject": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", - "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globule": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz", - "integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==", - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.12", - "minimatch": "~3.0.2" - } - }, - "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" - }, - "grunt": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.1.0.tgz", - "integrity": "sha512-+NGod0grmviZ7Nzdi9am7vuRS/h76PcWDsV635mEXF0PEQMUV6Kb+OjTdsVxbi0PZmfQOjCMKb3w8CVZcqsn1g==", - "requires": { - "coffeescript": "~1.10.0", - "dateformat": "~1.0.12", - "eventemitter2": "~0.4.13", - "exit": "~0.1.1", - "findup-sync": "~0.3.0", - "glob": "~7.0.0", - "grunt-cli": "~1.2.0", - "grunt-known-options": "~1.1.0", - "grunt-legacy-log": "~2.0.0", - "grunt-legacy-util": "~1.1.1", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.13.1", - "minimatch": "~3.0.2", - "mkdirp": "~1.0.3", - "nopt": "~3.0.6", - "path-is-absolute": "~1.0.0", - "rimraf": "~2.6.2" - }, - "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "grunt-cli": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", - "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", - "requires": { - "findup-sync": "~0.3.0", - "grunt-known-options": "~1.1.0", - "nopt": "~3.0.6", - "resolve": "~1.1.0" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" - } - } - }, - "grunt-cli": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", - "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", - "requires": { - "grunt-known-options": "~1.1.0", - "interpret": "~1.1.0", - "liftoff": "~2.5.0", - "nopt": "~4.0.1", - "v8flags": "~3.1.1" - }, - "dependencies": { - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - } - } - }, - "grunt-contrib-copy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", - "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", - "requires": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "grunt-contrib-sass": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-sass/-/grunt-contrib-sass-1.0.0.tgz", - "integrity": "sha1-gGg4JRy8DhqU1k1RXN00z2dNcBs=", - "requires": { - "async": "^0.9.0", - "chalk": "^1.0.0", - "cross-spawn": "^0.2.3", - "dargs": "^4.0.0", - "which": "^1.0.5" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "grunt-contrib-uglify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz", - "integrity": "sha512-dwf8/+4uW1+7pH72WButOEnzErPGmtUvc8p08B0eQS/6ON0WdeQu0+WFeafaPTbbY1GqtS25lsHWaDeiTQNWPg==", - "requires": { - "chalk": "^2.4.1", - "maxmin": "^2.1.0", - "uglify-js": "^3.5.0", - "uri-path": "^1.0.0" - } - }, - "grunt-contrib-watch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", - "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", - "requires": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==" - }, - "grunt-legacy-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", - "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.5" - } - }, - "grunt-legacy-log-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", - "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", - "requires": { - "chalk": "~2.4.1", - "lodash": "~4.17.10" - } - }, - "grunt-legacy-util": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", - "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", - "requires": { - "async": "~1.5.2", - "exit": "~0.1.1", - "getobject": "~0.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.10", - "underscore.string": "~3.3.4", - "which": "~1.3.0" - } - }, - "grunt-postcss": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/grunt-postcss/-/grunt-postcss-0.9.0.tgz", - "integrity": "sha512-lglLcVaoOIqH0sFv7RqwUKkEFGQwnlqyAKbatxZderwZGV1nDyKHN7gZS9LUiTx1t5GOvRBx0BEalHMyVwFAIA==", - "requires": { - "chalk": "^2.1.0", - "diff": "^3.0.0", - "postcss": "^6.0.11" - } - }, - "grunt-string-replace": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/grunt-string-replace/-/grunt-string-replace-1.3.1.tgz", - "integrity": "sha1-YzoDvHhIKg4OH5339kWBH8H7sWI=", - "requires": { - "async": "^2.0.0", - "chalk": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "grunt-ts": { - "version": "6.0.0-beta.22", - "resolved": "https://registry.npmjs.org/grunt-ts/-/grunt-ts-6.0.0-beta.22.tgz", - "integrity": "sha512-g9e+ZImQ7W38dfpwhp0+GUltXWidy3YGPfIA/IyGL5HMv6wmVmMMoSgscI5swhs2HSPf8yAvXAAJbwrouijoRg==", - "requires": { - "chokidar": "^2.0.4", - "csproj2ts": "^1.1.0", - "detect-indent": "^4.0.0", - "detect-newline": "^2.1.0", - "es6-promise": "~0.1.1", - "jsmin2": "^1.2.1", - "lodash": "~4.17.10", - "ncp": "0.5.1", - "rimraf": "2.2.6", - "semver": "^5.3.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz", - "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=" - } - } - }, - "gzip-size": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", - "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", - "requires": { - "duplexer": "^0.1.1" - } - }, - "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "hark": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/hark/-/hark-1.2.3.tgz", - "integrity": "sha512-u68vz9SCa38ESiFJSDjqK8XbXqWzyot7Cj6Y2b6jk2NJ+II3MY2dIrLMg/kjtIAun4Y1DHF/20hfx4rq1G5GMg==", - "requires": { - "wildemitter": "^1.2.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "highlight.js": { - "version": "9.18.1", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz", - "integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==" - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=" - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" - }, - "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=" - }, - "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=" - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "^2.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "requires": { - "source-map": "~0.5.3" - } - }, - "insert-module-globals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", - "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", - "requires": { - "JSONStream": "^1.0.3", - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "^3.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsmin2": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jsmin2/-/jsmin2-1.2.1.tgz", - "integrity": "sha1-iPvi+/dfCpH2YCD9mBzWk/S/5X4=" - }, - "json-stable-stringify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", - "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", - "requires": { - "jsonify": "~0.0.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" - }, - "labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", - "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - } - } - }, - "livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==" - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=" - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" - }, - "lunr": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", - "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==" - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "requires": { - "object-visit": "^1.0.0" - } - }, - "marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==" - }, - "maxmin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", - "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=", - "requires": { - "chalk": "^1.0.0", - "figures": "^1.0.1", - "gzip-size": "^3.0.0", - "pretty-bytes": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - } - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mkdirp-classic": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.2.tgz", - "integrity": "sha512-ejdnDQcR75gwknmMw/tx02AuRs8jCtqFoFqDZMjiNxsu85sRIJVXDKHuLYvUUPRBUtV2FpSZa9bL1BUa3BdR2g==" - }, - "module-deps": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.2.tgz", - "integrity": "sha512-a9y6yDv5u5I4A+IPHTnqFxcaKr4p50/zxTjcQJaX2ws9tN/W6J6YXnEKhqRyPhl494dkcxx951onSKVezmI+3w==", - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "ncp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz", - "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=" - }, - "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "normalice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/normalice/-/normalice-1.0.1.tgz", - "integrity": "sha1-A0NcLuzVYxprygLaOTDsPjRagPc=" - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "requires": { - "isobject": "^3.0.0" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=" - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "^2.0.0" - } - }, - "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "pretty-bytes": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", - "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, - "dependencies": { - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "requires": { - "readable-stream": "^2.0.2" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "^1.0.0" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shasum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", - "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", - "requires": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" - } - }, - "shasum-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", - "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", - "requires": { - "fast-safe-stringify": "^2.0.7" - } - }, - "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" - }, - "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.18.tgz", - "integrity": "sha512-9luZr/BZ2QeU6tO2uG8N2aZpVSli4TSAOAqFOyTO51AJcD9P99c0K1h6dD6r6qo5dyT44BR5exweOaLLeldTkQ==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.0.tgz", - "integrity": "sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw==", - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^3.0.6", - "xtend": "^4.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "^4.0.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "requires": { - "minimist": "^1.1.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", - "requires": { - "acorn-node": "^1.2.0" - } - }, - "terser": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz", - "integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==", - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "requires": { - "process": "~0.11.0" - } - }, - "tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "tsconfig": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz", - "integrity": "sha1-X0J45wGACWeo/Dg/0ZZIh48qbjo=", - "requires": { - "any-promise": "^1.3.0", - "parse-json": "^2.2.0", - "strip-bom": "^2.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "tsify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/tsify/-/tsify-4.0.1.tgz", - "integrity": "sha512-ClznEI+pmwY5wmD0J7HCSVERwkD+l71ch3Dqyod2JuQLEsFaiNDI+vPjaGadsuVFVvmzgoI7HghrBtWsSmCDHQ==", - "requires": { - "convert-source-map": "^1.1.0", - "fs.realpath": "^1.0.0", - "object-assign": "^4.1.0", - "semver": "^5.6.0", - "through2": "^2.0.0", - "tsconfig": "^5.0.3" - } - }, - "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" - }, - "tslint": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.1.tgz", - "integrity": "sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA==", - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.10.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - } - } - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", - "requires": { - "tslib": "^1.8.1" - } - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typedoc": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.4.tgz", - "integrity": "sha512-4Lotef1l6lNU5Fulpux809WPlF9CkmcXfv5QFyanrjYlxMFxSdARRdsy8Jv1OU3z0vjR4JsvUQT0YpiPqztcOA==", - "requires": { - "fs-extra": "^8.1.0", - "handlebars": "^4.7.6", - "highlight.js": "^9.18.1", - "lodash": "^4.17.15", - "lunr": "^2.3.8", - "marked": "0.8.2", - "minimatch": "^3.0.0", - "progress": "^2.0.3", - "shelljs": "^0.8.3", - "typedoc-default-themes": "^0.10.0" - } - }, - "typedoc-default-themes": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.1.tgz", - "integrity": "sha512-SuqAQI0CkwhqSJ2kaVTgl37cWs733uy9UGUqwtcds8pkFK8oRF4rZmCq+FXTGIb9hIUOu40rf5Kojg0Ha6akeg==", - "requires": { - "lunr": "^2.3.8" - } - }, - "typescript": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" - }, - "uglify-js": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.1.tgz", - "integrity": "sha512-JUPoL1jHsc9fOjVFHdQIhqEEJsQvfKDjlubcCilu8U26uZ73qOg8VsN8O1jbuei44ZPlwL7kmbAdM4tzaUvqnA==", - "requires": { - "commander": "~2.20.3" - } - }, - "umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==" - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" - }, - "undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", - "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", - "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" - } - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" - }, - "uri-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", - "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=" - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "version": "14.14.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.7.tgz", + "integrity": "sha512-Zw1vhUSQZYw+7u5dAwNbIA9TuTotpzY/OF7sJM9FqPOF3SPjKnxrjoTktXDZgUjybf4cWVBP7O8wvKdSaGHweg==" }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" - }, - "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, - "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", - "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "wildemitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/wildemitter/-/wildemitter-1.2.1.tgz", - "integrity": "sha512-UMmSUoIQSir+XbBpTxOTS53uJ8s/lVhADCkEbhfRjUGFDPme/XGOb0sBWLx5sTz7Wx/2+TlAw1eK9O5lw5PiEw==" - }, - "wolfy87-eventemitter": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", - "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==" - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" } } }, @@ -13035,6 +8702,11 @@ "find-up": "^2.1.0" } }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, "portfinder": { "version": "1.0.25", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", @@ -18221,6 +13893,16 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "wildemitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/wildemitter/-/wildemitter-1.2.1.tgz", + "integrity": "sha512-UMmSUoIQSir+XbBpTxOTS53uJ8s/lVhADCkEbhfRjUGFDPme/XGOb0sBWLx5sTz7Wx/2+TlAw1eK9O5lw5PiEw==" + }, + "wolfy87-eventemitter": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", + "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==" + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", diff --git a/openvidu-server/src/dashboard/package.json b/openvidu-server/src/dashboard/package.json index 0591bb1c..990dd6fe 100644 --- a/openvidu-server/src/dashboard/package.json +++ b/openvidu-server/src/dashboard/package.json @@ -13,7 +13,7 @@ "@angular/router": "9.1.2", "core-js": "3.6.5", "jquery": "3.5.0", - "openvidu-browser": "2.15.0", + "openvidu-browser": "2.16.0", "rxjs": "6.5.5", "tslib": "1.11.1", "zone.js": "0.10.3" diff --git a/openvidu-testapp/package.json b/openvidu-testapp/package.json index b6127815..4b450a9e 100644 --- a/openvidu-testapp/package.json +++ b/openvidu-testapp/package.json @@ -15,7 +15,7 @@ "colormap": "2.3.1", "core-js": "3.4.7", "hammerjs": "2.0.8", - "openvidu-browser": "2.15.0", + "openvidu-browser": "2.16.0", "openvidu-node-client": "2.16.0", "rxjs": "6.5.3", "zone.js": "0.10.2" @@ -44,5 +44,5 @@ "start": "ng serve", "test": "ng test" }, - "version": "2.15.0" + "version": "2.16.0" } \ No newline at end of file From 4bcd5c5445c73aa66431b1fb607a46a74c5e3905 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 12 Nov 2020 21:02:15 +0100 Subject: [PATCH 288/435] replicate_amis.sh script fix (no credentials) --- openvidu-server/deployments/pro/aws/replicate_amis.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/openvidu-server/deployments/pro/aws/replicate_amis.sh b/openvidu-server/deployments/pro/aws/replicate_amis.sh index 78772710..1a9c55d8 100755 --- a/openvidu-server/deployments/pro/aws/replicate_amis.sh +++ b/openvidu-server/deployments/pro/aws/replicate_amis.sh @@ -12,9 +12,6 @@ set -eu -o pipefail # OV_AMI_ID OpenVidu AMI ID export AWS_DEFAULT_REGION=eu-west-1 -export AWS_ACCESS_KEY_ID=${NAEVA_AWS_ACCESS_KEY_ID} -export AWS_SECRET_ACCESS_KEY=${NAEVA_AWS_SECRET_ACCESS_KEY} - echo "Making original AMIs public" From f695a13c88b07330e342d6d171369b5f424e6acd Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 12 Nov 2020 21:27:55 +0100 Subject: [PATCH 289/435] replicate_amis.sh: remove -x flag --- openvidu-server/deployments/pro/aws/replicate_amis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openvidu-server/deployments/pro/aws/replicate_amis.sh b/openvidu-server/deployments/pro/aws/replicate_amis.sh index 1a9c55d8..f8e9c787 100755 --- a/openvidu-server/deployments/pro/aws/replicate_amis.sh +++ b/openvidu-server/deployments/pro/aws/replicate_amis.sh @@ -1,4 +1,4 @@ -#!/bin/bash -x +#!/bin/bash set -eu -o pipefail # Replicate AMIs in all regions From 1c21a154cd1d5ac50f015bac0a83b0da6d4e063f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 14 Nov 2020 22:42:59 +0100 Subject: [PATCH 290/435] openvidu-test-e2e: add opera test and refactor Jenkinsfile --- openvidu-test-e2e/jenkins/Jenkinsfile | 309 +++++++++--------- .../e2e/AbstractOpenViduTestAppE2eTest.java | 1 + .../e2e/OpenViduTestAppE2eAndroidTest.java | 101 ++++++ .../test/e2e/OpenViduTestAppE2eTest.java | 72 ++-- 4 files changed, 307 insertions(+), 176 deletions(-) create mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index d673cd1e..d0c9b071 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -1,171 +1,176 @@ node('container') { - sh 'docker rm -f chrome firefox e2e || true' + sh 'docker rm -f e2e chrome firefox opera || true' + sh 'rm -rf /opt/openvidu/* || true' + sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' + sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' + sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://raw.githubusercontent.com/OpenVidu/openvidu/master/openvidu-test-e2e/docker/my-custom-layout/index.html' + docker.image('openvidu/openvidu-test-e2e:$DISTRO').pull() docker.image('selenium/standalone-chrome:latest').pull() docker.image('selenium/standalone-firefox:latest').pull() - docker.image('selenium/standalone-chrome:latest').withRun('-p 6666:4444 --name chrome --shm-size=1g -v /opt/openvidu:/opt/openvidu') { c -> - sh 'rm -rf /opt/openvidu/* || true' - sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' - sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' - sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://raw.githubusercontent.com/OpenVidu/openvidu/master/openvidu-test-e2e/docker/my-custom-layout/index.html' - docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { d -> - def mycontainer = docker.image('openvidu/openvidu-test-e2e:$DISTRO') - mycontainer.pull() - mycontainer.inside('--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged') { + docker.image('selenium/standalone-opera:latest').pull() - stage('Preparation') { - sh 'rm -rf ~/.m2 || true' - sh 'rm -rf openvidu || true' - sh 'rm -rf kurento-java || true' - sh 'git clone https://github.com/OpenVidu/openvidu.git' - sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' - sh(script: '''#!/bin/bash -xe - if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then - git clone https://github.com/Kurento/kurento-java.git - cd kurento-java - git checkout -f $KURENTO_JAVA_COMMIT - mvn clean install - fi - '''.stripIndent()) - sh(script: '''#!/bin/bash -xe - if $KURENTO_MEDIA_SERVER_DEV ; then - echo "Upgrading KMS to dev version" - sudo apt-get update && sudo apt-get install -y aptitude - sudo aptitude remove -y kurento-media-server - DISTRO=`lsb_release --codename | cut -f2` - sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list - sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server - fi - '''.stripIndent()) - } + docker.image('openvidu/openvidu-test-e2e:$DISTRO').inside('--name e2e -p 4200:4200 -p 4443:4443 -p 5555:5555 -u root -e MY_UID=0 -v /var/run/docker.sock:/var/run/docker.sock:rw -v /dev/shm:/dev/shm -v /opt/openvidu:/opt/openvidu --privileged') { - stage('OpenVidu Browser build') { - sh(script: '''#!/bin/bash -xe - cd openvidu - if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_BROWSER_COMMIT - fi - cd openvidu-browser - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-browser-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } + stage('Preparation') { + sh 'rm -rf ~/.m2 || true' + sh 'rm -rf openvidu || true' + sh 'rm -rf kurento-java || true' + sh 'git clone https://github.com/OpenVidu/openvidu.git' + sh 'cd openvidu && git fetch --all && git checkout $OPENVIDU_COMMIT' + sh(script: '''#!/bin/bash -xe + if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then + git clone https://github.com/Kurento/kurento-java.git + cd kurento-java + git checkout -f $KURENTO_JAVA_COMMIT + mvn clean install + fi + '''.stripIndent()) + sh(script: '''#!/bin/bash -xe + if $KURENTO_MEDIA_SERVER_DEV ; then + echo "Upgrading KMS to dev version" + sudo apt-get update && sudo apt-get install -y aptitude + sudo aptitude remove -y kurento-media-server + DISTRO=`lsb_release --codename | cut -f2` + sudo echo "deb [arch=amd64] http://ubuntu.openvidu.io/dev $DISTRO kms6" | sudo tee /etc/apt/sources.list.d/kurento.list + sudo apt-get update && sudo apt-get --yes -o Dpkg::Options::="--force-confnew" install kurento-media-server + fi + '''.stripIndent()) + } - stage('OpenVidu Node Client build') { - sh(script: '''#!/bin/bash -xe - cd openvidu - if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT - fi - cd openvidu-node-client - npm install --unsafe-perm && npm run build && npm pack - cp openvidu-node-client-*.tgz /opt/openvidu - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } + stage('OpenVidu Browser build') { + sh(script: '''#!/bin/bash -xe + cd openvidu + if [[ $OPENVIDU_BROWSER_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_BROWSER_COMMIT + fi + cd openvidu-browser + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-browser-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } - stage('OpenVidu TestApp build') { - sh(script: '''#!/bin/bash -xe - cd openvidu - if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_TESTAPP_COMMIT - fi - cd openvidu-testapp - npm install --unsafe-perm - npm install /opt/openvidu/openvidu-browser-*.tgz - npm install /opt/openvidu/openvidu-node-client-*.tgz - export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } + stage('OpenVidu Node Client build') { + sh(script: '''#!/bin/bash -xe + cd openvidu + if [[ $OPENVIDU_NODE_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_NODE_CLIENT_COMMIT + fi + cd openvidu-node-client + npm install --unsafe-perm && npm run build && npm pack + cp openvidu-node-client-*.tgz /opt/openvidu + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } - stage('OpenVidu Java Client build') { - sh(script: '''#!/bin/bash -xe - cd openvidu - if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT - fi - cd openvidu-java-client - mvn --batch-mode versions:set -DnewVersion=TEST - mvn clean compile package - mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar - cd .. - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } + stage('OpenVidu TestApp build') { + sh(script: '''#!/bin/bash -xe + cd openvidu + if [[ $OPENVIDU_TESTAPP_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_TESTAPP_COMMIT + fi + cd openvidu-testapp + npm install --unsafe-perm + npm install /opt/openvidu/openvidu-browser-*.tgz + npm install /opt/openvidu/openvidu-node-client-*.tgz + export NG_CLI_ANALYTICS="false" && ./node_modules/@angular/cli/bin/ng build --prod --output-path=/opt/openvidu/testapp + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } - stage('OpenVidu parent build') { - sh(script: '''#!/bin/bash -xe - if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then - cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) - cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION - fi - '''.stripIndent()) - sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' - sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' - } + stage('OpenVidu Java Client build') { + sh(script: '''#!/bin/bash -xe + cd openvidu + if [[ $OPENVIDU_JAVA_CLIENT_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_JAVA_CLIENT_COMMIT + fi + cd openvidu-java-client + mvn --batch-mode versions:set -DnewVersion=TEST + mvn clean compile package + mvn install:install-file -Dfile=target/openvidu-java-client-TEST.jar -DgroupId=io.openvidu -DartifactId=openvidu-java-client -Dversion=TEST -Dpackaging=jar + cd .. + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } - stage('OpenVidu Server unit tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' - } + stage('OpenVidu parent build') { + sh(script: '''#!/bin/bash -xe + if [[ $KURENTO_JAVA_COMMIT != "default" ]]; then + cd kurento-java && MVN_VERSION=$(mvn --batch-mode -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) + cd ../openvidu && mvn --batch-mode versions:set-property -Dproperty=version.kurento -DnewVersion=$MVN_VERSION + fi + '''.stripIndent()) + sh 'cd openvidu && mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST' + sh 'cd openvidu && mvn --batch-mode -DskipTests=true clean install' + } - stage('OpenVidu Server integration tests') { - sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' - } + stage('OpenVidu Server unit tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.unit.*Test test' + } - stage('OpenVidu Server build') { - sh(script: '''#!/bin/bash -xe - cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod - cd ../.. - mvn --batch-mode package - cp target/openvidu-server*.jar /opt/openvidu - '''.stripIndent()) - } + stage('OpenVidu Server integration tests') { + sh 'cd openvidu/openvidu-server && mvn --batch-mode -Dtest=io.openvidu.server.test.integration.*Test test' + } - stage ('Environment Launch') { - sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' - sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' - sh '/usr/bin/kurento-media-server &> /kms.log &' - sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' - sh(script: '''#!/bin/bash -xe - if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then - echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - else - echo "Using default openvidu-recording tag" - java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & - fi - '''.stripIndent()) - sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' - } + stage('OpenVidu Server build') { + sh(script: '''#!/bin/bash -xe + cd openvidu/openvidu-server/src/dashboard && npm install --unsafe-perm && npm install /opt/openvidu/openvidu-browser-*.tgz && export NG_CLI_ANALYTICS="false" && npm run build-prod + cd ../.. + mvn --batch-mode package + cp target/openvidu-server*.jar /opt/openvidu + '''.stripIndent()) + } - stage ('OpenVidu E2E tests') { - try { - sh(script: '''#!/bin/bash -xe - cd openvidu - if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then - git checkout -f $OPENVIDU_TESTE2E_COMMIT - fi - cd openvidu-test-browsers - mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean install - cd .. - mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST - mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST - cd openvidu-test-e2e - mvn -DskipTests=true clean install - sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test - git checkout -f $OPENVIDU_COMMIT - '''.stripIndent()) - } - finally { - junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' - archiveArtifacts artifacts: '**/openvidu-server.log' + stage ('Environment Launch') { + sh 'openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -subj "/CN=www.mydom.com/O=My Company LTD./C=US" -keyout /opt/openvidu/testapp/key.pem -out /opt/openvidu/testapp/cert.pem' + sh 'cd /opt/openvidu/testapp && http-server -S -p 4200 &> /opt/openvidu/testapp.log &' + sh '/usr/bin/kurento-media-server &> /kms.log &' + sh 'until $(curl --insecure --output /dev/null --silent http://127.0.0.1:8888/kurento); do echo "Waiting for KMS..."; sleep 1; done' + sh(script: '''#!/bin/bash -xe + if [ "$DOCKER_RECORDING_VERSION" != "default" ]; then + echo "Using custom openvidu-recording tag: $DOCKER_RECORDING_VERSION" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_RECORDING_VERSION=$DOCKER_RECORDING_VERSION -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + else + echo "Using default openvidu-recording tag" + java -jar -DDOMAIN_OR_PUBLIC_IP=172.17.0.1 -DOPENVIDU_SECRET=MY_SECRET -DHTTPS_PORT=4443 -DOPENVIDU_RECORDING=true -DOPENVIDU_RECORDING_CUSTOM_LAYOUT=/opt/openvidu/test-layouts -DOPENVIDU_WEBHOOK=true -DOPENVIDU_WEBHOOK_ENDPOINT=http://127.0.0.1:7777/webhook /opt/openvidu/openvidu-server-*.jar &> openvidu-server.log & + fi + '''.stripIndent()) + sh 'until $(curl --insecure --output /dev/null --silent --head --fail https://OPENVIDUAPP:MY_SECRET@localhost:4443/); do echo "Waiting for openvidu-server..."; sleep 2; done' + } + + docker.image('selenium/standalone-chrome:latest').withRun('-p 6666:4444 --name chrome --shm-size=1g -v /opt/openvidu:/opt/openvidu') { a -> + docker.image('selenium/standalone-firefox:latest').withRun('-p 6667:4444 --name firefox --shm-size=1g') { b -> + docker.image('selenium/standalone-opera:latest').withRun('-p 6668:4444 --name opera --shm-size=1g') { c -> + + stage ('OpenVidu E2E tests') { + try { + sh(script: '''#!/bin/bash -xe + cd openvidu + if [[ $OPENVIDU_TESTE2E_COMMIT != "default" ]]; then + git checkout -f $OPENVIDU_TESTE2E_COMMIT + fi + cd openvidu-test-browsers + mvn --batch-mode versions:set -DnewVersion=TEST && mvn clean install + cd .. + mvn --batch-mode versions:set-property -Dproperty=version.openvidu.java.client -DnewVersion=TEST + mvn --batch-mode versions:set-property -Dproperty=version.openvidu.test.browsers -DnewVersion=TEST + cd openvidu-test-e2e + mvn -DskipTests=true clean install + sudo mvn --batch-mode -Dtest=OpenViduTestAppE2eTest -DAPP_URL=https://172.17.0.1:4200/ -DOPENVIDU_URL=https://172.17.0.1:4443/ -DREMOTE_URL_CHROME=http://172.17.0.1:6666/wd/hub/ -DREMOTE_URL_FIREFOX=http://172.17.0.1:6667/wd/hub/ -DREMOTE_URL_OPERA=http://172.17.0.1:6668/wd/hub/ -DEXTERNAL_CUSTOM_LAYOUT_URL=http://172.17.0.1:5555 -DEXTERNAL_CUSTOM_LAYOUT_PARAMS=sessionId,CUSTOM_LAYOUT_SESSION,secret,MY_SECRET test + git checkout -f $OPENVIDU_COMMIT + '''.stripIndent()) + } + finally { + junit 'openvidu/openvidu-test-e2e/**/target/surefire-reports/TEST-*.xml' + archiveArtifacts artifacts: '**/openvidu-server.log' + } } + } } } } -} +} \ No newline at end of file diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java index 0127d9d5..1eea26af 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/AbstractOpenViduTestAppE2eTest.java @@ -102,6 +102,7 @@ public class AbstractOpenViduTestAppE2eTest { protected static void setupBrowserDrivers() { WebDriverManager.chromedriver().setup(); WebDriverManager.firefoxdriver().setup(); + WebDriverManager.operadriver().setup(); } protected static void cleanFoldersAndSetUpOpenViduJavaClient() { diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java new file mode 100644 index 00000000..7cac157d --- /dev/null +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java @@ -0,0 +1,101 @@ +package io.openvidu.test.e2e; + +import static org.openqa.selenium.OutputType.BASE64; + +import java.net.URL; + +import org.junit.jupiter.api.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Platform; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.remote.BrowserType; +import org.openqa.selenium.remote.DesiredCapabilities; + +import io.appium.java_client.AppiumDriver; +import io.appium.java_client.MobileElement; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.remote.MobileCapabilityType; + +public class OpenViduTestAppE2eAndroidTest { + + protected static String OPENVIDU_SECRET = "MY_SECRET"; + + @Test + void android() throws Exception { + + /* CHROME */ + // Create object of DesiredCapabilities class and specify android platform + DesiredCapabilities capabilities = DesiredCapabilities.android(); + // set the capability to execute test in chrome browser + capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, BrowserType.CHROME); + // set the capability to execute our test in Android Platform + capabilities.setCapability(MobileCapabilityType.PLATFORM, Platform.ANDROID); + // we need to define platform name + capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android"); + // Set the device name as well (you can give any name) + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "my phone"); + // set the android version as well + capabilities.setCapability(MobileCapabilityType.VERSION, "10.0"); + ChromeOptions chromeOptions = new ChromeOptions(); + // This flag avoids to grant the user media + chromeOptions.addArguments("--use-fake-ui-for-media-stream"); + // This flag fakes user media with synthetic video + chromeOptions.addArguments("--use-fake-device-for-media-stream"); + capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions); + /* CHROME */ + + /* FIREFOX */ +// DesiredCapabilities capabilities = DesiredCapabilities.android(); +// capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "MozillaFirefox"); +// capabilities.setCapability("automationName", "Gecko"); +// capabilities.setCapability("platformName", "linux"); +// +// FirefoxOptions options = new FirefoxOptions(); +// options.addPreference("androidPackage", "org.mozilla.firefox"); +// options.addPreference("androidDeviceSerial", "emulator-5554"); +//// capabilities.setCapability("moz:firefoxOptions", +//// "{\"androidPackage\":\"org.mozilla.firefox\",\"androidDeviceSerial\":\"emulator-5554\"}"); +// // capabilities.setCapability("moz:firefoxOptions", value); +// capabilities.setCapability(FirefoxOptions.FIREFOX_OPTIONS, +// "{\"androidPackage\":\"org.mozilla.firefox\",\"androidDeviceSerial\":\"emulator-5554\"}"); + /* FIREFOX */ + + // Create object of URL class and specify the appium server address + URL url = new URL("http://172.19.0.3:4723/wd/hub"); + + AppiumDriver driver = new AndroidDriver(url, capabilities); + + // Open url + driver.get("https://172.19.0.1:4200"); + + OpenViduEventManager eventManager = new OpenViduEventManager(driver, 50); + eventManager.startPolling(); + + // print the title + System.out.println("Title " + driver.getTitle()); + + WebElement urlInput = driver.findElement(By.id("openvidu-url")); + urlInput.clear(); + urlInput.sendKeys("https://172.19.0.1:4443/"); + WebElement secretInput = driver.findElement(By.id("openvidu-secret")); + secretInput.clear(); + secretInput.sendKeys(OPENVIDU_SECRET); + + driver.findElement(By.id("auto-join-checkbox")).click(); + driver.findElement(By.id("one2one-btn")).click(); + + eventManager.waitUntilEventReaches("connectionCreated", 4); + eventManager.waitUntilEventReaches("accessAllowed", 2); + eventManager.waitUntilEventReaches("streamCreated", 4); + eventManager.waitUntilEventReaches("streamPlaying", 4); + + System.out.println("data:image/png;base64," + ((TakesScreenshot) driver).getScreenshotAs(BASE64)); + + // close the browser + driver.quit(); + + } + +} diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 21a72851..066a94ee 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -117,6 +117,54 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { gracefullyLeaveParticipants(2); } + @Test + @DisplayName("One2One Firefox [Video + Audio]") + void oneToOneVideoAudioSessionFirefox() throws Exception { + + setupBrowser("firefox"); + + log.info("One2One Firefox [Video + Audio]"); + + user.getDriver().findElement(By.id("auto-join-checkbox")).click(); + user.getDriver().findElement(By.id("one2one-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("accessAllowed", 2); + user.getEventManager().waitUntilEventReaches("streamCreated", 4); + user.getEventManager().waitUntilEventReaches("streamPlaying", 4); + + final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); + Assert.assertEquals("Expected 4 videos but found " + numberOfVideos, 4, numberOfVideos); + Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() + .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + + gracefullyLeaveParticipants(2); + } + + @Test + @DisplayName("One2One Opera [Video + Audio]") + void oneToOneVideoAudioSessionOpera() throws Exception { + + setupBrowser("opera"); + + log.info("One2One Opera [Video + Audio]"); + + user.getDriver().findElement(By.id("auto-join-checkbox")).click(); + user.getDriver().findElement(By.id("one2one-btn")).click(); + + user.getEventManager().waitUntilEventReaches("connectionCreated", 4); + user.getEventManager().waitUntilEventReaches("accessAllowed", 2); + user.getEventManager().waitUntilEventReaches("streamCreated", 4); + user.getEventManager().waitUntilEventReaches("streamPlaying", 4); + + final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); + Assert.assertEquals("Expected 4 videos but found " + numberOfVideos, 4, numberOfVideos); + Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() + .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); + + gracefullyLeaveParticipants(2); + } + @Test @DisplayName("One2One [Audio]") void oneToOneAudioSession() throws Exception { @@ -299,30 +347,6 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { gracefullyLeaveParticipants(4); } - @Test - @DisplayName("One2One Firefox [Video + Audio]") - void oneToOneVideoAudioSessionFirefox() throws Exception { - - setupBrowser("firefox"); - - log.info("One2One Firefox [Video + Audio]"); - - user.getDriver().findElement(By.id("auto-join-checkbox")).click(); - user.getDriver().findElement(By.id("one2one-btn")).click(); - - user.getEventManager().waitUntilEventReaches("connectionCreated", 4); - user.getEventManager().waitUntilEventReaches("accessAllowed", 2); - user.getEventManager().waitUntilEventReaches("streamCreated", 4); - user.getEventManager().waitUntilEventReaches("streamPlaying", 4); - - final int numberOfVideos = user.getDriver().findElements(By.tagName("video")).size(); - Assert.assertEquals("Expected 4 videos but found " + numberOfVideos, 4, numberOfVideos); - Assert.assertTrue("Videos were expected to have audio and video tracks", user.getEventManager() - .assertMediaTracks(user.getDriver().findElements(By.tagName("video")), true, true)); - - gracefullyLeaveParticipants(2); - } - @Test @DisplayName("Cross-Browser test") void crossBrowserTest() throws Exception { From 5c8779b1ff1b487ccc6eb2fb83688a65862b1dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Fuente=20P=C3=A9rez?= Date: Sat, 14 Nov 2020 22:56:31 +0100 Subject: [PATCH 291/435] Delete OpenViduTestAppE2eAndroidTest.java --- .../e2e/OpenViduTestAppE2eAndroidTest.java | 101 ------------------ 1 file changed, 101 deletions(-) delete mode 100644 openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java deleted file mode 100644 index 7cac157d..00000000 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eAndroidTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package io.openvidu.test.e2e; - -import static org.openqa.selenium.OutputType.BASE64; - -import java.net.URL; - -import org.junit.jupiter.api.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Platform; -import org.openqa.selenium.TakesScreenshot; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.remote.BrowserType; -import org.openqa.selenium.remote.DesiredCapabilities; - -import io.appium.java_client.AppiumDriver; -import io.appium.java_client.MobileElement; -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.remote.MobileCapabilityType; - -public class OpenViduTestAppE2eAndroidTest { - - protected static String OPENVIDU_SECRET = "MY_SECRET"; - - @Test - void android() throws Exception { - - /* CHROME */ - // Create object of DesiredCapabilities class and specify android platform - DesiredCapabilities capabilities = DesiredCapabilities.android(); - // set the capability to execute test in chrome browser - capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, BrowserType.CHROME); - // set the capability to execute our test in Android Platform - capabilities.setCapability(MobileCapabilityType.PLATFORM, Platform.ANDROID); - // we need to define platform name - capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android"); - // Set the device name as well (you can give any name) - capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "my phone"); - // set the android version as well - capabilities.setCapability(MobileCapabilityType.VERSION, "10.0"); - ChromeOptions chromeOptions = new ChromeOptions(); - // This flag avoids to grant the user media - chromeOptions.addArguments("--use-fake-ui-for-media-stream"); - // This flag fakes user media with synthetic video - chromeOptions.addArguments("--use-fake-device-for-media-stream"); - capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions); - /* CHROME */ - - /* FIREFOX */ -// DesiredCapabilities capabilities = DesiredCapabilities.android(); -// capabilities.setCapability(MobileCapabilityType.BROWSER_NAME, "MozillaFirefox"); -// capabilities.setCapability("automationName", "Gecko"); -// capabilities.setCapability("platformName", "linux"); -// -// FirefoxOptions options = new FirefoxOptions(); -// options.addPreference("androidPackage", "org.mozilla.firefox"); -// options.addPreference("androidDeviceSerial", "emulator-5554"); -//// capabilities.setCapability("moz:firefoxOptions", -//// "{\"androidPackage\":\"org.mozilla.firefox\",\"androidDeviceSerial\":\"emulator-5554\"}"); -// // capabilities.setCapability("moz:firefoxOptions", value); -// capabilities.setCapability(FirefoxOptions.FIREFOX_OPTIONS, -// "{\"androidPackage\":\"org.mozilla.firefox\",\"androidDeviceSerial\":\"emulator-5554\"}"); - /* FIREFOX */ - - // Create object of URL class and specify the appium server address - URL url = new URL("http://172.19.0.3:4723/wd/hub"); - - AppiumDriver driver = new AndroidDriver(url, capabilities); - - // Open url - driver.get("https://172.19.0.1:4200"); - - OpenViduEventManager eventManager = new OpenViduEventManager(driver, 50); - eventManager.startPolling(); - - // print the title - System.out.println("Title " + driver.getTitle()); - - WebElement urlInput = driver.findElement(By.id("openvidu-url")); - urlInput.clear(); - urlInput.sendKeys("https://172.19.0.1:4443/"); - WebElement secretInput = driver.findElement(By.id("openvidu-secret")); - secretInput.clear(); - secretInput.sendKeys(OPENVIDU_SECRET); - - driver.findElement(By.id("auto-join-checkbox")).click(); - driver.findElement(By.id("one2one-btn")).click(); - - eventManager.waitUntilEventReaches("connectionCreated", 4); - eventManager.waitUntilEventReaches("accessAllowed", 2); - eventManager.waitUntilEventReaches("streamCreated", 4); - eventManager.waitUntilEventReaches("streamPlaying", 4); - - System.out.println("data:image/png;base64," + ((TakesScreenshot) driver).getScreenshotAs(BASE64)); - - // close the browser - driver.quit(); - - } - -} From ce204c661db59364b5ed57cf6b0dbe41b22e0421 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sat, 14 Nov 2020 23:27:42 +0100 Subject: [PATCH 292/435] openvidu-test-browsers: clean pom dependencies. Update browser users --- openvidu-test-browsers/pom.xml | 12 +----------- .../io/openvidu/test/browsers/FirefoxUser.java | 3 ++- .../io/openvidu/test/browsers/OperaUser.java | 17 ++++++++--------- openvidu-test-e2e/pom.xml | 14 +------------- pom.xml | 1 + 5 files changed, 13 insertions(+), 34 deletions(-) diff --git a/openvidu-test-browsers/pom.xml b/openvidu-test-browsers/pom.xml index f3dc1b1a..a398970a 100644 --- a/openvidu-test-browsers/pom.xml +++ b/openvidu-test-browsers/pom.xml @@ -77,16 +77,6 @@ selenium-java ${version.selenium} - - org.seleniumhq.selenium - selenium-chrome-driver - ${version.selenium} - - - org.seleniumhq.selenium - selenium-firefox-driver - ${version.selenium} - com.google.code.gson gson @@ -100,7 +90,7 @@ junit junit - 4.13.1 + ${version.junit} test diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java index 6c3b39b2..7048077a 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/FirefoxUser.java @@ -22,6 +22,7 @@ import java.net.URL; import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; import org.openqa.selenium.firefox.FirefoxProfile; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; @@ -54,7 +55,7 @@ public class FirefoxUser extends BrowserUser { } } else { log.info("Using local web driver"); - this.driver = new FirefoxDriver(capabilities); + this.driver = new FirefoxDriver(new FirefoxOptions(capabilities)); } this.configureDriver(); diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java index 0de43097..eb56e400 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/OperaUser.java @@ -4,10 +4,8 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.TimeUnit; -import org.openqa.selenium.UnexpectedAlertBehaviour; import org.openqa.selenium.opera.OperaDriver; import org.openqa.selenium.opera.OperaOptions; -import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; @@ -16,27 +14,28 @@ public class OperaUser extends BrowserUser { public OperaUser(String userName, int timeOfWaitInSeconds) { super(userName, timeOfWaitInSeconds); - OperaOptions options = new OperaOptions(); - options.setBinary("/usr/bin/opera"); DesiredCapabilities capabilities = DesiredCapabilities.operaBlink(); capabilities.setAcceptInsecureCerts(true); - capabilities.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE); - + OperaOptions options = new OperaOptions(); + // This flag avoids to grant the user media options.addArguments("--use-fake-ui-for-media-stream"); + // This flag fakes user media with synthetic video options.addArguments("--use-fake-device-for-media-stream"); - capabilities.setCapability(OperaOptions.CAPABILITY, options); + // This flag selects the entire screen as video source when screen sharing + options.addArguments("--auto-select-desktop-capture-source=Entire screen"); + options.merge(capabilities); String REMOTE_URL = System.getProperty("REMOTE_URL_OPERA"); if (REMOTE_URL != null) { log.info("Using URL {} to connect to remote web driver", REMOTE_URL); try { - this.driver = new RemoteWebDriver(new URL(REMOTE_URL), capabilities); + this.driver = new RemoteWebDriver(new URL(REMOTE_URL), options); } catch (MalformedURLException e) { e.printStackTrace(); } } else { log.info("Using local web driver"); - this.driver = new OperaDriver(capabilities); + this.driver = new OperaDriver(options); } this.driver.manage().timeouts().setScriptTimeout(this.timeOfWaitInSeconds, TimeUnit.SECONDS); diff --git a/openvidu-test-e2e/pom.xml b/openvidu-test-e2e/pom.xml index f2eabf8c..3c74d227 100644 --- a/openvidu-test-e2e/pom.xml +++ b/openvidu-test-e2e/pom.xml @@ -91,18 +91,6 @@ ${version.selenium} test - - org.seleniumhq.selenium - selenium-chrome-driver - ${version.selenium} - test - - - org.seleniumhq.selenium - selenium-firefox-driver - ${version.selenium} - test - org.seleniumhq.selenium selenium-api @@ -123,7 +111,7 @@ org.jcodec jcodec-javase - 0.2.3 + ${version.jcodec} test diff --git a/pom.xml b/pom.xml index ed5de35f..e3c536da 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,7 @@ 1.7.30 2.8.6 1.4.9 + 0.2.5 4.2.2 From e8dd9bd8f4c739a83f26d9d9f6b59393e17337eb Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sun, 15 Nov 2020 01:15:52 +0100 Subject: [PATCH 293/435] openvidu-server: signalSent event --- .../io/openvidu/server/cdr/CDREventName.java | 2 +- .../openvidu/server/cdr/CDREventSignal.java | 52 ++++++++++++++++++ .../openvidu/server/cdr/CallDetailRecord.java | 55 +++---------------- .../server/core/SessionEventsHandler.java | 19 +++++-- .../openvidu/server/core/SessionManager.java | 4 +- .../src/main/resources/application.properties | 2 +- openvidu-test-e2e/jenkins/Jenkinsfile | 2 + .../test/e2e/OpenViduTestAppE2eTest.java | 46 +++++++++++++++- 8 files changed, 126 insertions(+), 56 deletions(-) create mode 100644 openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventSignal.java diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventName.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventName.java index 2144b588..19b515ee 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventName.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventName.java @@ -21,6 +21,6 @@ public enum CDREventName { sessionCreated, sessionDestroyed, participantJoined, participantLeft, webrtcConnectionCreated, webrtcConnectionDestroyed, recordingStarted, recordingStopped, recordingStatusChanged, filterEventDispatched, - mediaNodeStatusChanged, autoscaling + signalSent, mediaNodeStatusChanged, autoscaling } diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventSignal.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventSignal.java new file mode 100644 index 00000000..9f3d232d --- /dev/null +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CDREventSignal.java @@ -0,0 +1,52 @@ +/* + * (C) Copyright 2017-2020 OpenVidu (https://openvidu.io) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.openvidu.server.cdr; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; + +public class CDREventSignal extends CDREvent { + + private String from; + private String[] to; + private String type; + private String data; + + public CDREventSignal(String sessionId, String from, String[] to, String type, String data) { + super(CDREventName.signalSent, sessionId, System.currentTimeMillis()); + this.from = from; + this.to = to; + this.type = type; + this.data = data; + } + + @Override + public JsonObject toJson() { + JsonObject json = super.toJson(); + json.addProperty("from", this.from); + JsonArray toArray = new JsonArray(); + for (String id : this.to) { + toArray.add(id); + } + json.add("to", toArray); + json.addProperty("type", this.type); + json.addProperty("data", this.data); + return json; + } + +} diff --git a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java index 9228d8fd..06df7084 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java +++ b/openvidu-server/src/main/java/io/openvidu/server/cdr/CallDetailRecord.java @@ -42,52 +42,8 @@ import io.openvidu.server.summary.SessionSummary; import io.openvidu.server.webhook.CDRLoggerWebhook; /** - * CDR logger to register all information of a Session. - * Enabled by property 'OPENVIDU_CDR=true' - * - * - 'sessionCreated': {sessionId, timestamp} - * - 'sessionDestroyed': {sessionId, timestamp, startTime, duration, reason} - * - 'participantJoined': {sessionId, timestamp, participantId, location, platform} - * - 'participantLeft': {sessionId, timestamp, participantId, startTime, duration, reason} - * - 'webrtcConnectionCreated' {sessionId, timestamp, participantId, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate]} - * - 'webrtcConnectionDestroyed' {sessionId, timestamp, participantId, startTime, duration, connection, [receivingFrom], audioEnabled, videoEnabled, [videoSource], [videoFramerate], reason} - * - 'recordingStarted' {sessionId, timestamp, id, name, hasAudio, hasVideo, resolution, recordingLayout, size} - * - 'recordingStopped' {sessionId, timestamp, id, name, hasAudio, hasVideo, resolution, recordingLayout, size} - * - 'recordingStatusChanged' {sessionId, timestamp, id, name, hasAudio, hasVideo, resolution, recordingLayout, size, status} - * - 'filterEventDispatched' {sessionId, timestamp, participantId, streamId, filterType, eventType, data} - * - * PROPERTIES VALUES: - * - * - sessionId: string - * - timestamp: number - * - startTime: number - * - duration: number - * - participantId: string - * - connection: "INBOUND", "OUTBOUND" - * - receivingFrom: string - * - audioEnabled: boolean - * - videoEnabled: boolean - * - videoSource: "CAMERA", "SCREEN", "CUSTOM", "IPCAM" - * - videoFramerate: number - * - videoDimensions: string - * - id: string - * - name: string - * - hasAudio: boolean - * - hasVideo: boolean - * - resolution string - * - recordingLayout: string - * - size: number - * - status: string - * - webrtcConnectionDestroyed.reason: "unsubscribe", "unpublish", "disconnect", "networkDisconnect", "mediaServerDisconnect", "openviduServerStopped" - * - participantLeft.reason: "unsubscribe", "unpublish", "disconnect", "networkDisconnect", "mediaServerDisconnect", "openviduServerStopped" - * - sessionDestroyed.reason: "lastParticipantLeft", "mediaServerDisconnect", "openviduServerStopped" - * - recordingStopped.reason: "recordingStoppedByServer", "lastParticipantLeft", "sessionClosedByServer", "automaticStop", "mediaServerDisconnect", "openviduServerStopped" - * - * [OPTIONAL_PROPERTIES]: - * - receivingFrom: only if connection = "INBOUND" - * - videoSource: only if videoEnabled = true - * - videoFramerate: only if videoEnabled = true - * - videoDimensions: only if videoEnabled = true + * CDR logger to register all information of a Session. Enabled by property + * 'OPENVIDU_CDR=true' * * @author Pablo Fuente (pablofuenteperez@gmail.com) */ @@ -228,6 +184,13 @@ public class CallDetailRecord { this.log(new CDREventFilterEvent(sessionId, participantId, streamId, filterType, event)); } + public void recordSignalSent(String sessionId, String from, String[] to, String type, String data) { + if (from != null) { + type = type.replaceFirst("^signal:", ""); + } + this.log(new CDREventSignal(sessionId, from, to, type, data)); + } + protected void log(CDREvent event) { this.loggers.forEach(logger -> { diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java index 70f1fa6d..989df39c 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java @@ -321,7 +321,7 @@ public class SessionEventsHandler { } public void onSendMessage(Participant participant, JsonObject message, Set participants, - Integer transactionId, OpenViduException error) { + String sessionId, Integer transactionId, OpenViduException error) { boolean isRpcCall = transactionId != null; if (isRpcCall) { @@ -332,16 +332,22 @@ public class SessionEventsHandler { } } + String from = null; + String type = null; + String data = null; + JsonObject params = new JsonObject(); if (message.has("data")) { - params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_DATA_PARAM, message.get("data").getAsString()); + data = message.get("data").getAsString(); + params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_DATA_PARAM, data); } if (message.has("type")) { - params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_TYPE_PARAM, message.get("type").getAsString()); + type = message.get("type").getAsString(); + params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_TYPE_PARAM, type); } if (participant != null) { - params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_FROM_PARAM, - participant.getParticipantPublicId()); + from = participant.getParticipantPublicId(); + params.addProperty(ProtocolElements.PARTICIPANTSENDMESSAGE_FROM_PARAM, from); } Set toSet = new HashSet(); @@ -360,6 +366,7 @@ public class SessionEventsHandler { if (toSet.isEmpty()) { for (Participant p : participants) { + toSet.add(p.getParticipantPublicId()); rpcNotificationService.sendNotification(p.getParticipantPrivateId(), ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD, params); } @@ -382,6 +389,8 @@ public class SessionEventsHandler { if (isRpcCall) { rpcNotificationService.sendResponse(participant.getParticipantPrivateId(), transactionId, new JsonObject()); } + + CDR.recordSignalSent(sessionId, from, toSet.toArray(new String[toSet.size()]), type, data); } public void onStreamPropertyChanged(Participant participant, Integer transactionId, Set participants, diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java index 0bcc6155..7e066dbc 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionManager.java @@ -116,7 +116,7 @@ public abstract class SessionManager { public void sendMessage(String message, String sessionId) { try { JsonObject messageJson = JsonParser.parseString(message).getAsJsonObject(); - sessionEventsHandler.onSendMessage(null, messageJson, getParticipants(sessionId), null, null); + sessionEventsHandler.onSendMessage(null, messageJson, getParticipants(sessionId), sessionId, null, null); } catch (JsonSyntaxException | IllegalStateException e) { throw new OpenViduException(Code.SIGNAL_FORMAT_INVALID_ERROR_CODE, "Provided signal object '" + message + "' has not a valid JSON format"); @@ -127,7 +127,7 @@ public abstract class SessionManager { try { JsonObject messageJson = JsonParser.parseString(message).getAsJsonObject(); sessionEventsHandler.onSendMessage(participant, messageJson, getParticipants(participant.getSessionId()), - transactionId, null); + participant.getSessionId(), transactionId, null); } catch (JsonSyntaxException | IllegalStateException e) { throw new OpenViduException(Code.SIGNAL_FORMAT_INVALID_ERROR_CODE, "Provided signal object '" + message + "' has not a valid JSON format"); diff --git a/openvidu-server/src/main/resources/application.properties b/openvidu-server/src/main/resources/application.properties index 45a69b5c..917f6324 100644 --- a/openvidu-server/src/main/resources/application.properties +++ b/openvidu-server/src/main/resources/application.properties @@ -24,7 +24,7 @@ OPENVIDU_CDR_PATH=/opt/openvidu/cdr OPENVIDU_WEBHOOK=false OPENVIDU_WEBHOOK_ENDPOINT= OPENVIDU_WEBHOOK_HEADERS=[] -OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined","participantLeft","webrtcConnectionCreated","webrtcConnectionDestroyed","recordingStatusChanged","filterEventDispatched","mediaNodeStatusChanged","autoscaling"] +OPENVIDU_WEBHOOK_EVENTS=["sessionCreated","sessionDestroyed","participantJoined","participantLeft","webrtcConnectionCreated","webrtcConnectionDestroyed","recordingStatusChanged","filterEventDispatched","signalSent","mediaNodeStatusChanged","autoscaling"] OPENVIDU_RECORDING=false OPENVIDU_RECORDING_DEBUG=false diff --git a/openvidu-test-e2e/jenkins/Jenkinsfile b/openvidu-test-e2e/jenkins/Jenkinsfile index d0c9b071..e722c6e6 100644 --- a/openvidu-test-e2e/jenkins/Jenkinsfile +++ b/openvidu-test-e2e/jenkins/Jenkinsfile @@ -1,9 +1,11 @@ node('container') { + sh 'docker rm -f e2e chrome firefox opera || true' sh 'rm -rf /opt/openvidu/* || true' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/barcode.y4m -P /opt/openvidu' sh 'wget https://github.com/OpenVidu/openvidu/raw/master/openvidu-test-e2e/docker/fakeaudio.wav -P /opt/openvidu' sh 'wget --directory-prefix=/opt/openvidu/test-layouts/layout1 https://raw.githubusercontent.com/OpenVidu/openvidu/master/openvidu-test-e2e/docker/my-custom-layout/index.html' + docker.image('openvidu/openvidu-test-e2e:$DISTRO').pull() docker.image('selenium/standalone-chrome:latest').pull() docker.image('selenium/standalone-firefox:latest').pull() diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index 066a94ee..00e5b417 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -48,6 +48,7 @@ import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions; import org.springframework.test.context.junit.jupiter.SpringExtension; +import com.google.gson.JsonArray; import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -3217,6 +3218,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { event = CustomWebhook.waitForEvent("webrtcConnectionCreated", 2); Assert.assertEquals("Wrong number of properties in event 'webrtcConnectionCreated'", 10 + 1, event.keySet().size()); + String connectionId1 = event.get("participantId").getAsString(); event = CustomWebhook.waitForEvent("recordingStatusChanged", 10); Assert.assertEquals("Wrong number of properties in event 'recordingStatusChanged'", 11 + 1, @@ -3258,11 +3260,53 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest { user.getDriver().findElement(By.id("add-user-btn")).click(); user.getDriver().findElement(By.cssSelector("#openvidu-instance-1 .join-btn")).click(); - CustomWebhook.waitForEvent("participantJoined", 2); + event = CustomWebhook.waitForEvent("participantJoined", 2); CustomWebhook.waitForEvent("webrtcConnectionCreated", 2); CustomWebhook.waitForEvent("webrtcConnectionCreated", 2); CustomWebhook.waitForEvent("webrtcConnectionCreated", 2); + String connectionId2 = event.get("participantId").getAsString(); + + // signalSent from client + long timestamp = System.currentTimeMillis(); + user.getDriver().findElement(By.cssSelector(("#openvidu-instance-0 .message-btn"))).click(); + user.getEventManager().waitUntilEventReaches("signal:chat", 2); + event = CustomWebhook.waitForEvent("signalSent", 1); + Assert.assertEquals("Wrong number of properties in event 'signalSent'", 6 + 1, event.keySet().size()); + Assert.assertEquals("Wrong sessionId in webhook event", "TestSession", + event.get("sessionId").getAsString()); + Assert.assertTrue("Wrong timestamp in webhook event", event.get("timestamp").getAsLong() > timestamp); + Assert.assertEquals("Wrong from in webhook event", connectionId1, event.get("from").getAsString()); + Assert.assertEquals("Wrong type in webhook event", "chat", event.get("type").getAsString()); + Assert.assertTrue("Wrong data in webhook event", !event.get("data").getAsString().isEmpty()); + Assert.assertEquals("Wrong event name in webhook event", "signalSent", event.get("event").getAsString()); + JsonArray toArray = event.get("to").getAsJsonArray(); + Assert.assertEquals("Wrong to array size", 2, toArray.size()); + Assert.assertTrue("Wrong to array content in webhook event", + toArray.contains(JsonParser.parseString(connectionId1))); + Assert.assertTrue("Wrong to array content in webhook event", + toArray.contains(JsonParser.parseString(connectionId2))); + + // signalSent from server + CustomHttpClient restClient = new CustomHttpClient(OPENVIDU_URL, "OPENVIDUAPP", OPENVIDU_SECRET); + restClient.rest(HttpMethod.POST, "/openvidu/api/signal", + "{'session':'TestSession','type':'chat','to':['" + connectionId1 + "'],'data':'SERVER_DATA'}", + HttpStatus.SC_OK); + user.getEventManager().waitUntilEventReaches("signal:chat", 3); + event = CustomWebhook.waitForEvent("signalSent", 1); + Assert.assertEquals("Wrong number of properties in event 'signalSent'", 6 + 1, event.keySet().size()); + Assert.assertEquals("Wrong sessionId in webhook event", "TestSession", + event.get("sessionId").getAsString()); + Assert.assertTrue("Wrong timestamp in webhook event", event.get("timestamp").getAsLong() > timestamp); + Assert.assertTrue("Wrong from in webhook event", event.get("from").isJsonNull()); + Assert.assertEquals("Wrong type in webhook event", "chat", event.get("type").getAsString()); + Assert.assertEquals("Wrong data in webhook event", "SERVER_DATA", event.get("data").getAsString()); + Assert.assertEquals("Wrong event name in webhook event", "signalSent", event.get("event").getAsString()); + toArray = event.get("to").getAsJsonArray(); + Assert.assertEquals("Wrong to array size", 1, toArray.size()); + Assert.assertTrue("Wrong to array content in webhook event", + toArray.contains(JsonParser.parseString(connectionId1))); + user.getDriver().findElement(By.id("session-api-btn-0")).click(); Thread.sleep(1000); user.getDriver().findElement(By.id("close-session-btn")).click(); From 827a5d9428ad34ae7187133a7fbb44158d932d58 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sun, 15 Nov 2020 01:18:10 +0100 Subject: [PATCH 294/435] openvidu-server: remove openvidu-browser 2.15.0 compatibility --- .../io/openvidu/server/core/TokenGenerator.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java index 8ef7dbdc..35192b52 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java +++ b/openvidu-server/src/main/java/io/openvidu/server/core/TokenGenerator.java @@ -51,26 +51,9 @@ public class TokenGenerator { if (this.openviduConfig.isTurnadminAvailable()) { turnCredentials = coturnCredentialsService.createUser(); } - - // REMOVE AFTER RELEASE 2.16.0 - token = compatibilityWithOpenViduBrowser2150(token, role, turnCredentials); - // REMOVE AFTER RELEASE 2.16.0 - ConnectionProperties connectionProperties = new ConnectionProperties.Builder().type(ConnectionType.WEBRTC) .data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build(); return new Token(token, sessionId, connectionProperties, turnCredentials); } - // REMOVE AFTER RELEASE 2.16.0 - private String compatibilityWithOpenViduBrowser2150(String token, OpenViduRole role, - TurnCredentials turnCredentials) { - token += "&role=" + role.name(); - token += "&version=" + openviduBuildConfig.getOpenViduServerVersion(); - if (turnCredentials != null) { - token += "&coturnIp=" + openviduConfig.getCoturnIp(); - token += "&turnUsername=" + turnCredentials.getUsername(); - token += "&turnCredential=" + turnCredentials.getCredential(); - } - return token; - } } From ababab7942539941d6fe3aa8a2109d95505ca72f Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Sun, 15 Nov 2020 22:12:07 +0100 Subject: [PATCH 295/435] Java 11 update --- openvidu-test-browsers/pom.xml | 4 ++-- openvidu-test-e2e/pom.xml | 4 ++-- pom.xml | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openvidu-test-browsers/pom.xml b/openvidu-test-browsers/pom.xml index a398970a..c29fb9b5 100644 --- a/openvidu-test-browsers/pom.xml +++ b/openvidu-test-browsers/pom.xml @@ -47,8 +47,8 @@ - - 1.8 + + 11 ${java.version} ${java.version} diff --git a/openvidu-test-e2e/pom.xml b/openvidu-test-e2e/pom.xml index 3c74d227..61a79507 100644 --- a/openvidu-test-e2e/pom.xml +++ b/openvidu-test-e2e/pom.xml @@ -47,8 +47,8 @@ - - 1.8 + + 11 ${java.version} ${java.version} diff --git a/pom.xml b/pom.xml index e3c536da..df5c4195 100644 --- a/pom.xml +++ b/pom.xml @@ -75,8 +75,8 @@ 3.0.0 3.2.0 - 1.8 - 1.8 + 11 + 11 https://github.com/OpenVidu/openvidu git@github.com:OpenVidu/openvidu.git @@ -92,8 +92,8 @@ UTF-8 - 1.8 - 1.8 + 11 + 11