Merge pull request #7 from OpenVidu/2.0.0

Release 2.0.0
This commit is contained in:
Pablo Fuente Pérez 2018-05-11 11:00:24 +02:00 committed by GitHub
commit 08cf531dfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 93891 additions and 137412 deletions

View File

@ -42,7 +42,7 @@ RUN set -x \
&& chmod -R go=u,go-w /home/ngrok \
&& chmod go= /home/ngrok
EXPOSE 8443
EXPOSE 4443
EXPOSE 4040
# Exec supervisord

View File

@ -1,5 +1,5 @@
web_addr: 0.0.0.0:4040
tunnels:
app:
addr: 8443
addr: 4443
proto: http

View File

@ -9,7 +9,7 @@ command=/bin/bash /kms.sh
redirect_stderr=true
[program:openvidu-server]
command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=8443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar"
command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=4443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar"
redirect_stderr=true
[program:ngrok]

View File

@ -9,12 +9,12 @@ var numOfVideos = 0; // Keeps track of the number of videos that are being show
// Check if the URL already has a room
window.addEventListener('load', function () {
sessionId = window.location.hash; // For 'https://myurl/#roomId', sessionId would be '#roomId'
sessionId = window.location.hash.slice(1); // For 'https://myurl/#roomId', sessionId would be 'roomId'
if (sessionId) {
// The URL has a session id. Join the room right away
console.log("Joining to room " + sessionId);
showSessionHideJoin();
joinRoom(sessionId);
joinRoom();
} else {
// The URL has not a session id. Show welcome page
showJoinHideSession();
@ -27,26 +27,23 @@ window.addEventListener('beforeunload', function () {
});
function joinRoom(sessionId) {
function joinRoom() {
if (!sessionId) {
// If the user is joining to a new room
sessionId = '#' + randomString();
sessionId = randomString();
}
// As insecure OpenVidu, the user's token can be a random string
var userId = randomString();
// --- 1) Get an OpenVidu object and init a session with a sessionId ---
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
// We will join the video-call "sessionId". As there's no server, this parameter must start with the URL of
// OpenVidu Server (with secure websocket protocol: "wss://") and must include the OpenVidu secret at the end
session = OV.initSession("wss://" + location.hostname + ":8443/" + sessionId + "?secret=MY_SECRET");
// --- 2) Init a session ---
session = OV.initSession();
// --- 2) Specify the actions when events take place ---
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
@ -67,58 +64,66 @@ function joinRoom(sessionId) {
});
// --- 3) Connect to the session ---
// --- 4) Connect to the session with a valid user token ---
// Remember 'userId' param (usually called 'token') is irrelevant when using the insecure version of OpenVidu
session.connect(userId, function (error) {
// 'getToken' method is simulating what your server-side should do.
// 'token' parameter should be retrieved and returned by your own backend
getToken(sessionId).then(token => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// Connect with the token
session.connect(token)
.then(() => {
// --- 4) Get your own camera stream with the desired resolution ---
// --- 5) Set page layout for active call ---
publisher = OV.initPublisher('publisher', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
// Update the URL shown in the browser's navigation bar to show the session id
var path = (location.pathname.slice(-1) == "/" ? location.pathname : location.pathname + "/");
window.history.pushState("", "", path + '#' + sessionId);
// Auxiliary methods to show the session's view
showSessionHideJoin();
initializeSessionView();
// --- 6) Get your own camera stream with the desired properties ---
publisher = OV.initPublisher('publisher', {
audioSource: undefined, // The source of audio. If undefined default audio input
videoSource: undefined, // The source of video. If undefined default video input
publishAudio: true, // Whether to start publishing with your audio unmuted or not
publishVideo: true, // Whether to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in target element 'video-container'
mirror: true // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
// When your own video is added to DOM, update the page layout to fit it
numOfVideos++;
updateLayout();
$(event.element).prop('muted', true); // Mute local video to avoid feedback
});
// --- 8) Publish your stream ---
session.publish(publisher);
})
.catch(error => {
console.log('There was an error connecting to the session:', error.code, error.message);
});
publisher.on('videoElementCreated', function (event) {
// When your own video is added to DOM, update the page layout to fit it
numOfVideos++;
updateLayout();
$(event.element).prop('muted', true); // Mute local video
});
// --- 5) Publish your stream ---
session.publish(publisher);
} else {
console.log('There was an error connecting to the session:', error.code, error.message);
}
});
// Update the URL shown in the browser's navigation bar to show the session id
var pathname = (location.pathname.slice(-1) === "/" ? location.pathname : location.pathname+"/");
window.history.pushState("", "", pathname + sessionId);
// Auxiliary methods to show the session's view
showSessionHideJoin();
initializeSessionView();
return false;
}
function leaveRoom() {
// --- 6) Leave the session by calling 'disconnect' method over the Session object ---
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
// Back to welcome page
window.location.href = window.location.origin + window.location.pathname;
}
@ -154,8 +159,6 @@ function muteVideo() {
}
// Generate a random string for sessionId and userId
function randomString() {
return Math.random().toString(36).slice(2);
}
@ -249,4 +252,52 @@ function updateLayout() {
}
}
/* AUXILIARY METHODS */
/**
* --------------------------
* SERVER-SIDE RESPONSABILITY
* --------------------------
* These methods retrieve the mandatory user token from OpenVidu Server.
* This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using
* the API REST, openvidu-java-client or openvidu-node-client):
* 1) Initialize a session in OpenVidu Server (POST /api/sessions)
* 2) Generate a token in OpenVidu Server (POST /api/tokens)
* 3) The token must be consumed in Session.connect() method
*/
function getToken(mySessionId) {
return createSession(mySessionId).then(sId => createToken(sId));
}
function createSession(sId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/sessions",
data: JSON.stringify({ customSessionId: sId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.id),
error: error => error.status === 409 ? resolve(sId) : reject(error)
});
});
}
function createToken(sId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/tokens",
data: JSON.stringify({ session: sId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.token),
error: error => reject(error)
});
});
}

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="resources/images/favicon.ico" type="image/x-icon">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
</head>
@ -50,11 +47,13 @@
</div>
</form>
<button id="mute-video" type="button" class="btn btn-primary float-right mute-button" onclick="muteVideo()">
<span class="glyphicon glyphicon-facetime-video"></span> <span class="hidden-xs">Video</span>
</button>
<span class="glyphicon glyphicon-facetime-video"></span>
<span class="hidden-xs">Video</span>
</button>
<button id="mute-audio" type="button" class="btn btn-primary float-right mute-button" onclick="muteAudio()">
<span class="glyphicon glyphicon-volume-up"></span> <span class="hidden-xs">Audio</span>
</button>
<span class="glyphicon glyphicon-volume-up"></span>
<span class="hidden-xs">Audio</span>
</button>
</div>
</div>
</nav>
@ -63,10 +62,10 @@
<!-- Join page template -->
<div id="join" class="row no-margin" hidden>
<div id="img-div"><img src="resources/images/openvidu_grey_bg_transp_cropped.png" /></div>
<div id="img-div"><img src="resources/images/openvidu_grey_bg_transp_cropped.png"/></div>
<div id="join-dialog" class="jumbotron vertical-center">
<h1 class="arciform">Get a room</h1>
<button type="button" class="btn btn-lg btn-success" onclick="joinRoom()">Go!</button>
<button type="button" class="btn btn-lg btn-success" onclick="joinRoom(); return false;">Go!</button>
</div>
</div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -3,41 +3,88 @@ var session;
function joinSession() {
var sessionId = document.getElementById("sessionId").value;
var mySessionId = document.getElementById("sessionId").value;
OV = new OpenVidu();
session = OV.initSession("wss://" + location.hostname + ":8443/" + sessionId + '?secret=MY_SECRET');
session = OV.initSession();
session.on('streamCreated', function (event) {
session.subscribe(event.stream, 'subscriber');
session.on("streamCreated", function (event) {
session.subscribe(event.stream, "subscriber");
});
session.connect(null, function (error) {
getToken(mySessionId).then(token => {
if (!error) {
var publisher = OV.initPublisher('publisher');
session.publish(publisher);
} else {
console.log('There was an error connecting to the session:', error.code, error.message);
}
session.connect(token)
.then(() => {
document.getElementById("session-header").innerText = mySessionId;
document.getElementById("join").style.display = "none";
document.getElementById("session").style.display = "block";
var publisher = OV.initPublisher("publisher");
session.publish(publisher);
})
.catch(error => {
console.log("There was an error connecting to the session:", error.code, error.message);
});
});
document.getElementById('session-header').innerText = sessionId;
document.getElementById('join').style.display = 'none';
document.getElementById('session').style.display = 'block';
return false;
}
function leaveSession() {
session.disconnect();
document.getElementById('join').style.display = 'block';
document.getElementById('session').style.display = 'none';
document.getElementById("join").style.display = "block";
document.getElementById("session").style.display = "none";
}
window.onbeforeunload = function () {
if (session) session.disconnect()
};
};
/**
* --------------------------
* SERVER-SIDE RESPONSABILITY
* --------------------------
* These methods retrieve the mandatory user token from OpenVidu Server.
* This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using
* the API REST, openvidu-java-client or openvidu-node-client):
* 1) Initialize a session in OpenVidu Server (POST /api/sessions)
* 2) Generate a token in OpenVidu Server (POST /api/tokens)
* 3) The token must be consumed in Session.connect() method
*/
function getToken(mySessionId) {
return createSession(mySessionId).then(sessionId => createToken(sessionId));
}
function createSession(sessionId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/sessions",
data: JSON.stringify({ customSessionId: sessionId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.id),
error: error => error.status === 409 ? resolve(sessionId) : reject(error)
});
});
}
function createToken(sessionId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/tokens",
data: JSON.stringify({ session: sessionId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.token),
error: error => reject(error)
});
});
}

View File

@ -2,15 +2,17 @@
<head>
<title>openvidu-hello-world</title>
<link rel="shortcut icon" href="resources/images/favicon.ico" type="image/x-icon">
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
</head>
<body>
<div id="join">
<h1>Join a video session</h1>
<form onsubmit="return joinSession()">
<form onsubmit="joinSession(); return false">
<p>
<label>Session:</label>
<input type="text" id="sessionId" value="SessionA" required>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,7 +7,10 @@
{
"root": "src",
"outDir": "dist",
"assets": "assets",
"assets": [
"assets",
"assets/images"
],
"index": "index.html",
"main": "main.ts",
"test": "test.ts",
@ -38,6 +41,9 @@
}
},
"defaults": {
"build": {
"showCircularDependencies": false
},
"styleExt": "css",
"prefixInterfaces": false
}

View File

@ -1,46 +1,29 @@
{
"name": "openvidu-insecure-angular",
"version": "0.0.0",
"license": "MIT",
"angular-cli": {},
"license": "Apache-2.0",
"scripts": {
"start": "ng serve",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test",
"pree2e": "webdriver-manager update",
"e2e": "protractor"
"start": "ng serve"
},
"private": true,
"dependencies": {
"@angular/common": "^2.4.0",
"@angular/compiler": "^2.4.0",
"@angular/core": "^2.4.0",
"@angular/forms": "^2.4.0",
"@angular/http": "^2.4.0",
"@angular/platform-browser": "^2.4.0",
"@angular/platform-browser-dynamic": "^2.4.0",
"@angular/router": "^3.4.0",
"core-js": "^2.4.1",
"openvidu-browser": "1.5.0",
"zone.js": "^0.7.6"
"@angular/common": "5.2.10",
"@angular/compiler": "5.2.10",
"@angular/core": "5.2.10",
"@angular/forms": "5.2.10",
"@angular/platform-browser": "5.2.10",
"@angular/platform-browser-dynamic": "5.2.10",
"core-js": "2.5.6",
"openvidu-browser": "1.9.0",
"openvidu-node-client": "1.9.0",
"zone.js": "0.8.26"
},
"devDependencies": {
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"@angular/cli": "1.0.0",
"@angular/compiler-cli": "^2.4.0",
"codelyzer": "~2.0.0",
"jasmine-core": "~2.5.2",
"jasmine-spec-reporter": "~3.2.0",
"karma": "~1.4.1",
"karma-chrome-launcher": "~2.0.0",
"karma-cli": "~1.0.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-coverage-istanbul-reporter": "^0.2.0",
"protractor": "~5.1.0",
"ts-node": "~2.0.0",
"tslint": "~4.4.2",
"typescript": "2.5.3"
"@types/node": "10.0.4",
"@angular/cli": "1.7.4",
"@angular/compiler-cli": "5.2.10",
"codelyzer": "4.3.0",
"ts-node": "6.0.3",
"tslint": "5.10.0",
"typescript": "2.7.2"
}
}
}

View File

