openvidu-node-client: support 2.3.0 REST API

pull/87/merge
pabloFuente 2018-07-22 22:13:45 +02:00
parent 12f8f8ecd3
commit 42a4feb1d9
13 changed files with 617 additions and 50 deletions

View File

@ -0,0 +1,77 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { OpenViduRole } from './OpenViduRole';
import { Publisher } from './Publisher';
/**
* See [[Session.activeConnections]]
*/
export class Connection {
/**
* Identifier of the connection. You can call [[Session.forceDisconnect]] passing this property as parameter
*/
connectionId: string;
/**
* Role of the connection
*/
role: OpenViduRole;
/**
* Token associated to the connection
*/
token: string;
/**
* Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]]
*/
serverData: string;
/**
* Data associated to the connection on the client-side. This value is set with second parameter of method
* [Session.connect](/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser
*/
clientData: string;
/**
* Array of Publisher objects this particular Connection is publishing to the Session (each Publisher object has one Stream, uniquely
* identified by its `streamId`). You can call [[Session.forceUnpublish]] passing any of this values as parameter
*/
publishers: Publisher[] = [];
/**
* Array of streams (their `streamId` properties) this particular Connection is subscribed to. Each one always corresponds to one
* Publisher of some other Connection: each string of this array must be equal to one [[Publisher.streamId]] of other Connection
*/
subscribers: string[] = [];
/**
* @hidden
*/
constructor(connectionId: string, role: OpenViduRole, token: string, serverData: string, clientData: string,
publishers: Publisher[], subscribers: string[]) {
this.connectionId = connectionId;
this.role = role;
this.token = token;
this.serverData = serverData;
this.clientData = clientData;
this.publishers = publishers;
this.subscribers = subscribers;
}
}

View File

