2018-04-18 14:29:07 +02:00
/ *
2018-05-06 02:20:25 +02:00
* ( C ) Copyright 2017 - 2018 OpenVidu ( https : //openvidu.io/)
2018-04-18 14:29:07 +02:00
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*
* /
2018-09-19 15:36:26 +02:00
import axios from 'axios' ;
import { Connection } from './Connection' ;
2018-09-24 11:04:54 +02:00
import { Publisher } from './Publisher' ;
2018-04-23 11:06:16 +02:00
import { Recording } from './Recording' ;
import { RecordingProperties } from './RecordingProperties' ;
2018-09-19 15:36:26 +02:00
import { Session } from './Session' ;
import { SessionProperties } from './SessionProperties' ;
2018-03-14 18:48:29 +01:00
2018-10-09 16:29:28 +02:00
/ * *
* @hidden
* /
interface ObjMap < T > { [ s : string ] : T ; }
2017-06-10 01:44:31 +02:00
export class OpenVidu {
2018-06-04 14:14:17 +02:00
private Buffer = require ( 'buffer/' ) . Buffer ;
2018-03-14 18:48:29 +01:00
2018-07-22 22:13:45 +02:00
/ * *
* @hidden
* /
static hostname : string ;
/ * *
* @hidden
* /
static port : number ;
/ * *
* @hidden
* /
static basicAuth : string ;
/ * *
* @hidden
* /
static readonly API_RECORDINGS : string = '/api/recordings' ;
/ * *
* @hidden
* /
static readonly API_RECORDINGS_START : string = '/start' ;
/ * *
* @hidden
* /
static readonly API_RECORDINGS_STOP : string = '/stop' ;
/ * *
* @hidden
* /
static readonly API_SESSIONS = '/api/sessions' ;
/ * *
* @hidden
* /
static readonly API_TOKENS = '/api/tokens' ;
private static o : OpenVidu ;
/ * *
* Array of active sessions . * * This value will remain unchanged since the last time method [ [ OpenVidu . fetch ] ]
* was called * * . Exceptions to this rule are :
*
* - Calling [ [ Session . fetch ] ] updates that specific Session status
* - Calling [ [ Session . close ] ] automatically removes the Session from the list of active Sessions
* - Calling [ [ Session . forceDisconnect ] ] automatically updates the inner affected connections for that specific Session
* - Calling [ [ Session . forceUnpublish ] ] also automatically updates the inner affected connections for that specific Session
* - Calling [ [ OpenVidu . startRecording ] ] and [ [ OpenVidu . stopRecording ] ] automatically updates the recording status of the
* Session ( [ [ Session . recording ] ] )
*
* To get the array of active sessions with their current actual value , you must call [ [ OpenVidu . fetch ] ] before consulting
* property [ [ activeSessions ] ]
* /
activeSessions : Session [ ] = [ ] ;
2018-04-24 15:42:23 +02:00
/ * *
* @param urlOpenViduServer Public accessible IP where your instance of OpenVidu Server is up an running
* @param secret Secret used on OpenVidu Server initialization
* /
2018-03-14 18:48:29 +01:00
constructor ( private urlOpenViduServer : string , secret : string ) {
this . setHostnameAndPort ( ) ;
2018-07-22 22:13:45 +02:00
OpenVidu . basicAuth = this . getBasicAuth ( secret ) ;
OpenVidu . o = this ;
2018-03-14 18:48:29 +01:00
}
2017-06-10 01:44:31 +02:00
2018-04-25 17:50:55 +02:00
/ * *
2018-07-22 22:13:45 +02:00
* Creates an OpenVidu session . You can call [ [ Session . getSessionId ] ] inside the resolved promise to retrieve the ` sessionId `
2018-04-25 17:50:55 +02:00
*
2018-05-03 10:58:26 +02:00
* @returns A Promise that is resolved to the [ [ Session ] ] if success and rejected with an Error object if not .
2018-04-25 17:50:55 +02:00
* /
public createSession ( properties? : SessionProperties ) : Promise < Session > {
return new Promise < Session > ( ( resolve , reject ) = > {
2018-07-22 22:13:45 +02:00
const session = new Session ( properties ) ;
2018-04-25 17:50:55 +02:00
session . getSessionIdHttp ( )
. then ( sessionId = > {
2018-07-22 22:13:45 +02:00
this . activeSessions . push ( session ) ;
2018-04-25 17:50:55 +02:00
resolve ( session ) ;
} )
. catch ( error = > {
reject ( error ) ;
} ) ;
} ) ;
2018-03-14 18:48:29 +01:00
}
2018-04-18 14:23:16 +02:00
public startRecording ( sessionId : string ) : Promise < Recording > ;
public startRecording ( sessionId : string , name : string ) : Promise < Recording > ;
public startRecording ( sessionId : string , properties : RecordingProperties ) : Promise < Recording > ;
2018-04-24 15:42:23 +02:00
/ * *
* Starts the recording of a [ [ Session ] ]
*
* @param sessionId The ` sessionId ` of the [ [ Session ] ] you want to start recording
* @param name The name you want to give to the video file . You can access this same value in your clients on recording events ( ` recordingStarted ` , ` recordingStopped ` )
*
2018-04-25 11:03:30 +02:00
* @returns A Promise that is resolved to the [ [ Recording ] ] if it successfully started ( the recording can be stopped with guarantees ) and rejected with an Error object if not . This Error object has as ` message ` property with the following values :
2018-04-24 15:42:23 +02:00
* - ` 404 ` : no session exists for the passed ` sessionId `
* - ` 400 ` : the session has no connected participants
* - ` 409 ` : the session is not configured for using [ [ MediaMode . ROUTED ] ] or it is already being recorded
2018-05-03 12:27:27 +02:00
* - ` 501 ` : OpenVidu Server recording module is disabled ( ` openvidu.recording ` property set to ` false ` )
2018-04-24 15:42:23 +02:00
* /
2018-04-18 14:23:16 +02:00
public startRecording ( sessionId : string , param2? : string | RecordingProperties ) : Promise < Recording > {
2018-04-18 10:39:39 +02:00
return new Promise < Recording > ( ( resolve , reject ) = > {
2018-03-14 18:48:29 +01:00
2018-06-04 14:14:17 +02:00
let data ;
2018-04-18 14:23:16 +02:00
if ( ! ! param2 ) {
if ( ! ( typeof param2 === 'string' ) ) {
2018-04-20 12:04:56 +02:00
const properties = < RecordingProperties > param2 ;
2018-06-04 14:14:17 +02:00
data = JSON . stringify ( {
2018-04-18 14:23:16 +02:00
session : sessionId ,
2018-04-23 11:06:16 +02:00
name : ! ! properties . name ? properties . name : '' ,
2019-01-18 20:59:27 +01:00
outputMode : ! ! properties . outputMode ? properties . outputMode : '' ,
2018-04-23 11:06:16 +02:00
recordingLayout : ! ! properties . recordingLayout ? properties . recordingLayout : '' ,
customLayout : ! ! properties . customLayout ? properties . customLayout : ''
2018-04-18 14:23:16 +02:00
} ) ;
} else {
2018-06-04 14:14:17 +02:00
data = JSON . stringify ( {
2018-04-18 14:23:16 +02:00
session : sessionId ,
2018-04-20 12:04:56 +02:00
name : param2 ,
2019-01-18 20:59:27 +01:00
outputMode : '' ,
2018-04-20 15:50:56 +02:00
recordingLayout : '' ,
customLayout : ''
2018-04-18 14:23:16 +02:00
} ) ;
}
} else {
2018-06-04 14:14:17 +02:00
data = JSON . stringify ( {
2018-04-18 14:23:16 +02:00
session : sessionId ,
2018-04-20 12:04:56 +02:00
name : '' ,
2019-01-18 20:59:27 +01:00
outputMode : '' ,
2018-04-20 15:50:56 +02:00
recordingLayout : '' ,
customLayout : ''
2018-04-18 14:23:16 +02:00
} ) ;
}
2018-03-14 18:48:29 +01:00
2018-06-04 14:14:17 +02:00
axios . post (
2018-07-22 22:13:45 +02:00
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_RECORDINGS + OpenVidu . API_RECORDINGS_START ,
2018-06-04 14:14:17 +02:00
data ,
{
headers : {
2018-07-22 22:13:45 +02:00
'Authorization' : OpenVidu . basicAuth ,
2018-06-04 14:14:17 +02:00
'Content-Type' : 'application/json'
}
2018-03-14 18:48:29 +01:00
}
2018-06-04 14:14:17 +02:00
)
. then ( res = > {
if ( res . status === 200 ) {
2018-04-18 10:39:39 +02:00
// SUCCESS response from openvidu-server (Recording in JSON format). Resolve new Recording
2018-07-22 22:13:45 +02:00
const r : Recording = new Recording ( res . data ) ;
2018-07-23 00:36:45 +02:00
const activeSession = this . activeSessions . find ( s = > s . sessionId === r . sessionId ) ;
if ( ! ! activeSession ) {
activeSession . recording = true ;
} else {
console . warn ( "No active session found for sessionId '" + r . sessionId + "'. This instance of OpenVidu Node Client didn't create this session" ) ;
}
2018-07-22 22:13:45 +02:00
resolve ( r ) ;
2018-03-14 18:48:29 +01:00
} else {
// ERROR response from openvidu-server. Resolve HTTP status
2018-06-04 14:14:17 +02:00
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
2018-03-14 18:48:29 +01:00
}
} ) ;
} ) ;
}
2018-04-24 15:42:23 +02:00
/ * *
* Stops the recording of a [ [ Session ] ]
*
* @param recordingId The ` id ` property of the [ [ Recording ] ] you want to stop
*
* @returns A Promise that is resolved to the [ [ Recording ] ] if it successfully stopped and rejected with an Error object if not . This Error object has as ` message ` property with the following values :
* - ` 404 ` : no recording exists for the passed ` recordingId `
* - ` 406 ` : recording has ` starting ` status . Wait until ` started ` status before stopping the recording
* /
2018-04-18 10:39:39 +02:00
public stopRecording ( recordingId : string ) : Promise < Recording > {
return new Promise < Recording > ( ( resolve , reject ) = > {
2018-03-14 18:48:29 +01:00
2018-06-04 14:14:17 +02:00
axios . post (
2018-07-22 22:13:45 +02:00
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_RECORDINGS + OpenVidu . API_RECORDINGS_STOP + '/' + recordingId ,
2018-06-04 14:14:17 +02:00
undefined ,
{
headers : {
2018-07-22 22:13:45 +02:00
'Authorization' : OpenVidu . basicAuth ,
2018-06-04 14:14:17 +02:00
'Content-Type' : 'application/x-www-form-urlencoded'
}
2018-03-14 18:48:29 +01:00
}
2018-06-04 14:14:17 +02:00
)
. then ( res = > {
if ( res . status === 200 ) {
2018-04-18 10:39:39 +02:00
// SUCCESS response from openvidu-server (Recording in JSON format). Resolve new Recording
2018-07-22 22:13:45 +02:00
const r : Recording = new Recording ( res . data ) ;
2018-07-23 00:36:45 +02:00
const activeSession = this . activeSessions . find ( s = > s . sessionId === r . sessionId ) ;
if ( ! ! activeSession ) {
activeSession . recording = false ;
} else {
console . warn ( "No active session found for sessionId '" + r . sessionId + "'. This instance of OpenVidu Node Client didn't create this session" ) ;
}
2018-07-22 22:13:45 +02:00
resolve ( r ) ;
2018-03-14 18:48:29 +01:00
} else {
// ERROR response from openvidu-server. Resolve HTTP status
2018-06-04 14:14:17 +02:00
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
2018-07-22 22:13:45 +02:00
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest
// in the browser and an instance of http.ClientRequest in node.js
2018-06-04 14:14:17 +02:00
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
2018-03-14 18:48:29 +01:00
}
} ) ;
} ) ;
}
2018-04-24 15:42:23 +02:00
/ * *
* Gets an existing [ [ Recording ] ]
*
* @param recordingId The ` id ` property of the [ [ Recording ] ] you want to retrieve
*
* @returns A Promise that is resolved to the [ [ Recording ] ] if it successfully stopped and rejected with an Error object if not . This Error object has as ` message ` property with the following values :
* - ` 404 ` : no recording exists for the passed ` recordingId `
* /
2018-04-18 10:39:39 +02:00
public getRecording ( recordingId : string ) : Promise < Recording > {
return new Promise < Recording > ( ( resolve , reject ) = > {
2018-03-14 18:48:29 +01:00
2018-06-04 14:14:17 +02:00
axios . get (
2018-07-22 22:13:45 +02:00
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_RECORDINGS + '/' + recordingId ,
2018-06-04 14:14:17 +02:00
{
headers : {
2018-07-22 22:13:45 +02:00
'Authorization' : OpenVidu . basicAuth ,
2018-06-04 14:14:17 +02:00
'Content-Type' : 'application/x-www-form-urlencoded'
}
2018-03-14 18:48:29 +01:00
}
2018-06-04 14:14:17 +02:00
)
. then ( res = > {
if ( res . status === 200 ) {
2018-04-18 10:39:39 +02:00
// SUCCESS response from openvidu-server (Recording in JSON format). Resolve new Recording
2018-06-04 14:14:17 +02:00
resolve ( new Recording ( res . data ) ) ;
2018-03-14 18:48:29 +01:00
} else {
// ERROR response from openvidu-server. Resolve HTTP status
2018-06-04 14:14:17 +02:00
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
2018-03-14 18:48:29 +01:00
}
} ) ;
} ) ;
}
2018-04-24 15:42:23 +02:00
/ * *
* Lists all existing recordings
*
* @returns A Promise that is resolved to an array with all existing recordings
* /
2018-04-18 10:39:39 +02:00
public listRecordings ( ) : Promise < Recording [ ] > {
return new Promise < Recording [ ] > ( ( resolve , reject ) = > {
2018-03-14 18:48:29 +01:00
2018-06-04 14:14:17 +02:00
axios . get (
2018-07-22 22:13:45 +02:00
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_RECORDINGS ,
2018-06-04 14:14:17 +02:00
{
headers : {
2018-07-22 22:13:45 +02:00
Authorization : OpenVidu.basicAuth
2018-06-04 14:14:17 +02:00
}
2018-03-14 18:48:29 +01:00
}
2018-06-04 14:14:17 +02:00
)
. then ( res = > {
if ( res . status === 200 ) {
2018-04-18 10:39:39 +02:00
// SUCCESS response from openvidu-server (JSON arrays of recordings in JSON format). Resolve list of new recordings
2018-04-23 11:06:16 +02:00
const recordingArray : Recording [ ] = [ ] ;
2018-06-04 14:14:17 +02:00
const responseItems = res . data . items ;
2018-04-23 11:06:16 +02:00
for ( const item of responseItems ) {
recordingArray . push ( new Recording ( item ) ) ;
2018-03-14 18:48:29 +01:00
}
2018-10-15 11:33:56 +02:00
// Order recordings by time of creation (newest first)
recordingArray . sort ( ( r1 , r2 ) = > ( r1 . createdAt < r2 . createdAt ) ? 1 : ( ( r2 . createdAt < r1 . createdAt ) ? - 1 : 0 ) ) ;
2018-04-18 10:39:39 +02:00
resolve ( recordingArray ) ;
2018-03-14 18:48:29 +01:00
} else {
// ERROR response from openvidu-server. Resolve HTTP status
2018-06-04 14:14:17 +02:00
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
2018-03-14 18:48:29 +01:00
}
} ) ;
} ) ;
}
2018-04-24 15:42:23 +02:00
/ * *
* Deletes a [ [ Recording ] ] . The recording must have status ` stopped ` or ` available `
*
* @param recordingId
*
* @returns A Promise that is resolved if the Recording was successfully deleted and rejected with an Error object if not . This Error object has as ` message ` property with the following values :
* - ` 404 ` : no recording exists for the passed ` recordingId `
* - ` 409 ` : the recording has ` started ` status . Stop it before deletion
* /
2018-03-14 18:48:29 +01:00
public deleteRecording ( recordingId : string ) : Promise < Error > {
return new Promise < Error > ( ( resolve , reject ) = > {
2018-06-04 14:14:17 +02:00
axios . delete (
2018-07-22 22:13:45 +02:00
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_RECORDINGS + '/' + recordingId ,
2018-06-04 14:14:17 +02:00
{
headers : {
2018-07-22 22:13:45 +02:00
'Authorization' : OpenVidu . basicAuth ,
2018-06-04 14:14:17 +02:00
'Content-Type' : 'application/x-www-form-urlencoded'
}
2018-03-14 18:48:29 +01:00
}
2018-06-04 14:14:17 +02:00
)
. then ( res = > {
if ( res . status === 204 ) {
2018-03-14 18:48:29 +01:00
// SUCCESS response from openvidu-server. Resolve undefined
resolve ( undefined ) ;
} else {
// ERROR response from openvidu-server. Resolve HTTP status
2018-06-04 14:14:17 +02:00
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
2018-03-14 18:48:29 +01:00
}
} ) ;
} ) ;
2018-01-27 19:39:49 +01:00
}
2018-07-22 22:13:45 +02:00
/ * *
* Updates every property of every active Session with the current status they have in OpenVidu Server .
* After calling this method you can access the updated array of active sessions in [ [ activeSessions ] ]
*
* @returns A promise resolved to true if any Session status has changed with respect to the server , or to false if not .
* This applies to any property or sub - property of any of the sessions locally stored in OpenVidu Node Client
* /
public fetch ( ) : Promise < boolean > {
return new Promise < boolean > ( ( resolve , reject ) = > {
axios . get (
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_SESSIONS ,
{
headers : {
Authorization : OpenVidu.basicAuth
}
}
)
. then ( res = > {
if ( res . status === 200 ) {
// Array to store fetched sessionIds and later remove closed sessions
const fetchedSessionIds : string [ ] = [ ] ;
// Boolean to store if any Session has changed
let hasChanged = false ;
res . data . content . forEach ( session = > {
fetchedSessionIds . push ( session . sessionId ) ;
2018-09-19 15:36:26 +02:00
let sessionIndex = - 1 ;
let storedSession = this . activeSessions . find ( ( s , index ) = > {
if ( s . sessionId === session . sessionId ) {
sessionIndex = index ;
return true ;
} else {
return false ;
}
} ) ;
2018-07-22 22:13:45 +02:00
if ( ! ! storedSession ) {
2018-09-19 15:36:26 +02:00
const fetchedSession : Session = new Session ( ) . resetSessionWithJson ( session ) ;
const changed : boolean = ! storedSession . equalTo ( fetchedSession ) ;
if ( changed ) {
storedSession = fetchedSession ;
this . activeSessions [ sessionIndex ] = storedSession ;
}
2018-07-22 22:13:45 +02:00
console . log ( "Available session '" + storedSession . sessionId + "' info fetched. Any change: " + changed ) ;
hasChanged = hasChanged || changed ;
} else {
this . activeSessions . push ( new Session ( session ) ) ;
console . log ( "New session '" + session . sessionId + "' info fetched" ) ;
hasChanged = true ;
}
} ) ;
2018-07-22 22:48:09 +02:00
// Remove closed sessions from activeSessions array
2018-07-23 10:01:49 +02:00
this . activeSessions = this . activeSessions . filter ( session = > {
if ( fetchedSessionIds . includes ( session . sessionId ) ) {
return true ;
} else {
console . log ( "Removing closed session '" + session . sessionId + "'" ) ;
hasChanged = true ;
return false ;
}
} ) ;
2018-07-22 22:48:09 +02:00
console . log ( 'Active sessions info fetched: ' , fetchedSessionIds ) ;
2018-07-22 22:13:45 +02:00
resolve ( hasChanged ) ;
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
}
} ) ;
} ) ;
}
2018-09-19 15:36:26 +02:00
/ * *
* @hidden
2018-10-09 16:29:28 +02:00
* @returns A map paring every existing sessionId with true or false depending on whether it has changed or not
2018-09-19 15:36:26 +02:00
* /
2018-10-09 16:29:28 +02:00
fetchWebRtc ( ) : Promise < any > {
2018-09-19 15:36:26 +02:00
// tslint:disable:no-string-literal
const addWebRtcStatsToConnections = ( connection : Connection , connectionsExtendedInfo : any ) = > {
const connectionExtended = connectionsExtendedInfo . find ( c = > c . connectionId === connection . connectionId ) ;
if ( ! ! connectionExtended ) {
2018-09-24 11:04:54 +02:00
const publisherArray = [ ] ;
2018-09-19 15:36:26 +02:00
connection . publishers . forEach ( pub = > {
const publisherExtended = connectionExtended . publishers . find ( p = > p . streamId === pub . streamId ) ;
const pubAux = { } ;
// Standard properties
pubAux [ 'streamId' ] = pub . streamId ;
pubAux [ 'createdAt' ] = pub . createdAt ;
2018-09-24 11:04:54 +02:00
const mediaOptions = {
audioActive : pub.audioActive ,
videoActive : pub.videoActive ,
hasAudio : pub.hasAudio ,
hasVideo : pub.hasVideo ,
typeOfVideo : pub.typeOfVideo ,
frameRate : pub.frameRate ,
videoDimensions : pub.videoDimensions
} ;
pubAux [ 'mediaOptions' ] = mediaOptions ;
const newPublisher = new Publisher ( pubAux ) ;
2018-09-19 15:36:26 +02:00
// WebRtc properties
2018-09-24 11:04:54 +02:00
newPublisher [ 'webRtc' ] = {
2018-09-19 15:36:26 +02:00
kms : {
events : publisherExtended.events ,
localCandidate : publisherExtended.localCandidate ,
remoteCandidate : publisherExtended.remoteCandidate ,
receivedCandidates : publisherExtended.receivedCandidates ,
2018-11-13 17:03:57 +01:00
webrtcEndpointName : publisherExtended.webrtcEndpointName ,
localSdp : publisherExtended.localSdp ,
remoteSdp : publisherExtended.remoteSdp
2018-09-19 15:36:26 +02:00
}
} ;
2018-09-24 11:04:54 +02:00
newPublisher [ 'localCandidatePair' ] = parseRemoteCandidatePair ( newPublisher [ 'webRtc' ] . kms . remoteCandidate ) ;
2018-09-19 15:36:26 +02:00
if ( ! ! publisherExtended . serverStats ) {
2018-09-24 11:04:54 +02:00
newPublisher [ 'webRtc' ] . kms . serverStats = publisherExtended . serverStats ;
2018-09-19 15:36:26 +02:00
}
2018-09-24 11:04:54 +02:00
publisherArray . push ( newPublisher ) ;
2018-09-19 15:36:26 +02:00
} ) ;
2018-09-24 11:04:54 +02:00
const subscriberArray = [ ] ;
2018-09-19 15:36:26 +02:00
connection . subscribers . forEach ( sub = > {
const subscriberExtended = connectionExtended . subscribers . find ( s = > s . streamId === sub ) ;
const subAux = { } ;
// Standard properties
subAux [ 'streamId' ] = sub ;
subAux [ 'publisher' ] = subscriberExtended . publisher ;
// WebRtc properties
subAux [ 'createdAt' ] = subscriberExtended . createdAt ;
subAux [ 'webRtc' ] = {
kms : {
events : subscriberExtended.events ,
localCandidate : subscriberExtended.localCandidate ,
remoteCandidate : subscriberExtended.remoteCandidate ,
receivedCandidates : subscriberExtended.receivedCandidates ,
2018-11-13 17:03:57 +01:00
webrtcEndpointName : subscriberExtended.webrtcEndpointName ,
localSdp : subscriberExtended.localSdp ,
remoteSdp : subscriberExtended.remoteSdp
2018-09-19 15:36:26 +02:00
}
} ;
2018-09-24 11:04:54 +02:00
subAux [ 'localCandidatePair' ] = parseRemoteCandidatePair ( subAux [ 'webRtc' ] . kms . remoteCandidate ) ;
2018-09-19 15:36:26 +02:00
if ( ! ! subscriberExtended . serverStats ) {
subAux [ 'webRtc' ] . kms . serverStats = subscriberExtended . serverStats ;
}
2018-09-24 11:04:54 +02:00
subscriberArray . push ( subAux ) ;
2018-09-19 15:36:26 +02:00
} ) ;
2018-09-24 11:04:54 +02:00
connection . publishers = publisherArray ;
connection . subscribers = subscriberArray ;
}
} ;
const parseRemoteCandidatePair = ( candidateStr : string ) = > {
if ( ! candidateStr ) {
return 'ERROR: No remote candidate available' ;
2018-09-19 15:36:26 +02:00
}
2018-09-24 11:04:54 +02:00
const array = candidateStr . split ( /\s+/ ) ;
return {
portNumber : array [ 5 ] ,
ipAddress : array [ 4 ] ,
transport : array [ 2 ] . toLowerCase ( ) ,
candidateType : array [ 7 ] ,
priority : array [ 3 ] ,
raw : candidateStr
} ;
2018-09-19 15:36:26 +02:00
} ;
2018-10-09 16:29:28 +02:00
return new Promise < { changes : boolean , sessionChanges : ObjMap < boolean > } > ( ( resolve , reject ) = > {
2018-09-19 15:36:26 +02:00
axios . get (
'https://' + OpenVidu . hostname + ':' + OpenVidu . port + OpenVidu . API_SESSIONS + '?webRtcStats=true' ,
{
headers : {
Authorization : OpenVidu.basicAuth
}
}
)
. then ( res = > {
if ( res . status === 200 ) {
// Array to store fetched sessionIds and later remove closed sessions
const fetchedSessionIds : string [ ] = [ ] ;
2018-10-09 16:29:28 +02:00
// Global changes
let globalChanges = false ;
// Collection of sessionIds telling whether each one of them has changed or not
const sessionChanges : ObjMap < boolean > = { } ;
2018-09-19 15:36:26 +02:00
res . data . content . forEach ( session = > {
fetchedSessionIds . push ( session . sessionId ) ;
let sessionIndex = - 1 ;
let storedSession = this . activeSessions . find ( ( s , index ) = > {
if ( s . sessionId === session . sessionId ) {
sessionIndex = index ;
return true ;
} else {
return false ;
}
} ) ;
if ( ! ! storedSession ) {
const fetchedSession : Session = new Session ( ) . resetSessionWithJson ( session ) ;
2018-09-24 11:04:54 +02:00
fetchedSession . activeConnections . forEach ( connection = > {
2018-09-19 15:36:26 +02:00
addWebRtcStatsToConnections ( connection , session . connections . content ) ;
} ) ;
2018-09-24 11:04:54 +02:00
let changed = ! storedSession . equalTo ( fetchedSession ) ;
if ( ! changed ) { // Check if server webrtc information has changed in any Publisher object (Session.equalTo does not check Publisher.webRtc auxiliary object)
fetchedSession . activeConnections . forEach ( ( connection , index1 ) = > {
for ( let index2 = 0 ; ( index2 < connection [ 'publishers' ] . length && ! changed ) ; index2 ++ ) {
changed = changed || JSON . stringify ( connection [ 'publishers' ] [ index2 ] [ 'webRtc' ] ) !== JSON . stringify ( storedSession . activeConnections [ index1 ] [ 'publishers' ] [ index2 ] [ 'webRtc' ] ) ;
}
} ) ;
}
2018-09-19 15:36:26 +02:00
if ( changed ) {
storedSession = fetchedSession ;
this . activeSessions [ sessionIndex ] = storedSession ;
}
console . log ( "Available session '" + storedSession . sessionId + "' info fetched. Any change: " + changed ) ;
2018-10-09 16:29:28 +02:00
sessionChanges [ storedSession . sessionId ] = changed ;
globalChanges = globalChanges || changed ;
2018-09-19 15:36:26 +02:00
} else {
const newSession = new Session ( session ) ;
newSession . activeConnections . forEach ( connection = > {
addWebRtcStatsToConnections ( connection , session . connections . content ) ;
} ) ;
this . activeSessions . push ( newSession ) ;
console . log ( "New session '" + session . sessionId + "' info fetched" ) ;
2018-10-09 16:29:28 +02:00
sessionChanges [ session . sessionId ] = true ;
globalChanges = true ;
2018-09-19 15:36:26 +02:00
}
} ) ;
// Remove closed sessions from activeSessions array
this . activeSessions = this . activeSessions . filter ( session = > {
if ( fetchedSessionIds . includes ( session . sessionId ) ) {
return true ;
} else {
console . log ( "Removing closed session '" + session . sessionId + "'" ) ;
2018-10-09 16:29:28 +02:00
sessionChanges [ session . sessionId ] = true ;
globalChanges = true ;
2018-09-19 15:36:26 +02:00
return false ;
}
} ) ;
console . log ( 'Active sessions info fetched: ' , fetchedSessionIds ) ;
2018-10-09 16:29:28 +02:00
resolve ( { changes : globalChanges , sessionChanges } ) ;
2018-09-19 15:36:26 +02:00
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject ( new Error ( res . status . toString ( ) ) ) ;
}
} ) . catch ( error = > {
if ( error . response ) {
// The request was made and the server responded with a status code (not 2xx)
reject ( new Error ( error . response . status . toString ( ) ) ) ;
} else if ( error . request ) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console . error ( error . request ) ;
} else {
// Something happened in setting up the request that triggered an Error
console . error ( 'Error' , error . message ) ;
}
} ) ;
} ) ;
}
// tslint:enable:no-string-literal
2018-03-14 18:48:29 +01:00
private getBasicAuth ( secret : string ) : string {
2018-06-04 14:14:17 +02:00
return 'Basic ' + this . Buffer ( 'OPENVIDUAPP:' + secret ) . toString ( 'base64' ) ;
2018-01-27 19:39:49 +01:00
}
2018-03-14 18:48:29 +01:00
private setHostnameAndPort ( ) : void {
2018-04-23 11:06:16 +02:00
const urlSplitted = this . urlOpenViduServer . split ( ':' ) ;
2018-03-14 18:48:29 +01:00
if ( urlSplitted . length === 3 ) { // URL has format: http:// + hostname + :port
2018-07-22 22:13:45 +02:00
OpenVidu . hostname = this . urlOpenViduServer . split ( ':' ) [ 1 ] . replace ( /\//g , '' ) ;
OpenVidu . port = parseInt ( this . urlOpenViduServer . split ( ':' ) [ 2 ] . replace ( /\//g , '' ) ) ;
2018-04-23 11:06:16 +02:00
} else if ( urlSplitted . length === 2 ) { // URL has format: hostname + :port
2018-07-22 22:13:45 +02:00
OpenVidu . hostname = this . urlOpenViduServer . split ( ':' ) [ 0 ] . replace ( /\//g , '' ) ;
OpenVidu . port = parseInt ( this . urlOpenViduServer . split ( ':' ) [ 1 ] . replace ( /\//g , '' ) ) ;
2018-03-14 18:48:29 +01:00
} else {
console . error ( "URL format incorrect: it must contain hostname and port (current value: '" + this . urlOpenViduServer + "')" ) ;
}
2017-06-10 01:44:31 +02:00
}
2018-07-22 22:13:45 +02:00
/ * *
* @hidden
* /
static getActiveSessions ( ) : Session [ ] {
return this . o . activeSessions ;
}
2017-06-10 01:44:31 +02:00
}