@ -1,16 +1,16 @@
<div id="main-container" class="container">
<div *ngIf="!session" id="join">
<div id="img-div"><img src="src/assets/images/openvidu_grey_bg_transp_cropped.png" /></div>
<div id="img-div"><img src="assets/images/openvidu_grey_bg_transp_cropped.png" /></div>
<div id="join-dialog" class="jumbotron vertical-center">
<h1>Join a video session</h1>
<form class="form-group" (submit)="joinSession()">
<p>
<label>Participant</label>
<input class="form-control" type="text" id="userName" name="userName" [(ngModel)]="userName" required>
<input class="form-control" type="text" id="userName" name="userName" [(ngModel)]="myUserName" required>
</p>
<p>
<label>Session</label>
<input class="form-control" type="text" id="sessionId" name="sessionId" [(ngModel)]="sessionId" required>
<input class="form-control" type="text" id="sessionId" name="sessionId" [(ngModel)]="mySessionId" required>
</p>
<p class="text-center">
<input class="btn btn-lg btn-success" type="submit" name="commit" value="Join!">
@ -21,7 +21,7 @@
<div *ngIf="session" id="session">
<div id="session-header">
<h1 id="session-title">{{sessionId}}</h1>
<h1 id="session-title">{{mySessionId}}</h1>
<input class="btn btn-large btn-danger" type="button" id="buttonLeaveSession" (click)="leaveSession()" value="Leave session">
</div>
<div *ngIf="this.mainVideoStream" id="main-video" class="col-md-6">

View File