@ -15,6 +15,9 @@
*
*/
/**
* See [[SessionProperties.mediaMode]]
*/
export enum MediaMode {
/**

View File

@ -24,34 +24,82 @@ import axios from 'axios';
export class OpenVidu {
private static readonly API_RECORDINGS: string = '/api/recordings';
private static readonly API_RECORDINGS_START: string = '/start';
private static readonly API_RECORDINGS_STOP: string = '/stop';
private hostname: string;
private port: number;
private basicAuth: string;
private Buffer = require('buffer/').Buffer;
/**
* @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[] = [];
/**
* @param urlOpenViduServer Public accessible IP where your instance of OpenVidu Server is up an running
* @param secret Secret used on OpenVidu Server initialization
*/
constructor(private urlOpenViduServer: string, secret: string) {
this.setHostnameAndPort();
this.basicAuth = this.getBasicAuth(secret);
OpenVidu.basicAuth = this.getBasicAuth(secret);
OpenVidu.o = this;
}
/**
* Creates an OpenVidu session. You can call [[Session.getSessionId]] in the resolved promise to retrieve the `sessionId`
* Creates an OpenVidu session. You can call [[Session.getSessionId]] inside the resolved promise to retrieve the `sessionId`
*
* @returns A Promise that is resolved to the [[Session]] if success and rejected with an Error object if not.
*/
public createSession(properties?: SessionProperties): Promise<Session> {
return new Promise<Session>((resolve, reject) => {
const session = new Session(this.hostname, this.port, this.basicAuth, properties);
const session = new Session(properties);
session.getSessionIdHttp()
.then(sessionId => {
this.activeSessions.push(session);
resolve(session);
})
.catch(error => {
@ -69,6 +117,7 @@ export class OpenVidu {
*
* @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`)
* **WARNING: this parameter follows an overwriting policy.** If you name two recordings the same, the newest MP4 file will overwrite the oldest one
*
* @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:
* - `404`: no session exists for the passed `sessionId`
@ -108,11 +157,11 @@ export class OpenVidu {
}
axios.post(
'https://' + this.hostname + ':' + this.port + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_START,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_START,
data,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/json'
}
}
@ -120,7 +169,9 @@ export class OpenVidu {
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server (Recording in JSON format). Resolve new Recording
resolve(new Recording(res.data));
const r: Recording = new Recording(res.data);
this.activeSessions.find(s => s.sessionId === r.sessionId).recording = true;
resolve(r);
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
@ -155,11 +206,11 @@ export class OpenVidu {
return new Promise<Recording>((resolve, reject) => {
axios.post(
'https://' + this.hostname + ':' + this.port + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_RECORDINGS + OpenVidu.API_RECORDINGS_STOP + '/' + recordingId,
undefined,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
@ -167,7 +218,9 @@ export class OpenVidu {
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server (Recording in JSON format). Resolve new Recording
resolve(new Recording(res.data));
const r: Recording = new Recording(res.data);
this.activeSessions.find(s => s.sessionId === r.sessionId).recording = false;
resolve(r);
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
@ -177,9 +230,8 @@ export class OpenVidu {
// 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
// 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
@ -201,10 +253,10 @@ export class OpenVidu {
return new Promise<Recording>((resolve, reject) => {
axios.get(
'https://' + this.hostname + ':' + this.port + OpenVidu.API_RECORDINGS + '/' + recordingId,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_RECORDINGS + '/' + recordingId,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
@ -243,11 +295,10 @@ export class OpenVidu {
return new Promise<Recording[]>((resolve, reject) => {
axios.get(
'https://' + this.hostname + ':' + this.port + OpenVidu.API_RECORDINGS,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_RECORDINGS,
{
headers: {
'Authorization': this.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
Authorization: OpenVidu.basicAuth
}
}
)
@ -294,10 +345,10 @@ export class OpenVidu {
return new Promise<Error>((resolve, reject) => {
axios.delete(
'https://' + this.hostname + ':' + this.port + OpenVidu.API_RECORDINGS + '/' + recordingId,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_RECORDINGS + '/' + recordingId,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
@ -327,6 +378,76 @@ export class OpenVidu {
});
}
/**
* 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);
let storedSession = this.activeSessions.find(s => s.sessionId === session.sessionId);
if (!!storedSession) {
const beforeJSON: string = JSON.stringify(storedSession);
storedSession = storedSession.resetSessionWithJson(session);
const afterJSON: string = JSON.stringify(storedSession);
const changed: boolean = !(beforeJSON === afterJSON);
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;
}
// Remove closed sessions from activeSessions array
this.activeSessions = this.activeSessions.filter(session => (!!fetchedSessionIds.find(sId => sId === session.sessionId)));
console.log('Active sessions info fetched: ', fetchedSessionIds);
});
if (res.data.content.length === 0) {
console.warn('No active sessions');
}
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);
}
});
});
}
private getBasicAuth(secret: string): string {
return 'Basic ' + this.Buffer('OPENVIDUAPP:' + secret).toString('base64');
}
@ -334,14 +455,21 @@ export class OpenVidu {
private setHostnameAndPort(): void {
const urlSplitted = this.urlOpenViduServer.split(':');
if (urlSplitted.length === 3) { // URL has format: http:// + hostname + :port
this.hostname = this.urlOpenViduServer.split(':')[1].replace(/\//g, '');
this.port = parseInt(this.urlOpenViduServer.split(':')[2].replace(/\//g, ''));
OpenVidu.hostname = this.urlOpenViduServer.split(':')[1].replace(/\//g, '');
OpenVidu.port = parseInt(this.urlOpenViduServer.split(':')[2].replace(/\//g, ''));
} else if (urlSplitted.length === 2) { // URL has format: hostname + :port
this.hostname = this.urlOpenViduServer.split(':')[0].replace(/\//g, '');
this.port = parseInt(this.urlOpenViduServer.split(':')[1].replace(/\//g, ''));
OpenVidu.hostname = this.urlOpenViduServer.split(':')[0].replace(/\//g, '');
OpenVidu.port = parseInt(this.urlOpenViduServer.split(':')[1].replace(/\//g, ''));
} else {
console.error("URL format incorrect: it must contain hostname and port (current value: '" + this.urlOpenViduServer + "')");
}
}
/**
* @hidden
*/
static getActiveSessions(): Session[] {
return this.o.activeSessions;
}
}

View File

@ -15,6 +15,9 @@
*
*/
/**
* See [[TokenOptions.role]]
*/
export enum OpenViduRole {
/**

View File

@ -0,0 +1,80 @@
/*
* (C) Copyright 2017-2018 OpenVidu (https://openvidu.io/)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
import { OpenViduRole } from './OpenViduRole';
/**
* See [[Connection.publishers]]
*
* This is a backend representation of a published media stream (see [OpenVidu Browser Stream class](/api/openvidu-browser/classes/stream.html))
*/
export class Publisher {
/**
* Unique identifier of the [Stream](/api/openvidu-browser/classes/stream.html) associated to this Publisher.
* Each Publisher is paired with only one Stream, so you can identify each Publisher by its
* [`Stream.streamId`](/api/openvidu-browser/classes/stream.html#streamid)
*/
streamId: string;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
hasAudio: boolean;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
hasVideo: boolean;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
audioActive: boolean;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
videoActive: boolean;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
frameRate: number;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
typeOfVideo: string;
/**
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
*/
videoDimensions: string;
constructor(json) {
this.streamId = json.streamId;
this.hasAudio = json.mediaOptions.hasAudio;
this.hasVideo = json.mediaOptions.hasVideo;
this.audioActive = json.mediaOptions.audioActive;
this.videoActive = json.mediaOptions.videoActive;
this.frameRate = json.mediaOptions.frameRate;
this.typeOfVideo = json.mediaOptions.typeOfVideo;
this.videoDimensions = json.mediaOptions.videoDimensions;
}
}

View File

@ -17,6 +17,9 @@
import { RecordingLayout } from './RecordingLayout';
/**
* See [[OpenVidu.startRecording]]
*/
export class Recording {
/**
@ -77,6 +80,9 @@ export class Recording {
recordingLayout: RecordingLayout;
/* tslint:disable:no-string-literal */
/**
* @hidden
*/
constructor(json: JSON) {
this.id = json['id'];
this.sessionId = json['sessionId'];
@ -94,6 +100,10 @@ export class Recording {
}
export namespace Recording {
/**
* See [[Recording.status]]
*/
export enum Status {
/**
@ -114,7 +124,7 @@ export namespace Recording {
/**
* The recording is available for downloading. This status is reached for all
* stopped recordings if [OpenVidu Server configuration](https://openvidu.io/docs/reference-docs/openvidu-server-params/)
* property <code>openvidu.recording.public-access</code> is true
* property `openvidu.recording.public-access` is true
*/
available,

View File

@ -15,6 +15,9 @@
*
*/
/**
* See [[SessionProperties.defaultRecordingLayout]] and [[RecordingProperties.recordingLayout]]
*/
export enum RecordingLayout {
/**

View File

@ -15,6 +15,9 @@
*
*/
/**
* See [[SessionProperties.recordingMode]]
*/
export enum RecordingMode {
/**

View File

@ -17,10 +17,14 @@
import { RecordingLayout } from './RecordingLayout';
/**
* See [[OpenVidu.startRecording]]
*/
export interface RecordingProperties {
/**
* The name you want to give to the video file. You can access this same value in your clients on recording events (`recordingStarted`, `recordingStopped`)
* The name you want to give to the video file. You can access this same value in your clients on recording events (`recordingStarted`, `recordingStopped`).
* **WARNING: this parameter follows an overwriting policy.** If you name two recordings the same, the newest MP4 file will overwrite the oldest one
*/
name?: string;

View File

@ -15,8 +15,11 @@
*
*/
import { Connection } from './Connection';
import { MediaMode } from './MediaMode';
import { OpenVidu } from './OpenVidu';
import { OpenViduRole } from './OpenViduRole';
import { Publisher } from './Publisher';
import { RecordingLayout } from './RecordingLayout';
import { RecordingMode } from './RecordingMode';
import { SessionProperties } from './SessionProperties';
@ -26,20 +29,53 @@ import axios from 'axios';
export class Session {
private static readonly API_SESSIONS = '/api/sessions';
private static readonly API_TOKENS = '/api/tokens';
/**
* Unique identifier of the Session
*/
sessionId: string;
/**
* Properties defining the session
*/
properties: SessionProperties;
private Buffer = require('buffer/').Buffer;
/**
* Array of active connections to the session. This property always initialize as an empty array and
* **will remain unchanged since the last time method [[Session.fetch]] was called**. Exceptions to this rule are:
*
* - Calling [[Session.forceUnpublish]] also automatically updates each affected Connection status
* - Calling [[Session.forceDisconnect]] automatically updates each affected Connection status
*
* To get the array of active connections with their current actual value, you must call [[Session.fetch]] before consulting
* property [[activeConnections]]
*/
activeConnections: Connection[] = [];
constructor(private hostname: string, private port: number, private basicAuth: string, properties?: SessionProperties) {
if (!properties) {
this.properties = {};
/**
* Whether the session is being recorded or not
*/
recording = false;
/**
* @hidden
*/
constructor(propertiesOrJson?) {
if (!!propertiesOrJson) {
// Defined parameter
if (!!propertiesOrJson.sessionId) {
// Parameter is a JSON representation of Session ('sessionId' property always defined)
this.resetSessionWithJson(propertiesOrJson);
} else {
// Parameter is a SessionProperties object
this.properties = propertiesOrJson;
}
} else {
this.properties = properties;
// Empty parameter
this.properties = {};
}
this.properties.mediaMode = !!this.properties.mediaMode ? this.properties.mediaMode : MediaMode.ROUTED;
this.properties.recordingMode = !!this.properties.recordingMode ? this.properties.recordingMode : RecordingMode.MANUAL;
this.properties.defaultRecordingLayout = !!this.properties.defaultRecordingLayout ? this.properties.defaultRecordingLayout : RecordingLayout.BEST_FIT;
}
/**
@ -64,11 +100,11 @@ export class Session {
});
axios.post(
'https://' + this.hostname + ':' + this.port + Session.API_TOKENS,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_TOKENS,
data,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/json'
}
}
@ -101,15 +137,15 @@ export class Session {
/**
* Gracefully closes the Session: unpublishes all streams and evicts every participant
*
* @returns A Promise that is resolved to the if the session has been closed successfully and rejected with an Error object if not
* @returns A Promise that is resolved if the session has been closed successfully and rejected with an Error object if not
*/
public close() {
return new Promise<string>((resolve, reject) => {
public close(): Promise<any> {
return new Promise<any>((resolve, reject) => {
axios.delete(
'https://' + this.hostname + ':' + this.port + Session.API_SESSIONS + '/' + this.sessionId,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS + '/' + this.sessionId,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
@ -117,6 +153,176 @@ export class Session {
.then(res => {
if (res.status === 204) {
// SUCCESS response from openvidu-server
const indexToRemove: number = OpenVidu.getActiveSessions().findIndex(s => s.sessionId === this.sessionId);
OpenVidu.getActiveSessions().splice(indexToRemove, 1);
resolve();
} 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);
}
});
});
}
/**
* Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of active
* connections to the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]] or [[Session.forceUnpublish]]
*
* @returns A promise resolved to true if the Session status has changed with respect to the server, or to false if not.
* This applies to any property or sub-property of the Session object
*/
public fetch(): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
const beforeJSON: string = JSON.stringify(this);
axios.get(
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS + '/' + this.sessionId,
{
headers: {
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server
this.resetSessionWithJson(res.data);
const afterJSON: string = JSON.stringify(this);
const hasChanged: boolean = !(beforeJSON === afterJSON);
console.log("Session info fetched for session '" + this.sessionId + "'. Any change: " + hasChanged);
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);
}
});
});
}
/**
* Forces the user with Connection `connectionId` to leave the session. OpenVidu Browser will trigger the proper events on the client-side
* (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`
*
* You can get `connection` parameter from [[Session.activeConnections]] array ([[Connection.connectionId]] for getting each `connectionId` property).
* Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
*
* @returns A Promise that is resolved if the user was successfully disconnected and rejected with an Error object if not
*/
public forceDisconnect(connection: string | Connection): Promise<any> {
return new Promise<any>((resolve, reject) => {
const connectionId: string = typeof connection === 'string' ? connection : (<Connection>connection).connectionId;
axios.delete(
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection/' + connectionId,
{
headers: {
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(res => {
if (res.status === 204) {
// SUCCESS response from openvidu-server
// Remove connection from activeConnections array
let connectionClosed;
this.activeConnections = this.activeConnections.filter(con => {
if (con.connectionId !== connectionId) {
return true;
} else {
connectionClosed = con;
return false;
}
});
// Remove every Publisher of the closed connection from every subscriber list of other connections
if (!!connectionClosed) {
connectionClosed.publishers.forEach(publisher => {
this.activeConnections.forEach(con => {
con.subscribers = con.subscribers.filter(subscriber => subscriber !== publisher.streamId);
});
});
} else {
console.warn("The closed connection wasn't fetched in OpenVidu Java Client. No changes in the collection of active connections of the Session");
}
console.log("Connection '" + connectionId + "' closed");
resolve();
} 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);
}
});
});
}
/**
* Forces some user to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it).
* OpenVidu Browser will trigger the proper events on the client-side (`streamDestroyed`) with reason set to `"forceUnpublishByServer"`.
*
* You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property).
* Remember to call [[Session.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server
*
* @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not
*/
public forceUnpublish(publisher: string | Publisher): Promise<any> {
return new Promise<any>((resolve, reject) => {
const streamId: string = typeof publisher === 'string' ? publisher : (<Publisher>publisher).streamId;
axios.delete(
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/stream/' + streamId,
{
headers: {
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
)
.then(res => {
if (res.status === 204) {
// SUCCESS response from openvidu-server
this.activeConnections.forEach(connection => {
// Try to remove the Publisher from the Connection publishers collection
connection.publishers = connection.publishers.filter(pub => pub.streamId !== streamId);
// Try to remove the Publisher from the Connection subscribers collection
connection.subscribers = connection.subscribers.filter(sub => sub !== streamId);
});
console.log("Stream '" + streamId + "' unpublished");
resolve();
} else {
// ERROR response from openvidu-server. Resolve HTTP status
@ -158,11 +364,11 @@ export class Session {
});
axios.post(
'https://' + this.hostname + ':' + this.port + Session.API_SESSIONS,
'https://' + OpenVidu.hostname + ':' + OpenVidu.port + OpenVidu.API_SESSIONS,
data,
{
headers: {
'Authorization': this.basicAuth,
'Authorization': OpenVidu.basicAuth,
'Content-Type': 'application/json'
}
}
@ -199,4 +405,43 @@ export class Session {
});
}
/**
* @hidden
*/
public resetSessionWithJson(json): Session {
this.sessionId = json.sessionId;
this.recording = json.recording;
let customSessionId: string;
let defaultCustomLayout: string;
if (!!this.properties) {
customSessionId = this.properties.customSessionId;
defaultCustomLayout = !!json.defaultCustomLayout ? json.defaultCustomLayout : this.properties.defaultCustomLayout;
}
this.properties = {
mediaMode: json.mediaMode,
recordingMode: json.recordingMode,
defaultRecordingLayout: json.defaultRecordingLayout
};
if (!!customSessionId) {
this.properties.customSessionId = customSessionId;
}
if (!!defaultCustomLayout) {
this.properties.defaultCustomLayout = defaultCustomLayout;
}
this.activeConnections = [];
json.connections.content.forEach(connection => {
const publishers: Publisher[] = [];
connection.publishers.forEach(publisher => {
publishers.push(new Publisher(publisher));
});
const subscribers: string[] = [];
connection.subscribers.forEach(subscriber => {
subscribers.push(subscriber.streamId);
});
this.activeConnections.push(new Connection(connection.connectionId, connection.role, connection.token, connection.serverData, connection.clientData, publishers, subscribers));
});
return this;
}
}

View File

@ -19,6 +19,9 @@ import { MediaMode } from './MediaMode';
import { RecordingLayout } from './RecordingLayout';
import { RecordingMode } from './RecordingMode';
/**
* See [[OpenVidu.createSession]]
*/
export interface SessionProperties {
/**
@ -34,12 +37,15 @@ export interface SessionProperties {
/**
* Default value used to initialize property [[RecordingProperties.recordingLayout]] of every recording of this session.
*
* You can easily override this value later by setting [[RecordingProperties.recordingLayout]] to any other value
*/
defaultRecordingLayout?: RecordingLayout;
/**
* Default value used to initialize property [[RecordingProperties.customLayout]] of every recording of this session.
* This property can only be defined if [[SessionProperties.defaultRecordingLayout]] is set to [[RecordingLayout.CUSTOM]].
*
* You can easily override this value later by setting [[RecordingProperties.customLayout]] to any other value
*/
defaultCustomLayout?: string;

View File

@ -17,6 +17,9 @@
import { OpenViduRole } from './OpenViduRole';
/**
* See [[Session.generateToken]]
*/
export interface TokenOptions {
/**

View File

@ -8,3 +8,5 @@ export * from './RecordingLayout';
export * from './RecordingMode';
export * from './Recording';
export * from './RecordingProperties';
export * from './Connection';
export * from './Publisher';