@ -1,12 +1,13 @@
import { OpenVidu, Session, Stream } from 'openvidu-browser';
import { Component, HostListener, Input } from '@angular/core';
import { Component, HostListener, Input, OnDestroy } from '@angular/core';
import { OpenVidu, Session, Stream, StreamEvent } from 'openvidu-browser';
import { OpenVidu as OpenViduAPI } from 'openvidu-node-client';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
export class AppComponent implements OnDestroy {
// OpenVidu objects
OV: OpenVidu;
@ -17,8 +18,8 @@ export class AppComponent {
localStream: Stream;
// Join form
sessionId: string;
userName: string;
mySessionId: string;
myUserName: string;
// Main video of the page, will be 'localStream' or one of the 'remoteStreams',
// updated by an Output event of StreamComponent children
@ -41,81 +42,81 @@ export class AppComponent {
joinSession() {
// --- 1) Get an OpenVidu object and init a session with a sessionId ---
// --- 1) Get an OpenVidu object ---
// Init OpenVidu object
this.OV = new OpenVidu();
// We will join the video-call "sessionId". As there's no server, this parameter must start with the URL of
// OpenVidu Server (with secure websocket protocol: "wss://") and must include the OpenVidu secret at the end
this.session = this.OV.initSession('wss://' + location.hostname + ':8443/' + this.sessionId + '?secret=MY_SECRET');
// --- 2) Init a session ---
this.session = this.OV.initSession();
// --- 2) Specify the actions when events take place ---
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
this.session.on('streamCreated', (event) => {
this.session.on('streamCreated', (event: StreamEvent) => {
// Add the new stream to 'remoteStreams' array
this.remoteStreams.push(event.stream);
// Subscribe to the Stream to receive it. Second parameter is an empty string
// Subscribe to the Stream to receive it. Second parameter is undefined
// so OpenVidu doesn't create an HTML video by its own
this.session.subscribe(event.stream, '');
this.session.subscribe(event.stream, undefined);
});
// On every Stream destroyed...
this.session.on('streamDestroyed', (event) => {
// Avoid OpenVidu trying to remove the HTML video element
event.preventDefault();
this.session.on('streamDestroyed', (event: StreamEvent) => {
// Remove the stream from 'remoteStreams' array
this.deleteRemoteStream(event.stream);
});
// --- 3) Connect to the session ---
// --- 4) Connect to the session with a valid user token ---
// First param irrelevant if your app has no server-side. Second param will be received by every user
// in Stream.connection.data property, which will be appended to DOM as the user's nickname
this.session.connect(null, '{"clientData": "' + this.userName + '"}', (error) => {
// 'getToken' method is simulating what your server-side should do.
// 'token' parameter should be retrieved and returned by your own backend
this.getToken().then(token => {
// If connection successful, initialize a publisher and publish to the session
if (!error) {
// First param is the token got from OpenVidu Server. Second param can be retrieved by every user on event
// 'streamCreated' (property Stream.connection.data), and will be appended to DOM as the user's nickname
this.session.connect(token, { clientData: this.myUserName })
.then(() => {
// --- 4) Get your own camera stream with the desired resolution ---
// --- 5) Get your own camera stream ---
// Both audio and video will be active. Second parameter is an empty string
// so OpenVidu doesn't create an HTML video by its own
let publisher = this.OV.initPublisher('', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
// Init a publisher passing undefined as targetElement (we don't want OpenVidu to insert a video
// element: we will manage it ourselves) and with the desired properties
let publisher = this.OV.initPublisher(undefined, {
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// Store your webcam stream in 'localStream' object
this.localStream = publisher.stream;
// Set the main video in the page to display our webcam
this.mainVideoStream = this.localStream;
// --- 6) Publish your stream ---
this.session.publish(publisher);
})
.catch(error => {
console.log('There was an error connecting to the session:', error.code, error.message);
});
// Store your webcam stream in 'localStream' object
this.localStream = publisher.stream;
// Set the main video in the page to display our webcam
this.mainVideoStream = this.localStream;
// --- 5) Publish your stream ---
this.session.publish(publisher);
} else {
console.log('There was an error connecting to the session:', error.code, error.message);
}
});
return false;
}
leaveSession() {
// --- 6) Leave the session by calling 'disconnect' method over the Session object ---
// --- 7) Leave the session by calling 'disconnect' method over the Session object ---
if (this.session) { this.session.disconnect(); };
// Empty all properties...
@ -129,8 +130,8 @@ export class AppComponent {
private generateParticipantInfo() {
// Random user nickname and sessionId
this.sessionId = 'SessionA';
this.userName = 'Participant' + Math.floor(Math.random() * 100);
this.mySessionId = 'SessionA';
this.myUserName = 'Participant' + Math.floor(Math.random() * 100);
}
private deleteRemoteStream(stream: Stream): void {
@ -144,4 +145,26 @@ export class AppComponent {
this.mainVideoStream = stream;
}
/**
* --------------------------
* SERVER-SIDE RESPONSABILITY
* --------------------------
* This method retrieve the mandatory user token from OpenVidu Server,
* in this case making use of OpenVidu Node Client.
* This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION. In this case:
* 1) Initialize a session in OpenVidu Server (OpenVidu.createSession with OpenVidu Node Client)
* 2) Generate a token in OpenVidu Server (Session.generateToken with OpenVidu Node Client)
* 3) The token must be consumed in Session.connect() method of OpenVidu Browser
*/
getToken(): Promise<string> {
let OV_NodeClient = new OpenViduAPI('https://' + location.hostname + ':4443', 'MY_SECRET');
return OV_NodeClient.createSession({ customSessionId: this.mySessionId })
.then(session_NodeClient => {
return session_NodeClient.generateToken();
});
}
}

View File

@ -1,7 +1,6 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { StreamComponent } from './stream.component';
@ -12,8 +11,7 @@ import { StreamComponent } from './stream.component';
],
imports: [
BrowserModule,
FormsModule,
HttpModule
FormsModule
],
providers: [],
bootstrap: [AppComponent]

View File

@ -1,5 +1,4 @@
import { Component, Input, Output, AfterViewInit, DoCheck, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { Stream } from 'openvidu-browser';
@Component({
@ -61,7 +60,7 @@ export class StreamComponent implements AfterViewInit, DoCheck {
return JSON.parse(this.stream.connection.data).clientData;
}
videoClicked() { // Triggers event for the parent component to update its view
videoClicked() { // Triggers event for the parent component to update its main video display
this.mainVideoStream.next(this.stream);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -3,18 +3,15 @@
<head>
<meta charset="utf-8">
<title>openvidu-insecure-angular</title>
<link rel="shortcut icon" href="favicon.ico">
<link rel="shortcut icon" href="assets/images/favicon.ico">
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1" charset="utf-8">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
</head>
@ -24,7 +21,7 @@
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/"><img class="demo-logo" src="src/assets/images/openvidu_vert_white_bg_trans_cropped.png"/> Insecure Angular</a>
<a class="navbar-brand" href="/"><img class="demo-logo" src="assets/images/openvidu_vert_white_bg_trans_cropped.png"/> Insecure Angular</a>
<a class="navbar-brand nav-icon" href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-insecure-angular" title="GitHub Repository" target="_blank"><i class="fa fa-github" aria-hidden="true"></i></a>
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-insecure-angular/" title="Documentation" target="_blank"><i class="fa fa-book" aria-hidden="true"></i></a>
</div>
@ -36,7 +33,7 @@
<footer class="footer">
<div class="container">
<div class="text-muted">OpenVidu © 2017</div>
<a href="http://www.openvidu.io/" target="_blank"><img class="openvidu-logo" src="src/assets/images/openvidu_globe_bg_transp_cropped.png"/></a>
<a href="http://www.openvidu.io/" target="_blank"><img class="openvidu-logo" src="assets/images/openvidu_globe_bg_transp_cropped.png"/></a>
</div>
</footer>

View File

@ -43,7 +43,7 @@ RUN set -x \
&& chmod go= /home/ngrok
EXPOSE 4040
EXPOSE 8443
EXPOSE 4443
# Exec supervisord
CMD ["/usr/bin/supervisord"]

View File

@ -1,5 +1,5 @@
web_addr: 0.0.0.0:4040
tunnels:
app:
addr: 8443
addr: 4443
proto: http

View File

@ -9,7 +9,7 @@ command=/bin/bash /kms.sh
redirect_stderr=true
[program:openvidu-server]
command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=8443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar"
command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=4443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar"
redirect_stderr=true
[program:ngrok]

View File

@ -6,29 +6,27 @@ var session;
function joinSession() {
var sessionId = document.getElementById("sessionId").value;
var userName = document.getElementById("userName").value;
var mySessionId = document.getElementById("sessionId").value;
var myUserName = document.getElementById("userName").value;
// --- 1) Get an OpenVidu object and init a session with a sessionId ---
// --- 1) Get an OpenVidu object ---
// Init OpenVidu object
OV = new OpenVidu();
// We will join the video-call "sessionId". As there's no server, this parameter must start with the URL of
// OpenVidu Server (with secure websocket protocol: "wss://") and must include the OpenVidu secret at the end
session = OV.initSession("wss://" + location.hostname + ":8443/" + sessionId + '?secret=MY_SECRET');
// --- 2) Init a session ---
session = OV.initSession();
// --- 2) Specify the actions when events take place ---
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', event => {
// Subscribe to the Stream to receive it. HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
subscriber.on('videoElementCreated', event => {
// Add a new <p> element for the user's nickname just below its video
appendUserData(event.element, subscriber.stream.connection);
@ -36,63 +34,70 @@ function joinSession() {
});
// On every Stream destroyed...
session.on('streamDestroyed', function (event) {
session.on('streamDestroyed', event => {
// Delete the HTML element with the user's nickname. HTML videos are automatically removed from DOM
removeUserData(event.stream.connection);
});
// --- 3) Connect to the session ---
// --- 4) Connect to the session with a valid user token ---
// First param irrelevant if your app has no server-side. Second param will be received by every user
// in Stream.connection.data property, which will be appended to DOM as the user's nickname
session.connect(null, '{"clientData": "' + userName + '"}', function (error) {
// 'getToken' method is simulating what your server-side should do.
// 'token' parameter should be retrieved and returned by your own backend
getToken(mySessionId).then(token => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// First param is the token got from OpenVidu Server. Second param can be retrieved by every user on event
// 'streamCreated' (property Stream.connection.data), and will be appended to DOM as the user's nickname
session.connect(token, { clientData: myUserName })
.then(() => {
// --- 4) Get your own camera stream with the desired resolution ---
// --- 5) Set page layout for active call ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
document.getElementById('session-title').innerText = mySessionId;
document.getElementById('join').style.display = 'none';
document.getElementById('session').style.display = 'block';
// --- 6) Get your own camera stream with the desired properties ---
var publisher = OV.initPublisher('video-container', {
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
initMainVideo(event.element, myUserName);
appendUserData(event.element, myUserName);
event.element['muted'] = true;
});
// --- 8) Publish your stream ---
session.publish(publisher);
})
.catch(error => {
console.log('There was an error connecting to the session:', error.code, error.message);
});
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
initMainVideo(event.element, userName);
appendUserData(event.element, userName);
event.element['muted'] = true;
});
// --- 5) Publish your stream ---
session.publish(publisher);
} else {
console.log('There was an error connecting to the session:', error.code, error.message);
}
});
document.getElementById('session-title').innerText = sessionId;
document.getElementById('join').style.display = 'none';
document.getElementById('session').style.display = 'block';
return false;
}
function leaveSession() {
// --- 6) Leave the session by calling 'disconnect' method over the Session object ---
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
// Removing all HTML elements with the user's nicknames.
// Removing all HTML elements with user's nicknames.
// HTML videos are automatically removed when leaving a Session
removeAllUserData();
@ -101,9 +106,6 @@ function leaveSession() {
document.getElementById('session').style.display = 'none';
}
/* OPENVIDU METHODS */
/* APPLICATION SPECIFIC METHODS */
@ -168,4 +170,52 @@ function initMainVideo(videoElement, userData) {
document.querySelector('#main-video video')['muted'] = true;
}
/* APPLICATION SPECIFIC METHODS */
/**
* --------------------------
* SERVER-SIDE RESPONSABILITY
* --------------------------
* These methods retrieve the mandatory user token from OpenVidu Server.
* This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using
* the API REST, openvidu-java-client or openvidu-node-client):
* 1) Initialize a session in OpenVidu Server (POST /api/sessions)
* 2) Generate a token in OpenVidu Server (POST /api/tokens)
* 3) The token must be consumed in Session.connect() method
*/
function getToken(mySessionId) {
return createSession(mySessionId).then(sessionId => createToken(sessionId));
}
function createSession(sessionId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/sessions",
data: JSON.stringify({ customSessionId: sessionId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.id),
error: error => error.status === 409 ? resolve(sessionId) : reject(error)
});
});
}
function createToken(sessionId) {
return new Promise((resolve, reject) => {
$.ajax({
type: "POST",
url: "https://" + location.hostname + ":4443/api/tokens",
data: JSON.stringify({ session: sessionId }),
headers: {
"Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"),
"Content-Type": "application/json"
},
success: response => resolve(response.token),
error: error => reject(error)
});
});
}

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="resources/images/favicon.ico" type="image/x-icon">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
<link rel="stylesheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
</head>
@ -38,7 +35,7 @@
<div id="img-div"><img src="resources/images/openvidu_grey_bg_transp_cropped.png" /></div>
<div id="join-dialog" class="jumbotron vertical-center">
<h1>Join a video session</h1>
<form class="form-group" onsubmit="return joinSession()">
<form class="form-group" onsubmit="joinSession(); return false">
<p>
<label>Participant</label>
<input class="form-control" type="text" id="userName" required>
@ -73,4 +70,4 @@
</body>
</html>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -15,6 +15,7 @@
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">

View File

@ -95,7 +95,7 @@
<dependency>
<groupId>io.openvidu</groupId>
<artifactId>openvidu-java-client</artifactId>
<version>1.7.0</version>
<version>2.0.0</version>
</dependency>
</dependencies>

View File

@ -63,7 +63,7 @@ public class LoginController {
}
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
@RequestMapping(value = "/logout", method = RequestMethod.POST)
public ResponseEntity<Object> logout(HttpSession session) {
System.out.println("'" + session.getAttribute("loggedUser") + "' has logged out");
session.invalidate();

View File

@ -25,22 +25,28 @@ import io.openvidu.java.client.OpenViduRole;
@RequestMapping("/api-sessions")
public class SessionController {
OpenVidu openVidu;
// OpenVidu object as entrypoint of the SDK
private OpenVidu openVidu;
// Collection to pair session names and OpenVidu Session objects
private Map<String, Session> mapSessions = new ConcurrentHashMap<>();
private Map<String, Map<String, OpenViduRole>> mapSessionIdsTokens = new ConcurrentHashMap<>();
// Collection to pair session names and tokens (the inner Map pairs tokens and role associated)
private Map<String, Map<String, OpenViduRole>> mapSessionNamesTokens = new ConcurrentHashMap<>();
// URL where our OpenVidu server is listening
private String OPENVIDU_URL;
// Secret shared with our OpenVidu server
private String SECRET;
public SessionController(@Value("${openvidu.secret}") String secret, @Value("${openvidu.url}") String openviduUrl) {
this.SECRET = secret;
this.OPENVIDU_URL = openviduUrl;
this.openVidu = new OpenVidu(OPENVIDU_URL, SECRET);
}
@RequestMapping(value = "/get-sessionid-token", method = RequestMethod.POST)
public ResponseEntity<JSONObject> getSessionIdToken(@RequestBody String sessionNameParam, HttpSession httpSession)
@RequestMapping(value = "/get-token", method = RequestMethod.POST)
public ResponseEntity<JSONObject> getToken(@RequestBody String sessionNameParam, HttpSession httpSession)
throws ParseException {
try {
@ -48,12 +54,12 @@ public class SessionController {
} catch (Exception e) {
return getErrorResponse(e);
}
System.out.println("Getting sessionId and token | {sessionName}=" + sessionNameParam);
System.out.println("Getting a token from OpenVidu Server | {sessionName}=" + sessionNameParam);
JSONObject sessionJSON = (JSONObject) new JSONParser().parse(sessionNameParam);
// The video-call to connect ("TUTORIAL")
String sessionName = (String) sessionJSON.get("session");
// The video-call to connect
String sessionName = (String) sessionJSON.get("sessionName");
// Role associated to this user
OpenViduRole role = LoginController.users.get(httpSession.getAttribute("loggedUser")).role;
@ -68,22 +74,18 @@ public class SessionController {
JSONObject responseJson = new JSONObject();
if (this.mapSessions.get(sessionName) != null) {
// Session already exists: return existing sessionId and a new token
// Session already exists
System.out.println("Existing session " + sessionName);
try {
// Get the existing sessionId from our collection with
// the sessionName param ("TUTORIAL")
String sessionId = this.mapSessions.get(sessionName).getSessionId();
// Generate a new token with the recently created tokenOptions
String token = this.mapSessions.get(sessionName).generateToken(tokenOptions);
// Update our collection storing the new token
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Prepare the response with the sessionId and the token
responseJson.put(0, sessionId);
responseJson.put(1, token);
// Prepare the response with the token
responseJson.put(0, token);
// Return the response to the client
return new ResponseEntity<>(responseJson, HttpStatus.OK);
@ -94,25 +96,22 @@ public class SessionController {
}
} else {
// New session: return a new sessionId and token
// New session
System.out.println("New session " + sessionName);
try {
// Create a new OpenVidu Session
Session session = this.openVidu.createSession();
// Get the sessionId
String sessionId = session.getSessionId();
// Generate a new token with the recently created tokenOptions
String token = session.generateToken(tokenOptions);
// Store the session and the token in our collections
this.mapSessions.put(sessionName, session);
this.mapSessionIdsTokens.put(sessionId, new ConcurrentHashMap<>());
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.put(sessionName, new ConcurrentHashMap<>());
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Prepare the response with the sessionId and the token
responseJson.put(0, sessionId);
responseJson.put(1, token);
// Prepare the response with the token
responseJson.put(0, token);
// Return the response to the client
return new ResponseEntity<>(responseJson, HttpStatus.OK);
@ -140,29 +139,23 @@ public class SessionController {
String sessionName = (String) sessionNameTokenJSON.get("sessionName");
String token = (String) sessionNameTokenJSON.get("token");
// If the session exists ("TUTORIAL" in this case)
if (this.mapSessions.get(sessionName) != null) {
String sessionId = this.mapSessions.get(sessionName).getSessionId();
if (this.mapSessionIdsTokens.containsKey(sessionId)) {
// If the token exists
if (this.mapSessionIdsTokens.get(sessionId).remove(token) != null) {
// User left the session
if (this.mapSessionIdsTokens.get(sessionId).isEmpty()) {
// Last user left: session must be removed
this.mapSessions.remove(sessionName);
}
return new ResponseEntity<>(HttpStatus.OK);
} else {
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
// If the session exists
if (this.mapSessions.get(sessionName) != null && this.mapSessionNamesTokens.get(sessionName) != null) {
// If the token exists
if (this.mapSessionNamesTokens.get(sessionName).remove(token) != null) {
// User left the session
if (this.mapSessionNamesTokens.get(sessionName).isEmpty()) {
// Last user left: session must be removed
this.mapSessions.remove(sessionName);
}
return new ResponseEntity<>(HttpStatus.OK);
} else {
// The SESSIONID wasn't valid
System.out.println("Problems in the app server: the SESSIONID wasn't valid");
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
} else {
// The SESSION does not exist
System.out.println("Problems in the app server: the SESSION does not exist");

View File

@ -5,5 +5,5 @@ server.ssl.key-store-password: openvidu
server.ssl.key-store-type: JKS
server.ssl.key-alias: openvidu-selfsigned
openvidu.url: https://localhost:8443/
openvidu.url: https://localhost:4443/
openvidu.secret: MY_SECRET

View File

@ -1,35 +1,34 @@
var OV;
var session;
var sessionId;
var token;
var nickName;
var userName;
var sessionName;
var sessionName; // Name of the video session the user will connect to
var token; // Token retrieved from OpenVidu Server
/* OPENVIDU METHODS */
function joinSession() {
getSessionIdAndToken(function () {
getToken((token) => {
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
session = OV.initSession(sessionId);
// --- 2) Init a session ---
// --- 2) Specify the actions when events take place ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
appendUserData(event.element, subscriber.stream.connection);
@ -37,38 +36,49 @@ function joinSession() {
});
// On every Stream destroyed...
session.on('streamDestroyed', function (event) {
session.on('streamDestroyed', (event) => {
// Delete the HTML element with the user's name and nickname
removeUserData(event.stream.connection);
});
// --- 3) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
session.connect(token, '{"clientData": "' + nickName + '"}', function (error) {
var nickName = $("#nickName").val();
session.connect(token, { clientData: nickName })
.then(() => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// --- 5) Set page layout for active call ---
// Here we check somehow if the user has at least 'PUBLISHER' role before
var userName = $("#user").val();
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// Here we check somehow if the user has 'PUBLISHER' role before
// trying to publish its stream. Even if someone modified the client's code and
// published the stream, it wouldn't work if the token sent in Session.connect
// method doesn't belong to a 'PUBLIHSER' role
if (isPublisher()) {
// method is not recognized as 'PUBLIHSER' role by OpenVidu Server
if (isPublisher(userName)) {
// --- 4) Get your own camera stream ---
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
// Init the main video with ours and append our data
var userData = {
nickName: nickName,
@ -80,7 +90,7 @@ function joinSession() {
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
@ -88,22 +98,18 @@ function joinSession() {
console.warn('You don\'t have permissions to publish');
initMainVideoThumbnail(); // Show SUBSCRIBER message in main video
}
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
return false;
});
});
return false;
}
function leaveSession() {
// 6) Leave the session by calling 'disconnect' method over the Session object
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
session = null;
@ -124,68 +130,66 @@ function leaveSession() {
function logIn() {
var user = $("#user").val(); // Username
var pass = $("#pass").val(); // Password
var jsonBody = JSON.stringify({ // Body of POST request
'user': user,
'pass': pass
});
userName = user;
httpRequest('POST', 'api-login/login', jsonBody, 'Login WRONG', function successCallback(response) {
console.warn(userName + ' login');
$("#name-user").text(user);
$("#not-logged").hide();
$("#logged").show();
// Random nickName and session
$("#sessionName").val("Session " + Math.floor(Math.random() * 10));
$("#participantName").val("Participant " + Math.floor(Math.random() * 100));
});
httpPostRequest(
'api-login/login',
{user: user, pass: pass},
'Login WRONG',
(response) => {
$("#name-user").text(user);
$("#not-logged").hide();
$("#logged").show();
// Random nickName and session
$("#sessionName").val("Session " + Math.floor(Math.random() * 10));
$("#nickName").val("Participant " + Math.floor(Math.random() * 100));
}
);
}
function logOut() {
httpRequest('GET', 'api-login/logout', null, 'Logout WRONG', function successCallback(response) {
console.warn(userName + ' logout');
$("#not-logged").show();
$("#logged").hide();
});
httpPostRequest(
'api-login/logout',
{},
'Logout WRONG',
(response) => {
$("#not-logged").show();
$("#logged").hide();
}
);
}
function getSessionIdAndToken(callback) {
function getToken(callback) {
sessionName = $("#sessionName").val(); // Video-call chosen by the user
nickName = $("#participantName").val(); // Nickname chosen by the user
var jsonBody = JSON.stringify({ // Body of POST request
'session': sessionName
});
// Send POST request
httpRequest('POST', 'api-sessions/get-sessionid-token', jsonBody, 'Request of SESSIONID and TOKEN gone WRONG:', function successCallback(response) {
sessionId = response[0]; // Get sessionId from response
token = response[1]; // Get token from response
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")");
callback(); // Continue the join operation
});
httpPostRequest(
'api-sessions/get-token',
{sessionName: sessionName},
'Request of TOKEN gone WRONG:',
(response) => {
token = response[0]; // Get token from response
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
callback(token); // Continue the join operation
}
);
}
function removeUser() {
// Body of POST request with the name of the session and the token of the leaving user
var jsonBody = JSON.stringify({
'sessionName': sessionName,
'token': token
});
// Send POST request
httpRequest('POST', 'api-sessions/remove-user', jsonBody, 'User couldn\'t be removed from session', function successCallback(response) {
console.warn(userName + " correctly removed from session");
});
httpPostRequest(
'api-sessions/remove-user',
{sessionName: sessionName, token: token},
'User couldn\'t be removed from session',
(response) => {
console.warn("You have been removed from session " + sessionName);
}
);
}
function httpRequest(method, url, body, errorMsg, callback) {
function httpPostRequest(url, body, errorMsg, callback) {
var http = new XMLHttpRequest();
http.open(method, url, true);
http.open('POST', url, true);
http.setRequestHeader('Content-type', 'application/json');
http.addEventListener('readystatechange', processRequest, false);
http.send(body);
http.send(JSON.stringify(body));
function processRequest() {
if (http.readyState == 4) {
@ -209,7 +213,7 @@ function httpRequest(method, url, body, errorMsg, callback) {
/* APPLICATION BROWSER METHODS */
window.onbeforeunload = function () { // Gracefully leave session
window.onbeforeunload = () => { // Gracefully leave session
if (session) {
removeUser();
leaveSession();
@ -261,9 +265,12 @@ function addClickListener(videoElement, clientData, serverData) {
videoElement.addEventListener('click', function () {
var mainVideo = $('#main-video video').get(0);
if (mainVideo.srcObject !== videoElement.srcObject) {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeOut("fast", () => {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeIn("fast");
});
}
});
}
@ -279,7 +286,7 @@ function initMainVideoThumbnail() {
$('#main-video video').css("background", "url('images/subscriber-msg.jpg') round");
}
function isPublisher() {
function isPublisher(userName) {
return userName.includes('publisher');
}

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
<script>
$(document).ready(function () {
@ -88,7 +85,7 @@
<form class="form-group" onsubmit="return false">
<p>
<label>Participant</label>
<input class="form-control" type="text" id="participantName" required>
<input class="form-control" type="text" id="nickName" required>
</p>
<p>
<label>Session</label>
@ -130,4 +127,4 @@
</body>
</html>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,9 @@
},
"homepage": "https://github.com/OpenVidu/openvidu-tutorials#readme",
"dependencies": {
"body-parser": "^1.17.2",
"express": "^4.15.3",
"express-session": "^1.15.3",
"openvidu-node-client": "1.7.0"
"body-parser": "1.18.2",
"express": "4.16.3",
"express-session": "1.15.6",
"openvidu-node-client": "2.0.0"
}
}

View File

@ -1,75 +1,84 @@
var OV;
var session;
var sessionId;
var token;
var nickName;
var userName;
var sessionName;
var sessionName; // Name of the video session the user will connect to
var token; // Token retrieved from OpenVidu Server
/* OPENVIDU METHODS */
function joinSession() {
getSessionIdAndToken(function () {
getToken((token) => {
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
session = OV.initSession(sessionId);
// --- 2) Init a session ---
// --- 2) Specify the actions when events take place ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
// Add a new <p> element for the user's name and nickname just below its video
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
appendUserData(event.element, subscriber.stream.connection);
});
});
// On every Stream destroyed...
session.on('streamDestroyed', function (event) {
session.on('streamDestroyed', (event) => {
// Delete the HTML element with the user's name and nickname
removeUserData(event.stream.connection);
});
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
var nickName = $("#nickName").val();
session.connect(token, { clientData: nickName })
.then(() => {
// --- 3) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
// --- 5) Set page layout for active call ---
session.connect(token, '{"clientData": "' + nickName + '"}', function (error) {
var userName = $("#user").val();
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// Here we check somehow if the user has at least 'PUBLISHER' role before
// Here we check somehow if the user has 'PUBLISHER' role before
// trying to publish its stream. Even if someone modified the client's code and
// published the stream, it wouldn't work if the token sent in Session.connect
// method doesn't belong to a 'PUBLIHSER' role
if (isPublisher()) {
// method is not recognized as 'PUBLIHSER' role by OpenVidu Server
if (isPublisher(userName)) {
// --- 4) Get your own camera stream ---
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
// Init the main video with ours and append our data
var userData = {
nickName: nickName,
@ -77,11 +86,11 @@ function joinSession() {
};
initMainVideo(event.element, userData);
appendUserData(event.element, userData);
$(event.element).prop('muted', true); // Mute lcoal video
$(event.element).prop('muted', true); // Mute local video
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
@ -89,22 +98,18 @@ function joinSession() {
console.warn('You don\'t have permissions to publish');
initMainVideoThumbnail(); // Show SUBSCRIBER message in main video
}
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
return false;
});
});
return false;
}
function leaveSession() {
// 6) Leave the session by calling 'disconnect' method over the Session object
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
session = null;
@ -125,67 +130,66 @@ function leaveSession() {
function logIn() {
var user = $("#user").val(); // Username
var pass = $("#pass").val(); // Password
var jsonBody = JSON.stringify({ // Body of POST request
'user': user,
'pass': pass
});
userName = user;
httpRequest('POST', '/api-login/login', jsonBody, 'Login WRONG', function successCallback(response){ // Send POST request
console.warn(userName + ' login');
$("#name-user").text(user);
$("#not-logged").hide();
$("#logged").show();
// Random nickName and session
$("#sessionName").val("Session " + Math.floor(Math.random() * 10));
$("#participantName").val("Participant " + Math.floor(Math.random() * 100));
});
httpPostRequest(
'api-login/login',
{user: user, pass: pass},
'Login WRONG',
(response) => {
$("#name-user").text(user);
$("#not-logged").hide();
$("#logged").show();
// Random nickName and session
$("#sessionName").val("Session " + Math.floor(Math.random() * 10));
$("#nickName").val("Participant " + Math.floor(Math.random() * 100));
}
);
}
function logOut() {
httpRequest('GET', 'api-login/logout', null, 'Logout WRONG', function successCallback(response) {
console.warn(userName + ' logout');
$("#not-logged").show();
$("#logged").hide();
});
httpPostRequest(
'api-login/logout',
{},
'Logout WRONG',
(response) => {
$("#not-logged").show();
$("#logged").hide();
}
);
}
function getSessionIdAndToken(callback) {
function getToken(callback) {
sessionName = $("#sessionName").val(); // Video-call chosen by the user
nickName = $("#participantName").val(); // Nickname chosen by the user
var jsonBody = JSON.stringify({ // Body of POST request
'session': sessionName
});
// Send POST request
httpRequest('POST', 'api-sessions/get-sessionid-token', jsonBody, 'Request of SESSIONID and TOKEN gone WRONG:', function successCallback(response) {
sessionId = response[0]; // Get sessionId from response
token = response[1]; // Get token from response
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")");
callback(); // Continue the join operation
});
httpPostRequest(
'api-sessions/get-token',
{sessionName: sessionName},
'Request of TOKEN gone WRONG:',
(response) => {
token = response[0]; // Get token from response
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
callback(token); // Continue the join operation
}
);
}
function removeUser() {
// Body of POST request with the name of the session and the token of the leaving user
var jsonBody = JSON.stringify({
'sessionName': sessionName,
'token': token
});
// Send POST request
httpRequest('POST', 'api-sessions/remove-user', jsonBody, 'User couldn\'t be removed from session', function successCallback(response) {
console.warn(userName + " correctly removed from session");
});
httpPostRequest(
'api-sessions/remove-user',
{sessionName: sessionName, token: token},
'User couldn\'t be removed from session',
(response) => {
console.warn("You have been removed from session " + sessionName);
}
);
}
function httpRequest(method, url, body, errorMsg, callback) {
function httpPostRequest(url, body, errorMsg, callback) {
var http = new XMLHttpRequest();
http.open(method, url, true);
http.open('POST', url, true);
http.setRequestHeader('Content-type', 'application/json');
http.addEventListener('readystatechange', processRequest, false);
http.send(body);
http.send(JSON.stringify(body));
function processRequest() {
if (http.readyState == 4) {
@ -209,7 +213,7 @@ function httpRequest(method, url, body, errorMsg, callback) {
/* APPLICATION BROWSER METHODS */
window.onbeforeunload = function () { // Gracefully leave session
window.onbeforeunload = () => { // Gracefully leave session
if (session) {
removeUser();
leaveSession();
@ -261,9 +265,12 @@ function addClickListener(videoElement, clientData, serverData) {
videoElement.addEventListener('click', function () {
var mainVideo = $('#main-video video').get(0);
if (mainVideo.srcObject !== videoElement.srcObject) {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeOut("fast", () => {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeIn("fast");
});
}
});
}
@ -279,7 +286,7 @@ function initMainVideoThumbnail() {
$('#main-video video').css("background", "url('images/subscriber-msg.jpg') round");
}
function isPublisher() {
function isPublisher(userName) {
return userName.includes('publisher');
}

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
<script>
$(document).ready(function () {
@ -88,7 +85,7 @@
<form class="form-group" onsubmit="return false">
<p>
<label>Participant</label>
<input class="form-control" type="text" id="participantName" required>
<input class="form-control" type="text" id="nickName" required>
</p>
<p>
<label>Session</label>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -63,13 +63,13 @@ var OPENVIDU_URL = process.argv[2];
// Environment variable: secret shared with our OpenVidu server
var OPENVIDU_SECRET = process.argv[3];
// OpenVidu object to ask openvidu-server for sessionId and token
// Entrypoint to OpenVidu Node Client SDK
var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
// Collection to pair session names and OpenVidu Session objects
var mapSessionNameSession = {};
// Collection to pair sessionId's (identifiers of Session objects) and tokens
var mapSessionIdTokens = {};
// Collection to pair session names with OpenVidu Session objects
var mapSessions = {};
// Collection to pair session names with tokens
var mapSessionNamesTokens = {};
console.log("App listening on port 5000");
@ -81,7 +81,7 @@ console.log("App listening on port 5000");
// Login
app.post('/api-login/login', function (req, res) {
// Retrieve params from POST body
var user = req.body.user;
var pass = req.body.pass;
@ -102,91 +102,89 @@ app.post('/api-login/login', function (req, res) {
});
// Logout
app.get('/api-login/logout', function (req, res) {
app.post('/api-login/logout', function (req, res) {
console.log("'" + req.session.loggedUser + "' has logged out");
req.session.destroy();
res.status(200).send();
});
// Get sessionId and token (add new user to session)
app.post('/api-sessions/get-sessionid-token', function (req, res) {
// Get token (add new user to session)
app.post('/api-sessions/get-token', function (req, res) {
if (!isLogged(req.session)) {
req.session.destroy();
res.status(401).send('User not logged');
} else {
// The video-call to connect ("TUTORIAL")
var sessionName = req.body.session;
// The video-call to connect
var sessionName = req.body.sessionName;
// Role associated to this user
var role = users.find(u => (u.user === req.session.loggedUser)).role;
// Optional data to be passed to other users when this user connects to the video-call
// In this case, a JSON with the value we stored in the req.session object on login
var serverData = '{"serverData": "' + req.session.loggedUser + '"}';
var serverData = JSON.stringify({ serverData: req.session.loggedUser });
console.log("Getting a token | {sessionName}={" + sessionName + "}");
console.log("Getting sessionId and token | {sessionName}={" + sessionName + "}");
// Build tokenOptions object with the serverData and the role
var tokenOptions = new TokenOptions.Builder()
.data(serverData)
.role(role)
.build();
var tokenOptions = {
data: serverData,
role: role
};
if (mapSessionNameSession[sessionName]) {
// Session already exists: return existing sessionId and a new token
if (mapSessions[sessionName]) {
// Session already exists
console.log('Existing session ' + sessionName);
// Get the existing Session from the collection
var mySession = mapSessionNameSession[sessionName];
var mySession = mapSessions[sessionName];
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Get the existing sessionId
mySession.getSessionId(function (sessionId) {
mySession.generateToken(tokenOptions)
.then(token => {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
// Return the sessionId and token to the client
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
mapSessionNamesTokens[sessionName].push(token);
// Return the token to the client
res.status(200).send({
0: sessionId,
1: token
0: token
});
})
.catch(error => {
console.error(error);
});
});
} else { // New session: return a new sessionId and a new token
} else {
// New session
console.log('New session ' + sessionName);
// Create a new OpenVidu Session
var mySession = OV.createSession();
// Get the sessionId asynchronously
mySession.getSessionId(function (sessionId) {
// Store the new Session in the collection of Sessions
mapSessionNameSession[sessionName] = mySession;
// Store a new empty array in the collection of tokens
mapSessionIdTokens[sessionId] = [];
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
// Create a new OpenVidu Session asynchronously
OV.createSession()
.then(session => {
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
// Return the sessionId and token to the client
res.status(200).send({
0: sessionId,
1: token
});
// Generate a new token asynchronously with the recently created tokenOptions
session.generateToken(tokenOptions)
.then(token => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return the Token to the client
res.status(200).send({
0: token
});
})
.catch(error => {
console.error(error);
});
})
.catch(error => {
console.error(error);
});
});
}
}
});
@ -203,35 +201,26 @@ app.post('/api-sessions/remove-user', function (req, res) {
console.log('Removing user | {sessionName, token}={' + sessionName + ', ' + token + '}');
// If the session exists
var mySession = mapSessionNameSession[sessionName];
if (mySession) {
mySession.getSessionId(function (sessionId) {
var tokens = mapSessionIdTokens[sessionId];
if (tokens) {
var index = tokens.indexOf(token);
// If the token exists
if (index !== -1) {
// Token removed!
tokens.splice(index, 1);
console.log(sessionName + ': ' + mapSessionIdTokens[sessionId].toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
if (mapSessionIdTokens[sessionId].length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessionNameSession[sessionName];
}
res.status(200).send();
} else {
var msg = 'Problems in the app server: the SESSIONID wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
});
if (mapSessions[sessionName] && mapSessionNamesTokens[sessionName]) {
var tokens = mapSessionNamesTokens[sessionName];
var index = tokens.indexOf(token);
// If the token exists
if (index !== -1) {
// Token removed
tokens.splice(index, 1);
console.log(sessionName + ': ' + tokens.toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
if (tokens.length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessions[sessionName];
}
res.status(200).send();
} else {
var msg = 'Problems in the app server: the SESSION does not exist';
console.log(msg);

View File

@ -10,6 +10,7 @@
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">

View File

@ -41,7 +41,7 @@
<dependency>
<groupId>io.openvidu</groupId>
<artifactId>openvidu-java-client</artifactId>
<version>1.7.0</version>
<version>2.0.0</version>
</dependency>
</dependencies>

View File

@ -20,18 +20,19 @@ import io.openvidu.java.client.TokenOptions;
@Controller
public class SessionController {
// OpenVidu object to ask openvidu-server for sessionId and token
// OpenVidu object as entrypoint of the SDK
private OpenVidu openVidu;
// Collection to pair session names and OpenVidu Session objects
private Map<String, Session> mapSessions = new ConcurrentHashMap<>();
// Collection to pair sessionId's and tokens (the inner Map pairs tokens and role associated)
private Map<String, Map<String, OpenViduRole>> mapSessionIdsTokens = new ConcurrentHashMap<>();
// Collection to pair session names and tokens (the inner Map pairs tokens and role associated)
private Map<String, Map<String, OpenViduRole>> mapSessionNamesTokens = new ConcurrentHashMap<>();
// URL where our OpenVidu server is listening
private String OPENVIDU_URL;
// Secret shared with our OpenVidu server
private String SECRET;
public SessionController(@Value("${openvidu.secret}") String secret, @Value("${openvidu.url}") String openviduUrl) {
this.SECRET = secret;
@ -61,25 +62,21 @@ public class SessionController {
TokenOptions tokenOptions = new TokenOptions.Builder().data(serverData).role(role).build();
if (this.mapSessions.get(sessionName) != null) {
// Session already exists: return existing sessionId and a new token
// Session already exists
System.out.println("Existing session " + sessionName);
try {
// Get the existing sessionId from our collection with
// the sessionName param ("TUTORIAL")
String sessionId = this.mapSessions.get(sessionName).getSessionId();
// Generate a new token with the recently created tokenOptions
String token = this.mapSessions.get(sessionName).generateToken(tokenOptions);
// Update our collection storing the new token
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Add all the needed attributes to the template
model.addAttribute("sessionId", sessionId);
model.addAttribute("sessionName", sessionName);
model.addAttribute("token", token);
model.addAttribute("nickName", clientData);
model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
model.addAttribute("sessionName", sessionName);
// Return session.html template
return "session";
@ -90,28 +87,25 @@ public class SessionController {
return "dashboard";
}
} else {
// New session: return a new sessionId and a new token
// New session
System.out.println("New session " + sessionName);
try {
// Create a new OpenVidu Session
Session session = this.openVidu.createSession();
// Get the sessionId
String sessionId = session.getSessionId();
// Generate a new token with the recently created tokenOptions
String token = session.generateToken(tokenOptions);
// Store the session and the token in our collections
this.mapSessions.put(sessionName, session);
this.mapSessionIdsTokens.put(sessionId, new ConcurrentHashMap<>());
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.put(sessionName, new ConcurrentHashMap<>());
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Add all the needed attributes to the template
model.addAttribute("sessionId", sessionId);
model.addAttribute("sessionName", sessionName);
model.addAttribute("token", token);
model.addAttribute("nickName", clientData);
model.addAttribute("userName", httpSession.getAttribute("loggedUser"));
model.addAttribute("sessionName", sessionName);
// Return session.html template
return "session";
@ -135,31 +129,24 @@ public class SessionController {
}
System.out.println("Removing user | sessioName=" + sessionName + ", token=" + token);
// If the session exists
if (this.mapSessions.get(sessionName) != null) {
String sessionId = this.mapSessions.get(sessionName).getSessionId();
if (this.mapSessionIdsTokens.containsKey(sessionId)) {
// If the token exists
if (this.mapSessionIdsTokens.get(sessionId).remove(token) != null) {
System.out.println(sessionName + ": " + this.mapSessionIdsTokens.get(sessionId).toString());
// User left the session
if (this.mapSessionIdsTokens.get(sessionId).isEmpty()) {
// Last user left: session must be removed
this.mapSessions.remove(sessionName);
System.out.println(sessionName + " empty!");
}
return "redirect:/dashboard";
} else {
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return "redirect:/dashboard";
// If the session exists ("TUTORIAL" in this case)
if (this.mapSessions.get(sessionName) != null && this.mapSessionNamesTokens.get(sessionName) != null) {
// If the token exists
if (this.mapSessionNamesTokens.get(sessionName).remove(token) != null) {
// User left the session
if (this.mapSessionNamesTokens.get(sessionName).isEmpty()) {
// Last user left: session must be removed
this.mapSessions.remove(sessionName);
}
return "redirect:/dashboard";
} else {
// The SESSIONID wasn't valid
System.out.println("Problems in the app server: the SESSIONID wasn't valid");
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return "redirect:/dashboard";
}
} else {
// The SESSION does not exist
System.out.println("Problems in the app server: the SESSION does not exist");

View File

@ -5,5 +5,5 @@ server.ssl.key-store-password: openvidu
server.ssl.key-store-type: JKS
server.ssl.key-alias: openvidu-selfsigned
openvidu.url: https://localhost:8443/
openvidu.url: https://localhost:4443/
openvidu.secret: MY_SECRET

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon"></link>
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"></link>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"></link>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></link>
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen"></link>
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
</head>
<body>
@ -25,10 +22,15 @@
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/"><img class="demo-logo" src="images/openvidu_vert_white_bg_trans_cropped.png"/> MVC Java</a>
<a class="navbar-brand" href="/">
<img class="demo-logo" src="images/openvidu_vert_white_bg_trans_cropped.png" /> MVC Java</a>
<a class="navbar-brand nav-icon" href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-mvc-java" title="GitHub Repository"
target="_blank"><i class="fa fa-github" aria-hidden="true"></i></a>
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-mvc-java/" title="Documentation" target="_blank"><i class="fa fa-book" aria-hidden="true"></i></a>
target="_blank">
<i class="fa fa-github" aria-hidden="true"></i>
</a>
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-mvc-java/" title="Documentation" target="_blank">
<i class="fa fa-book" aria-hidden="true"></i>
</a>
</div>
</div>
</nav>
@ -58,7 +60,9 @@
<footer class="footer">
<div class="container">
<div class="text-muted">OpenVidu © 2017</div>
<a href="http://www.openvidu.io/" target="_blank"><img class="openvidu-logo" src="images/openvidu_globe_bg_transp_cropped.png"/></a>
<a href="http://www.openvidu.io/" target="_blank">
<img class="openvidu-logo" src="images/openvidu_globe_bg_transp_cropped.png" />
</a>
</div>
</footer>
@ -67,32 +71,32 @@
<script th:inline="javascript">
// Get all the attributes from the template in Thymeleaf style
var sessionId = [[${sessionId}]];
var token = [[${token}]];
var nickName = [[${nickName}]];
var userName = [[${userName}]];
var sessionName = [[${sessionName}]];
var sessionName = [[${ sessionName }]];
var token = [[${ token }]];
var nickName = [[${ nickName }]];
var userName = [[${ userName }]];
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' +
sessionId + ", TOKEN:" + token + ")");
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
// --- 1) Get an OpenVidu object ---
var OV = new OpenVidu();
var session = OV.initSession(sessionId);
OV = new OpenVidu();
// --- 2) Init a session ---
// --- 2) Specify the actions when events take place ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
appendUserData(event.element, subscriber.stream.connection);
@ -100,38 +104,47 @@
});
// On every Stream destroyed...
session.on('streamDestroyed', function (event) {
session.on('streamDestroyed', (event) => {
// Delete the HTML element with the user's name and nickname
removeUserData(event.stream.connection);
});
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
// --- 3) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
session.connect(token, '{"clientData": "' + nickName + '"}', function (error) {
session.connect(token, { clientData: nickName })
.then(() => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// --- 5) Set page layout for active call ---
// Here we check somehow if the user has at least 'PUBLISHER' role before
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// Here we check somehow if the user has 'PUBLISHER' role before
// trying to publish its stream. Even if someone modified the client's code and
// published the stream, it wouldn't work if the token sent in Session.connect
// method doesn't belong to a 'PUBLIHSER' role
// method is not recognized as 'PUBLIHSER' role by OpenVidu Server
if (isPublisher()) {
// --- 4) Get your own camera stream ---
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
// Init the main video with ours and append our data
var userData = {
nickName: nickName,
@ -143,7 +156,7 @@
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
@ -151,15 +164,15 @@
console.warn('You don\'t have permissions to publish');
initMainVideoThumbnail(); // Show SUBSCRIBER message in main video
}
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
});
function leaveSession() {
// --- 6) Leave the session by calling 'disconnect' method over the Session object ---
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
}
@ -207,9 +220,12 @@
videoElement.addEventListener('click', function () {
var mainVideo = $('#main-video video').get(0);
if (mainVideo.srcObject !== videoElement.srcObject) {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeOut("fast", () => {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeIn("fast");
});
}
});
}

View File

@ -17,10 +17,10 @@
},
"homepage": "https://github.com/OpenVidu/openvidu-tutorials#readme",
"dependencies": {
"body-parser": "^1.17.2",
"ejs": "^2.5.6",
"express": "^4.15.3",
"express-session": "^1.15.3",
"openvidu-node-client": "1.7.0"
"body-parser": "1.18.2",
"ejs": "2.6.1",
"express": "4.16.3",
"express-session": "1.15.6",
"openvidu-node-client": "2.0.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -64,13 +64,13 @@ var OPENVIDU_URL = process.argv[2];
// Environment variable: secret shared with our OpenVidu server
var OPENVIDU_SECRET = process.argv[3];
// OpenVidu object to ask openvidu-server for sessionId and token
// Entrypoint to OpenVidu Node Client SDK
var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
// Collection to pair session names and OpenVidu Session objects
var mapSessionNameSession = {};
// Collection to pair sessionId's (identifiers of Session objects) and tokens
var mapSessionIdTokens = {};
// Collection to pair session names with OpenVidu Session objects
var mapSessions = {};
// Collection to pair session names with tokens
var mapSessionNamesTokens = {};
console.log("App listening on port 5000");
@ -103,36 +103,36 @@ app.get('/dashboard', dashboardController);
function dashboardController(req, res) {
// Check if the user is already logged in
if (isLogged(req.session)) {
// User is already logged. Immediately return dashboard
user = req.session.loggedUser;
res.render('dashboard.ejs', {
user: user
});
} else {
// User wasn't logged and wants to
// Retrieve params from POST body
var user = req.body.user;
// Check if the user is already logged in
if (isLogged(req.session)) {
// User is already logged. Immediately return dashboard
user = req.session.loggedUser;
res.render('dashboard.ejs', {
user: user
});
} else {
// User wasn't logged and wants to
// Retrieve params from POST body
var user = req.body.user;
var pass = req.body.pass;
console.log("Logging in | {user, pass}={" + user + ", " + pass + "}");
if (login(user, pass)) { // Correct user-pass
// Validate session and return OK
if (login(user, pass)) { // Correct user-pass
// Validate session and return OK
// Value stored in req.session allows us to identify the user in future requests
console.log("'" + user + "' has logged in");
req.session.loggedUser = user;
res.render('dashboard.ejs', {
user: user
});
} else { // Wrong user-pass
req.session.loggedUser = user;
res.render('dashboard.ejs', {
user: user
});
} else { // Wrong user-pass
// Invalidate session and return index template
console.log("'" + user + "' invalid credentials");
req.session.destroy();
res.redirect('/');
}
}
req.session.destroy();
res.redirect('/');
}
}
}
app.post('/session', (req, res) => {
@ -140,9 +140,9 @@ app.post('/session', (req, res) => {
req.session.destroy();
res.redirect('/');
} else {
// The nickname sent by the client
// The nickname sent by the client
var clientData = req.body.data;
// The video-call to connect ("TUTORIAL")
// The video-call to connect
var sessionName = req.body.sessionname;
// Role associated to this user
@ -150,77 +150,76 @@ app.post('/session', (req, res) => {
// Optional data to be passed to other users when this user connects to the video-call
// In this case, a JSON with the value we stored in the req.session object on login
var serverData = '{"serverData": "' + req.session.loggedUser + '"}';
console.log("Getting sessionId and token | {sessionName}={" + sessionName + "}");
var serverData = JSON.stringify({ serverData: req.session.loggedUser });
console.log("Getting a token | {sessionName}={" + sessionName + "}");
// Build tokenOptions object with the serverData and the role
var tokenOptions = new TokenOptions.Builder()
.data(serverData)
.role(role)
.build();
var tokenOptions = {
data: serverData,
role: role
};
if (mapSessionNameSession[sessionName]) {
// Session already exists: return existing sessionId and a new token
if (mapSessions[sessionName]) {
// Session already exists
console.log('Existing session ' + sessionName);
// Get the existing Session from the collection
var mySession = mapSessionNameSession[sessionName];
var mySession = mapSessions[sessionName];
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Get the existing sessionId
mySession.getSessionId(function (sessionId) {
mySession.generateToken(tokenOptions)
.then(token => {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
res.render('session.ejs', {
sessionId: sessionId,
sessionId: mySession.getSessionId(),
token: token,
nickName: clientData,
userName: req.session.loggedUser,
sessionName: sessionName
});
})
.catch(error => {
console.error(error);
});
});
} else { // New session: return a new sessionId and a new token
} else {
// New session
console.log('New session ' + sessionName);
// Create a new OpenVidu Session
var mySession = OV.createSession();
// Get the sessionId asynchronously
mySession.getSessionId(function (sessionId) {
// Store the new Session in the collection of Sessions
mapSessionNameSession[sessionName] = mySession;
// Store a new empty array in the collection of tokens
mapSessionIdTokens[sessionId] = [];
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
// Create a new OpenVidu Session asynchronously
OV.createSession()
.then(session => {
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
// Return session template with all the needed attributes
res.render('session.ejs', {
sessionId: sessionId,
token: token,
nickName: clientData,
userName: req.session.loggedUser,
sessionName: sessionName
});
// Generate a new token asynchronously with the recently created tokenOptions
session.generateToken(tokenOptions)
.then(token => {
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Return session template with all the needed attributes
res.render('session.ejs', {
sessionName: sessionName,
token: token,
nickName: clientData,
userName: req.session.loggedUser,
});
})
.catch(error => {
console.error(error);
});
})
.catch(error => {
console.error(error);
});
});
}
}
});
@ -234,41 +233,32 @@ app.post('/leave-session', (req, res) => {
var sessionName = req.body.sessionname;
var token = req.body.token;
console.log('Removing user | {sessionName, token}={' + sessionName + ', ' + token + '}');
// If the session exists
var mySession = mapSessionNameSession[sessionName];
if (mySession) {
mySession.getSessionId(function (sessionId) {
var tokens = mapSessionIdTokens[sessionId];
if (tokens) {
var index = tokens.indexOf(token);
// If the token exists
if (index !== -1) {
// Token removed!
tokens.splice(index, 1);
console.log(sessionName + ': ' + mapSessionIdTokens[sessionId].toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.redirect('/dashboard');
}
if (mapSessionIdTokens[sessionId].length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessionNameSession[sessionName];
}
res.redirect('/dashboard');
} else {
var msg = 'Problems in the app server: the SESSIONID wasn\'t valid';
console.log(msg);
res.redirect('/dashboard');
}
});
if (mapSessions[sessionName] && mapSessionNamesTokens[sessionName]) {
var tokens = mapSessionNamesTokens[sessionName];
var index = tokens.indexOf(token);
// If the token exists
if (index !== -1) {
// Token removed
tokens.splice(index, 1);
console.log(sessionName + ': ' + tokens.toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.redirect('/dashboard');
}
if (tokens.length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessions[sessionName];
}
res.redirect('/dashboard');
} else {
var msg = 'Problems in the app server: the SESSION does not exist';
console.log(msg);
res.redirect('/dashboard');
res.status(500).send(msg);
}
}
});

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon"></link>
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous"></link>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"></link>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></link>
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen"></link>
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
</head>
<body>
@ -25,10 +22,15 @@
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="/"><img class="demo-logo" src="images/openvidu_vert_white_bg_trans_cropped.png"/> MVC Node</a>
<a class="navbar-brand" href="/">
<img class="demo-logo" src="images/openvidu_vert_white_bg_trans_cropped.png" /> MVC Node</a>
<a class="navbar-brand nav-icon" href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-mvc-node" title="GitHub Repository"
target="_blank"><i class="fa fa-github" aria-hidden="true"></i></a>
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-mvc-node/" title="Documentation" target="_blank"><i class="fa fa-book" aria-hidden="true"></i></a>
target="_blank">
<i class="fa fa-github" aria-hidden="true"></i>
</a>
<a class="navbar-brand nav-icon" href="http://www.openvidu.io/docs/tutorials/openvidu-mvc-node/" title="Documentation" target="_blank">
<i class="fa fa-book" aria-hidden="true"></i>
</a>
</div>
</div>
</nav>
@ -58,7 +60,9 @@
<footer class="footer">
<div class="container">
<div class="text-muted">OpenVidu © 2017</div>
<a href="http://www.openvidu.io/" target="_blank"><img class="openvidu-logo" src="images/openvidu_globe_bg_transp_cropped.png"/></a>
<a href="http://www.openvidu.io/" target="_blank">
<img class="openvidu-logo" src="images/openvidu_globe_bg_transp_cropped.png" />
</a>
</div>
</footer>
@ -66,71 +70,80 @@
<script>
// Get all the attributes from the template in EJS style
var sessionId = <%- JSON.stringify(sessionId) %>;
var sessionName = <%- JSON.stringify(sessionName) %>;
var token = <%- JSON.stringify(token) %>;
var nickName = <%- JSON.stringify(nickName) %>;
var userName = <%- JSON.stringify(userName) %>;
var sessionName = <%- JSON.stringify(sessionName) %>;
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' +
sessionId + ", TOKEN:" + token + ")");
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
var OV = new OpenVidu();
var session = OV.initSession(sessionId);
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
// --- 2) Specify the actions when events take place ---
// --- 2) Init a session ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
// Add a new HTML element for the user's name and nickname just below its video
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
appendUserData(event.element, subscriber.stream.connection);
});
});
// On every Stream destroyed...
session.on('streamDestroyed', function (event) {
session.on('streamDestroyed', (event) => {
// Delete the HTML element with the user's name and nickname
removeUserData(event.stream.connection);
});
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
// --- 3) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
session.connect(token, { clientData: nickName })
.then(() => {
session.connect(token, '{"clientData": "' + nickName + '"}', function (error) {
// --- 5) Set page layout for active call ---
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// Here we check somehow if the user has at least 'PUBLISHER' role before
// Here we check somehow if the user has 'PUBLISHER' role before
// trying to publish its stream. Even if someone modified the client's code and
// published the stream, it wouldn't work if the token sent in Session.connect
// method doesn't belong to a 'PUBLIHSER' role
// method is not recognized as 'PUBLIHSER' role by OpenVidu Server
if (isPublisher()) {
// --- 4) Get your own camera stream ---
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
// Init the main video with ours and append our data
var userData = {
nickName: nickName,
@ -142,23 +155,23 @@
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
} else {
console.warn('You don\'t have permissions to publish');
initMainVideoThumbnail(); // Show SUBSCRIBER message in main video
}
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
});
function leaveSession() {
// --- 6) Leave the session by calling 'disconnect' method over the Session object ---
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
}
@ -206,9 +219,12 @@
videoElement.addEventListener('click', function () {
var mainVideo = $('#main-video video').get(0);
if (mainVideo.srcObject !== videoElement.srcObject) {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeOut("fast", () => {
$('#main-video p.nickName').html(clientData);
$('#main-video p.userName').html(serverData);
mainVideo.srcObject = videoElement.srcObject;
$('#main-video').fadeIn("fast");
});
}
});
}

View File

@ -95,7 +95,7 @@
<dependency>
<groupId>io.openvidu</groupId>
<artifactId>openvidu-java-client</artifactId>
<version>1.8.0</version>
<version>2.0.0</version>
</dependency>
</dependencies>

View File

@ -1,9 +1,11 @@
package io.openvidu.js.java;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
@ -16,9 +18,10 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.openvidu.java.client.Archive;
import io.openvidu.java.client.Recording;
import io.openvidu.java.client.OpenVidu;
import io.openvidu.java.client.OpenViduException;
import io.openvidu.java.client.OpenViduHttpException;
import io.openvidu.java.client.OpenViduJavaClientException;
import io.openvidu.java.client.Session;
import io.openvidu.java.client.TokenOptions;
import io.openvidu.java.client.OpenViduRole;
@ -27,13 +30,19 @@ import io.openvidu.java.client.OpenViduRole;
@RequestMapping("/api")
public class MyRestController {
OpenVidu openVidu;
// OpenVidu object as entrypoint of the SDK
private OpenVidu openVidu;
// Collection to pair session names and OpenVidu Session objects
private Map<String, Session> mapSessions = new ConcurrentHashMap<>();
private Map<String, Map<String, OpenViduRole>> mapSessionIdsTokens = new ConcurrentHashMap<>();
// Collection to pair session names and tokens (the inner Map pairs tokens and role associated)
private Map<String, Map<String, OpenViduRole>> mapSessionNamesTokens = new ConcurrentHashMap<>();
// Collection to pair session names and recording objects
private Map<String, Boolean> sessionRecordings = new ConcurrentHashMap<>();
// URL where our OpenVidu server is listening
private String OPENVIDU_URL;
// Secret shared with our OpenVidu server
private String SECRET;
public MyRestController(@Value("${openvidu.secret}") String secret, @Value("${openvidu.url}") String openviduUrl) {
@ -46,15 +55,15 @@ public class MyRestController {
/*** Session API ***/
/*******************/
@RequestMapping(value = "/get-sessionid-token", method = RequestMethod.POST)
public ResponseEntity<JSONObject> getSessionIdToken(@RequestBody String sessionNameParam) throws ParseException {
@RequestMapping(value = "/get-token", method = RequestMethod.POST)
public ResponseEntity<JSONObject> getToken(@RequestBody String sessionNameParam) throws ParseException {
System.out.println("Getting sessionId and token | {sessionName}=" + sessionNameParam);
JSONObject sessionJSON = (JSONObject) new JSONParser().parse(sessionNameParam);
// The video-call to connect ("TUTORIAL")
String sessionName = (String) sessionJSON.get("session");
String sessionName = (String) sessionJSON.get("sessionName");
// Role associated to this user
OpenViduRole role = OpenViduRole.PUBLISHER;
@ -65,22 +74,18 @@ public class MyRestController {
JSONObject responseJson = new JSONObject();
if (this.mapSessions.get(sessionName) != null) {
// Session already exists: return existing sessionId and a new token
// Session already exists
System.out.println("Existing session " + sessionName);
try {
// Get the existing sessionId from our collection with
// the sessionName param ("TUTORIAL")
String sessionId = this.mapSessions.get(sessionName).getSessionId();
// Generate a new token with the recently created tokenOptions
String token = this.mapSessions.get(sessionName).generateToken(tokenOptions);
// Update our collection storing the new token
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Prepare the response with the sessionId and the token
responseJson.put(0, sessionId);
responseJson.put(1, token);
// Prepare the response with the token
responseJson.put(0, token);
// Return the response to the client
return new ResponseEntity<>(responseJson, HttpStatus.OK);
@ -91,25 +96,22 @@ public class MyRestController {
}
} else {
// New session: return a new sessionId and token
// New session
System.out.println("New session " + sessionName);
try {
// Create a new OpenVidu Session
Session session = this.openVidu.createSession();
// Get the sessionId
String sessionId = session.getSessionId();
// Generate a new token with the recently created tokenOptions
String token = session.generateToken(tokenOptions);
// Store the session and the token in our collections
this.mapSessions.put(sessionName, session);
this.mapSessionIdsTokens.put(sessionId, new ConcurrentHashMap<>());
this.mapSessionIdsTokens.get(sessionId).put(token, role);
this.mapSessionNamesTokens.put(sessionName, new ConcurrentHashMap<>());
this.mapSessionNamesTokens.get(sessionName).put(token, role);
// Prepare the response with the sessionId and the token
responseJson.put(0, sessionId);
responseJson.put(1, token);
responseJson.put(0, token);
// Return the response to the client
return new ResponseEntity<>(responseJson, HttpStatus.OK);
@ -131,30 +133,23 @@ public class MyRestController {
String sessionName = (String) sessionNameTokenJSON.get("sessionName");
String token = (String) sessionNameTokenJSON.get("token");
// If the session exists ("TUTORIAL" in this case)
if (this.mapSessions.get(sessionName) != null) {
String sessionId = this.mapSessions.get(sessionName).getSessionId();
// If the session exists
if (this.mapSessions.get(sessionName) != null && this.mapSessionNamesTokens.get(sessionName) != null) {
if (this.mapSessionIdsTokens.containsKey(sessionId)) {
// If the token exists
if (this.mapSessionIdsTokens.get(sessionId).remove(token) != null) {
// User left the session
if (this.mapSessionIdsTokens.get(sessionId).isEmpty()
&& !this.sessionRecordings.containsKey(sessionId)) {
// Last user left and recording is not taking place: session must be removed
this.mapSessions.remove(sessionName);
}
return new ResponseEntity<>(HttpStatus.OK);
} else {
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
// If the token exists
if (this.mapSessionNamesTokens.get(sessionName).remove(token) != null) {
// User left the session
if (this.mapSessionNamesTokens.get(sessionName).isEmpty()) {
// Last user left: session must be removed
this.mapSessions.remove(sessionName);
}
return new ResponseEntity<>(HttpStatus.OK);
} else {
// The SESSIONID wasn't valid
System.out.println("Problems in the app server: the SESSIONID wasn't valid");
// The TOKEN wasn't valid
System.out.println("Problems in the app server: the TOKEN wasn't valid");
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
} else {
// The SESSION does not exist
System.out.println("Problems in the app server: the SESSION does not exist");
@ -174,10 +169,10 @@ public class MyRestController {
System.out.println("Starting recording | {sessionId}=" + sessionId);
try {
Archive archive = this.openVidu.startRecording(sessionId);
Recording recording = this.openVidu.startRecording(sessionId);
this.sessionRecordings.put(sessionId, true);
return new ResponseEntity<>(archive, HttpStatus.OK);
} catch (OpenViduException e) {
return new ResponseEntity<>(getJsonFromRecording(recording), HttpStatus.OK);
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@ -190,10 +185,10 @@ public class MyRestController {
System.out.println("Stoping recording | {recordingId}=" + recordingId);
try {
Archive archive = this.openVidu.stopRecording(recordingId);
this.sessionRecordings.remove(archive.getSessionId());
return new ResponseEntity<>(archive, HttpStatus.OK);
} catch (OpenViduException e) {
Recording recording = this.openVidu.stopRecording(recordingId);
this.sessionRecordings.remove(recording.getSessionId());
return new ResponseEntity<>(getJsonFromRecording(recording), HttpStatus.OK);
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@ -208,7 +203,7 @@ public class MyRestController {
try {
this.openVidu.deleteRecording(recordingId);
return new ResponseEntity<>(HttpStatus.OK);
} catch (OpenViduException e) {
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@ -219,9 +214,9 @@ public class MyRestController {
System.out.println("Getting recording | {recordingId}=" + recordingId);
try {
Archive archive = this.openVidu.getRecording(recordingId);
return new ResponseEntity<>(archive, HttpStatus.OK);
} catch (OpenViduException e) {
Recording recording = this.openVidu.getRecording(recordingId);
return new ResponseEntity<>(getJsonFromRecording(recording), HttpStatus.OK);
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@ -232,13 +227,15 @@ public class MyRestController {
System.out.println("Listing recordings");
try {
List<Archive> archives = this.openVidu.listRecordings();
return new ResponseEntity<>(archives, HttpStatus.OK);
} catch (OpenViduException e) {
List<Recording> recordings = this.openVidu.listRecordings();
return new ResponseEntity<>(getJsonArrayFromRecordingList(recordings), HttpStatus.OK);
} catch (OpenViduJavaClientException | OpenViduHttpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@SuppressWarnings("unchecked")
private ResponseEntity<JSONObject> getErrorResponse(Exception e) {
JSONObject json = new JSONObject();
json.put("cause", e.getCause());
@ -247,4 +244,30 @@ public class MyRestController {
return new ResponseEntity<>(json, HttpStatus.INTERNAL_SERVER_ERROR);
}
@SuppressWarnings("unchecked")
private JSONObject getJsonFromRecording(Recording recording) {
JSONObject json = new JSONObject();
json.put("createdAt", recording.getCreatedAt());
json.put("duration", recording.getDuration());
json.put("hasAudio", recording.hasAudio());
json.put("hasVideo", recording.hasVideo());
json.put("id", recording.getId());
json.put("recordingLayout", recording.getRecordingLayout());
json.put("name", recording.getName());
json.put("sessionId", recording.getSessionId());
json.put("size", recording.getSize());
json.put("status", recording.getStatus());
json.put("url", recording.getUrl());
return json;
}
@SuppressWarnings("unchecked")
private JSONArray getJsonArrayFromRecordingList(Collection<Recording> recordings) {
JSONArray array = new JSONArray();
for (Recording recording : recordings) {
array.add(getJsonFromRecording(recording));
}
return array;
}
}

View File

@ -5,5 +5,5 @@ server.ssl.key-store-password: openvidu
server.ssl.key-store-type: JKS
server.ssl.key-alias: openvidu-selfsigned
openvidu.url: https://localhost:8443/
openvidu.url: https://localhost:4443/
openvidu.secret: MY_SECRET

View File

@ -1,88 +1,94 @@
var OV;
var session;
var sessionId;
var token;
var sessionName;
var token;
var numVideos = 0;
/* OPENVIDU METHODS */
function joinSession() {
getSessionIdAndToken(function () {
getToken(function () {
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
session = OV.initSession(sessionId);
// --- 2) Init a session ---
// --- 2) Specify the actions when events take place ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(1);
});
// When the HTML video has been appended to DOM...
subscriber.on('videoElementDestroyed', function (event) {
subscriber.on('videoElementDestroyed', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(-1);
});
});
// --- 3) Connect to the session passing the retrieved token ---
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
session.connect(token, null, function (error) {
session.connect(token)
.then(() => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// --- 5) Set page layout for active call ---
// --- 4) Get your own camera stream ---
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
updateNumVideos(1);
$(event.element).prop('muted', true); // Mute local video
});
// When the HTML video has been appended to DOM...
publisher.on('videoElementDestroyed', function (event) {
publisher.on('videoElementDestroyed', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(-1);
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
});
return false;
});
@ -90,7 +96,7 @@ function joinSession() {
function leaveSession() {
// 6) Leave the session by calling 'disconnect' method over the Session object
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
session = null;
@ -106,33 +112,32 @@ function leaveSession() {
/* APPLICATION REST METHODS */
function getSessionIdAndToken(callback) {
function getToken(callback) {
sessionName = $("#sessionName").val(); // Video-call chosen by the user
var jsonBody = JSON.stringify({ // Body of POST request
'session': sessionName
});
// Send POST request
httpRequest('POST', 'api/get-sessionid-token', jsonBody, 'Request of SESSIONID and TOKEN gone WRONG:', function successCallback(response) {
sessionId = response[0]; // Get sessionId from response
token = response[1]; // Get token from response
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")");
callback(); // Continue the join operation
});
httpRequest(
'POST',
'api/get-token',
{sessionName: sessionName},
'Request of TOKEN gone WRONG:',
(response) => {
token = response[0]; // Get token from response
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
callback(token); // Continue the join operation
}
);
}
function removeUser() {
// Body of POST request with the name of the session and the token of the leaving user
var jsonBody = JSON.stringify({
'sessionName': sessionName,
'token': token
});
// Send POST request
httpRequest('POST', 'api/remove-user', jsonBody, 'User couldn\'t be removed from session', function successCallback(response) {
console.warn("User correctly removed from session");
});
httpRequest(
'POST',
'api/remove-user',
{sessionName: sessionName, token: token},
'User couldn\'t be removed from session',
(response) => {
console.warn("You have been removed from session " + sessionName);
}
);
}
function httpRequest(method, url, body, errorMsg, callback) {
@ -141,7 +146,7 @@ function httpRequest(method, url, body, errorMsg, callback) {
http.open(method, url, true);
http.setRequestHeader('Content-type', 'application/json');
http.addEventListener('readystatechange', processRequest, false);
http.send(body);
http.send(JSON.stringify(body));
function processRequest() {
if (http.readyState == 4) {
@ -163,48 +168,69 @@ function httpRequest(method, url, body, errorMsg, callback) {
var recordingId;
function startRecording() {
var jsonBody = JSON.stringify({
'session': session.sessionId
});
httpRequest('POST', 'api/recording/start', jsonBody, 'Start recording WRONG', function successCallback(response) {
console.log(response);
recordingId = response.id;
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'POST',
'api/recording/start',
{session: session.sessionId},
'Start recording WRONG',
(response) => {
console.log(response);
recordingId = response.id;
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function stopRecording() {
var jsonBody = JSON.stringify({
'recording': recordingId
});
httpRequest('POST', 'api/recording/stop', jsonBody, 'Stop recording WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'POST',
'api/recording/stop',
{recording: recordingId},
'Stop recording WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function deleteRecording() {
var jsonBody = JSON.stringify({
'recording': recordingId
});
httpRequest('DELETE', 'api/recording/delete', jsonBody, 'Delete recording WRONG', function successCallback() {
console.log("DELETE ok");
$('#text-area').text("DELETE ok");
});
httpRequest(
'DELETE',
'api/recording/delete',
{recording: recordingId},
'Delete recording WRONG',
() => {
console.log("DELETE ok");
$('#text-area').text("DELETE ok");
}
);
}
function getRecording() {
httpRequest('GET', 'api/recording/get/' + recordingId, '', 'Get recording WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'GET',
'api/recording/get/' + recordingId,
{},
'Get recording WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function listRecordings() {
httpRequest('GET', 'api/recording/list', '', 'List recordings WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'GET',
'api/recording/list',
{},
'List recordings WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
/* APPLICATION REST METHODS */

View File

@ -7,17 +7,14 @@
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon">
<!-- Bootstrap -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
crossorigin="anonymous"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
<script>
$(document).ready(function () {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,8 @@
},
"homepage": "https://github.com/OpenVidu/openvidu-tutorials#readme",
"dependencies": {
"body-parser": "^1.17.2",
"express": "^4.15.3",
"express-session": "^1.15.3",
"openvidu-node-client": "1.8.0"
"body-parser": "1.18.2",
"express": "4.16.3",
"openvidu-node-client": "2.0.0"
}
}

View File

@ -1,88 +1,94 @@
var OV;
var session;
var sessionId;
var token;
var sessionName;
var token;
var numVideos = 0;
/* OPENVIDU METHODS */
function joinSession() {
getSessionIdAndToken(function () {
getToken(function () {
// --- 1) Get an OpenVidu object and init a session with the retrieved sessionId ---
// --- 1) Get an OpenVidu object ---
OV = new OpenVidu();
session = OV.initSession(sessionId);
// --- 2) Init a session ---
// --- 2) Specify the actions when events take place ---
session = OV.initSession();
// --- 3) Specify the actions when events take place in the session ---
// On every new Stream received...
session.on('streamCreated', function (event) {
session.on('streamCreated', (event) => {
// Subscribe to the Stream to receive it
// HTML video will be appended to element with 'video-container' id
var subscriber = session.subscribe(event.stream, 'video-container');
// When the HTML video has been appended to DOM...
subscriber.on('videoElementCreated', function (event) {
subscriber.on('videoElementCreated', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(1);
});
// When the HTML video has been appended to DOM...
subscriber.on('videoElementDestroyed', function (event) {
subscriber.on('videoElementDestroyed', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(-1);
});
});
// --- 3) Connect to the session passing the retrieved token ---
// --- 4) Connect to the session passing the retrieved token and some more data from
// the client (in this case a JSON with the nickname chosen by the user) ---
session.connect(token, null, function (error) {
session.connect(token)
.then(() => {
// If the connection is successful, initialize a publisher and publish to the session
if (!error) {
// --- 5) Set page layout for active call ---
// --- 4) Get your own camera stream ---
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
// --- 6) Get your own camera stream ---
var publisher = OV.initPublisher('video-container', {
audio: true, // Whether you want to transmit audio or not
video: true, // Whether you want to transmit video or not
audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted
videoActive: true, // Whether you want to start the publishing with your video enabled or disabled
quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH')
screen: false // true to get your screen as video source instead of your camera
audioSource: undefined, // The source of audio. If undefined default microphone
videoSource: undefined, // The source of video. If undefined default webcam
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
publishVideo: true, // Whether you want to start publishing with your video enabled or not
resolution: '640x480', // The resolution of your video
frameRate: 30, // The frame rate of your video
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
mirror: false // Whether to mirror your local video or not
});
// --- 7) Specify the actions when events take place in our publisher ---
// When our HTML video has been added to DOM...
publisher.on('videoElementCreated', function (event) {
publisher.on('videoElementCreated', (event) => {
updateNumVideos(1);
$(event.element).prop('muted', true); // Mute local video
});
// When the HTML video has been appended to DOM...
publisher.on('videoElementDestroyed', function (event) {
publisher.on('videoElementDestroyed', (event) => {
// Add a new HTML element for the user's name and nickname over its video
updateNumVideos(-1);
});
// --- 5) Publish your stream ---
// --- 8) Publish your stream ---
session.publish(publisher);
} else {
})
.catch(error => {
console.warn('There was an error connecting to the session:', error.code, error.message);
}
});
$('#session-title').text(sessionName);
$('#join').hide();
$('#session').show();
});
return false;
});
@ -90,12 +96,12 @@ function joinSession() {
function leaveSession() {
// 6) Leave the session by calling 'disconnect' method over the Session object
// --- 9) Leave the session by calling 'disconnect' method over the Session object ---
session.disconnect();
session = null;
numVideos = 0;
$('#join').show();
$('#session').hide();
}
@ -106,33 +112,32 @@ function leaveSession() {
/* APPLICATION REST METHODS */
function getSessionIdAndToken(callback) {
function getToken(callback) {
sessionName = $("#sessionName").val(); // Video-call chosen by the user
var jsonBody = JSON.stringify({ // Body of POST request
'session': sessionName
});
// Send POST request
httpRequest('POST', 'api/get-sessionid-token', jsonBody, 'Request of SESSIONID and TOKEN gone WRONG:', function successCallback(response) {
sessionId = response[0]; // Get sessionId from response
token = response[1]; // Get token from response
console.warn('Request of SESSIONID and TOKEN gone WELL (SESSIONID:' + sessionId + ", TOKEN:" + token + ")");
callback(); // Continue the join operation
});
httpRequest(
'POST',
'api/get-token',
{sessionName: sessionName},
'Request of TOKEN gone WRONG:',
(response) => {
token = response[0]; // Get token from response
console.warn('Request of TOKEN gone WELL (TOKEN:' + token + ')');
callback(token); // Continue the join operation
}
);
}
function removeUser() {
// Body of POST request with the name of the session and the token of the leaving user
var jsonBody = JSON.stringify({
'sessionName': sessionName,
'token': token
});
// Send POST request
httpRequest('POST', 'api/remove-user', jsonBody, 'User couldn\'t be removed from session', function successCallback(response) {
console.warn("User correctly removed from session");
});
httpRequest(
'POST',
'api/remove-user',
{sessionName: sessionName, token: token},
'User couldn\'t be removed from session',
(response) => {
console.warn("You have been removed from session " + sessionName);
}
);
}
function httpRequest(method, url, body, errorMsg, callback) {
@ -141,7 +146,7 @@ function httpRequest(method, url, body, errorMsg, callback) {
http.open(method, url, true);
http.setRequestHeader('Content-type', 'application/json');
http.addEventListener('readystatechange', processRequest, false);
http.send(body);
http.send(JSON.stringify(body));
function processRequest() {
if (http.readyState == 4) {
@ -163,48 +168,69 @@ function httpRequest(method, url, body, errorMsg, callback) {
var recordingId;
function startRecording() {
var jsonBody = JSON.stringify({
'session': session.sessionId
});
httpRequest('POST', 'api/recording/start', jsonBody, 'Start recording WRONG', function successCallback(response) {
console.log(response);
recordingId = response.id;
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'POST',
'api/recording/start',
{session: session.sessionId},
'Start recording WRONG',
(response) => {
console.log(response);
recordingId = response.id;
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function stopRecording() {
var jsonBody = JSON.stringify({
'recording': recordingId
});
httpRequest('POST', 'api/recording/stop', jsonBody, 'Stop recording WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'POST',
'api/recording/stop',
{recording: recordingId},
'Stop recording WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function deleteRecording() {
var jsonBody = JSON.stringify({
'recording': recordingId
});
httpRequest('DELETE', 'api/recording/delete', jsonBody, 'Delete recording WRONG', function successCallback() {
console.log("DELETE ok");
$('#text-area').text("DELETE ok");
});
httpRequest(
'DELETE',
'api/recording/delete',
{recording: recordingId},
'Delete recording WRONG',
() => {
console.log("DELETE ok");
$('#text-area').text("DELETE ok");
}
);
}
function getRecording() {
httpRequest('GET', 'api/recording/get/' + recordingId, '', 'Get recording WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'GET',
'api/recording/get/' + recordingId,
{},
'Get recording WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
function listRecordings() {
httpRequest('GET', 'api/recording/list', '', 'List recordings WRONG', function successCallback(response) {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
});
httpRequest(
'GET',
'api/recording/list',
{},
'List recordings WRONG',
(response) => {
console.log(response);
$('#text-area').text(JSON.stringify(response, null, "\t"));
}
);
}
/* APPLICATION REST METHODS */

View File

@ -17,7 +17,7 @@
<!-- Bootstrap -->
<link rel="styleSheet" href="style.css" type="text/css" media="screen">
<script src="openvidu-browser-1.8.0.js"></script>
<script src="openvidu-browser-2.0.0.js"></script>
<script src="app.js"></script>
<script>
$(document).ready(function () {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -16,17 +16,11 @@ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
// Node imports
var express = require('express');
var fs = require('fs');
var session = require('express-session');
var https = require('https');
var bodyParser = require('body-parser'); // Pull information from HTML POST (express4)
var app = express(); // Create our app with express
// Server configuration
app.use(session({
saveUninitialized: true,
resave: false,
secret: 'MY_SECRET'
}));
app.use(express.static(__dirname + '/public')); // Set the static files location
app.use(bodyParser.urlencoded({
'extended': 'true'
@ -48,13 +42,13 @@ var OPENVIDU_URL = process.argv[2];
// Environment variable: secret shared with our OpenVidu server
var OPENVIDU_SECRET = process.argv[3];
// OpenVidu object to ask openvidu-server for sessionId and token
// Entrypoint to OpenVidu Node Client SDK
var OV = new OpenVidu(OPENVIDU_URL, OPENVIDU_SECRET);
// Collection to pair session names and OpenVidu Session objects
var mapSessionNameSession = {};
// Collection to pair sessionId's (identifiers of Session objects) and tokens
var mapSessionIdTokens = {};
// Collection to pair session names with OpenVidu Session objects
var mapSessions = {};
// Collection to pair session names with tokens
var mapSessionNamesTokens = {};
console.log("App listening on port 5000");
@ -63,76 +57,72 @@ console.log("App listening on port 5000");
/* Session API */
// Get sessionId and token (add new user to session)
app.post('/api/get-sessionid-token', function (req, res) {
// The video-call to connect ("TUTORIAL")
var sessionName = req.body.session;
console.log("Getting sessionId and token | {sessionName}={" + sessionName + "}");
// Get token (add new user to session)
app.post('/api/get-token', function (req, res) {
// The video-call to connect
var sessionName = req.body.sessionName;
// Role associated to this user
var role = OpenViduRole.PUBLISHER;
// Build tokenOptions object with the serverData and the role
var tokenOptions = new TokenOptions.Builder()
.role(role)
.build();
console.log("Getting a token | {sessionName}={" + sessionName + "}");
if (mapSessionNameSession[sessionName]) {
// Session already exists: return existing sessionId and a new token
// Build tokenOptions object with PUBLIHSER role
var tokenOptions = { role: role }
if (mapSessions[sessionName]) {
// Session already exists
console.log('Existing session ' + sessionName);
// Get the existing Session from the collection
var mySession = mapSessionNameSession[sessionName];
var mySession = mapSessions[sessionName];
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Get the existing sessionId
mySession.getSessionId(function (sessionId) {
mySession.generateToken(tokenOptions)
.then(token => {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
mapSessionNamesTokens[sessionName].push(token);
// Return the sessionId and token to the client
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
// Return the token to the client
res.status(200).send({
0: sessionId,
1: token
0: token
});
})
.catch(error => {
console.error(error);
});
});
} else { // New session: return a new sessionId and a new token
} else {
// New session
console.log('New session ' + sessionName);
// Create a new OpenVidu Session
var mySession = OV.createSession();
// Create a new OpenVidu Session asynchronously
OV.createSession()
.then(session => {
// Store the new Session in the collection of Sessions
mapSessions[sessionName] = session;
// Store a new empty array in the collection of tokens
mapSessionNamesTokens[sessionName] = [];
// Get the sessionId asynchronously
mySession.getSessionId(function (sessionId) {
// Generate a new token asynchronously with the recently created tokenOptions
session.generateToken(tokenOptions)
.then(token => {
// Store the new Session in the collection of Sessions
mapSessionNameSession[sessionName] = mySession;
// Store a new empty array in the collection of tokens
mapSessionIdTokens[sessionId] = [];
// Store the new token in the collection of tokens
mapSessionNamesTokens[sessionName].push(token);
// Generate a new token asynchronously with the recently created tokenOptions
mySession.generateToken(tokenOptions, function (token) {
// Store the new token in the collection of tokens
mapSessionIdTokens[sessionId].push(token);
console.log('SESSIONID: ' + sessionId);
console.log('TOKEN: ' + token);
// Return the sessionId and token to the client
res.status(200).send({
0: sessionId,
1: token
});
// Return the Token to the client
res.status(200).send({
0: token
});
})
.catch(error => {
console.error(error);
});
})
.catch(error => {
console.error(error);
});
});
}
});
@ -143,36 +133,27 @@ app.post('/api/remove-user', function (req, res) {
var token = req.body.token;
console.log('Removing user | {sessionName, token}={' + sessionName + ', ' + token + '}');
// If the session exists
var mySession = mapSessionNameSession[sessionName];
if (mySession) {
mySession.getSessionId(function (sessionId) {
var tokens = mapSessionIdTokens[sessionId];
if (tokens) {
var index = tokens.indexOf(token);
// If the session exists
if (mapSessions[sessionName] && mapSessionNamesTokens[sessionName]) {
var tokens = mapSessionNamesTokens[sessionName];
var index = tokens.indexOf(token);
// If the token exists
if (index !== -1) {
// Token removed!
tokens.splice(index, 1);
console.log(sessionName + ': ' + mapSessionIdTokens[sessionId].toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
if (mapSessionIdTokens[sessionId].length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessionNameSession[sessionName];
}
res.status(200).send();
} else {
var msg = 'Problems in the app server: the SESSIONID wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
});
// If the token exists
if (index !== -1) {
// Token removed
tokens.splice(index, 1);
console.log(sessionName + ': ' + tokens.toString());
} else {
var msg = 'Problems in the app server: the TOKEN wasn\'t valid';
console.log(msg);
res.status(500).send(msg);
}
if (tokens.length == 0) {
// Last user left: session must be removed
console.log(sessionName + ' empty!');
delete mapSessions[sessionName];
}
res.status(200).send();
} else {
var msg = 'Problems in the app server: the SESSION does not exist';
console.log(msg);
@ -182,32 +163,31 @@ app.post('/api/remove-user', function (req, res) {
/* Recording API */
// Start session recording
// Start recording
app.post('/api/recording/start', function (req, res) {
// Retrieve params from POST body
var sessionId = req.body.session;
console.log("Starting recording | {sessionId}=" + sessionId);
OV.startRecording(sessionId)
.then(archive => res.status(200).send(archive))
.then(recording => res.status(200).send(getJsonFromRecording(recording)))
.catch(error => res.status(400).send(error.message));
});
// Start session recording
// Stop recording
app.post('/api/recording/stop', function (req, res) {
// Retrieve params from POST body
var recordingId = req.body.recording;
console.log("Stoping recording | {recordingId}=" + recordingId);
OV.stopRecording(recordingId)
.then(archive => res.status(200).send(archive))
.then(recording => res.status(200).send(getJsonFromRecording(recording)))
.catch(error => res.status(400).send(error.message));
});
// Start session recording
// Delete recording
app.delete('/api/recording/delete', function (req, res) {
// Retrieve params from DELETE body
var recordingId = req.body.recording;
@ -218,22 +198,46 @@ app.delete('/api/recording/delete', function (req, res) {
.catch(error => res.status(400).send(error.message));
});
// Start session recording
// Get recording
app.get('/api/recording/get/:recordingId', function (req, res) {
// Retrieve params from GET url
var recordingId = req.params.recordingId;
console.log("Getting recording | {recordingId}=" + recordingId);
OV.getRecording(recordingId)
.then(archive => res.status(200).send(archive))
.then(recording => res.status(200).send(getJsonFromRecording(recording)))
.catch(error => res.status(400).send(error.message));
});
// Start session recording
// List all recordings
app.get('/api/recording/list', function (req, res) {
console.log("Listing recordings");
OV.listRecordings()
.then(archives => res.status(200).send(archives))
.then(recordings => res.status(200).send(getJsonArrayFromRecordingList(recordings)))
.catch(error => res.status(400).send(error.message));
});
});
function getJsonFromRecording(recording) {
return {
"createdAt": recording.createdAt,
"duration": recording.duration,
"hasAudio": recording.hasAudio,
"hasVideo": recording.hasVideo,
"id": recording.id,
"name": recording.name,
"recordingLayout": recording.recordingLayout,
"sessionId": recording.sessionId,
"size": recording.size,
"status": recording.status,
"url": recording.url
}
}
function getJsonArrayFromRecordingList(recordings) {
var jsonArray = [];
recordings.forEach(recording => {
jsonArray.push(getJsonFromRecording(recording));
})
return jsonArray;
}