mirror of https://github.com/OpenVidu/openvidu.git
openvidu-node-client: equalTo mehtods and OpenVidu.fetchWebRtc
parent
5039f5e00c
commit
1d1f9d0457
|
@ -92,4 +92,36 @@ export class Connection {
|
||||||
this.publishers = publishers;
|
this.publishers = publishers;
|
||||||
this.subscribers = subscribers;
|
this.subscribers = subscribers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
equalTo(other: Connection): boolean {
|
||||||
|
let equals: boolean = (
|
||||||
|
this.connectionId === other.connectionId &&
|
||||||
|
this.createdAt === other.createdAt &&
|
||||||
|
this.role === other.role &&
|
||||||
|
this.token === other.token &&
|
||||||
|
this.location === other.location &&
|
||||||
|
this.platform === other.platform &&
|
||||||
|
this.serverData === other.serverData &&
|
||||||
|
this.clientData === other.clientData &&
|
||||||
|
this.subscribers.length === other.subscribers.length &&
|
||||||
|
this.publishers.length === other.publishers.length);
|
||||||
|
if (equals) {
|
||||||
|
equals = JSON.stringify(this.subscribers) === JSON.stringify(other.subscribers);
|
||||||
|
if (equals) {
|
||||||
|
let i = 0;
|
||||||
|
while (equals && i < this.publishers.length) {
|
||||||
|
equals = this.publishers[i].equalTo(other.publishers[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return equals;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,12 +15,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Session } from './Session';
|
import axios from 'axios';
|
||||||
import { SessionProperties } from './SessionProperties';
|
import { Connection } from './Connection';
|
||||||
import { Recording } from './Recording';
|
import { Recording } from './Recording';
|
||||||
import { RecordingProperties } from './RecordingProperties';
|
import { RecordingProperties } from './RecordingProperties';
|
||||||
|
import { Session } from './Session';
|
||||||
|
import { SessionProperties } from './SessionProperties';
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export class OpenVidu {
|
export class OpenVidu {
|
||||||
|
|
||||||
|
@ -415,12 +416,22 @@ export class OpenVidu {
|
||||||
|
|
||||||
res.data.content.forEach(session => {
|
res.data.content.forEach(session => {
|
||||||
fetchedSessionIds.push(session.sessionId);
|
fetchedSessionIds.push(session.sessionId);
|
||||||
let storedSession = this.activeSessions.find(s => s.sessionId === 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) {
|
if (!!storedSession) {
|
||||||
const beforeJSON: string = JSON.stringify(storedSession);
|
const fetchedSession: Session = new Session().resetSessionWithJson(session);
|
||||||
storedSession = storedSession.resetSessionWithJson(session);
|
const changed: boolean = !storedSession.equalTo(fetchedSession);
|
||||||
const afterJSON: string = JSON.stringify(storedSession);
|
if (changed) {
|
||||||
const changed: boolean = !(beforeJSON === afterJSON);
|
storedSession = fetchedSession;
|
||||||
|
this.activeSessions[sessionIndex] = storedSession;
|
||||||
|
}
|
||||||
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||||
hasChanged = hasChanged || changed;
|
hasChanged = hasChanged || changed;
|
||||||
} else {
|
} else {
|
||||||
|
@ -462,6 +473,164 @@ export class OpenVidu {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
fetchWebRtc(): Promise<boolean> {
|
||||||
|
|
||||||
|
// tslint:disable:no-string-literal
|
||||||
|
const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => {
|
||||||
|
const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId);
|
||||||
|
if (!!connectionExtended) {
|
||||||
|
connection['publishersWebRtc'] = [];
|
||||||
|
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;
|
||||||
|
pubAux['audioActive'] = pub.audioActive;
|
||||||
|
pubAux['videoActive'] = pub.videoActive;
|
||||||
|
pubAux['hasAudio'] = pub.hasAudio;
|
||||||
|
pubAux['hasVideo'] = pub.hasVideo;
|
||||||
|
pubAux['typeOfVideo'] = pub.typeOfVideo;
|
||||||
|
pubAux['frameRate'] = pub.frameRate;
|
||||||
|
pubAux['videoDimensions'] = pub.videoDimensions;
|
||||||
|
// WebRtc properties
|
||||||
|
pubAux['webRtc'] = {
|
||||||
|
kms: {
|
||||||
|
events: publisherExtended.events,
|
||||||
|
localCandidate: publisherExtended.localCandidate,
|
||||||
|
remoteCandidate: publisherExtended.remoteCandidate,
|
||||||
|
receivedCandidates: publisherExtended.receivedCandidates,
|
||||||
|
webrtcTagName: publisherExtended.webrtcTagName
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!!publisherExtended.serverStats) {
|
||||||
|
pubAux['webRtc'].kms.serverStats = publisherExtended.serverStats;
|
||||||
|
}
|
||||||
|
connection['publishersWebRtc'].push(pubAux);
|
||||||
|
});
|
||||||
|
connection['subscribersWebRtc'] = [];
|
||||||
|
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,
|
||||||
|
webrtcTagName: subscriberExtended.webrtcTagName
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!!subscriberExtended.serverStats) {
|
||||||
|
subAux['webRtc'].kms.serverStats = subscriberExtended.serverStats;
|
||||||
|
}
|
||||||
|
connection['subscribersWebRtc'].push(subAux);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise<boolean>((resolve, reject) => {
|
||||||
|
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[] = [];
|
||||||
|
// Boolean to store if any Session has changed
|
||||||
|
let hasChanged = false;
|
||||||
|
|
||||||
|
res.data.content.forEach(session => {
|
||||||
|
fetchedSessionIds.push(session.sessionId);
|
||||||
|
let sessionIndex = -1;
|
||||||
|
let storedSession = this.activeSessions.find((s, index) => {
|
||||||
|
if (s.sessionId === session.sessionId) {
|
||||||
|
sessionIndex = index;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!!storedSession) {
|
||||||
|
const fetchedSession: Session = new Session().resetSessionWithJson(session);
|
||||||
|
let changed = !storedSession.equalTo(fetchedSession);
|
||||||
|
fetchedSession.activeConnections.forEach((connection, index1) => {
|
||||||
|
addWebRtcStatsToConnections(connection, session.connections.content);
|
||||||
|
if (!changed) { // Check if server information has changed in any Publisher/Subscriber
|
||||||
|
for (let index2 = 0; (index2 < connection['publishersWebRtc'].length && !changed); index2++) {
|
||||||
|
changed = changed || JSON.stringify(connection['publishersWebRtc'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishersWebRtc'][index2]['webRtc']);
|
||||||
|
}
|
||||||
|
if (!changed) {
|
||||||
|
for (let index2 = 0; (index2 < connection['subscribersWebRtc'].length && !changed); index2++) {
|
||||||
|
changed = changed || JSON.stringify(connection['subscribersWebRtc'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['subscribersWebRtc'][index2]['webRtc']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (changed) {
|
||||||
|
storedSession = fetchedSession;
|
||||||
|
this.activeSessions[sessionIndex] = storedSession;
|
||||||
|
}
|
||||||
|
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
|
||||||
|
hasChanged = hasChanged || changed;
|
||||||
|
} 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");
|
||||||
|
hasChanged = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Remove closed sessions from activeSessions array
|
||||||
|
this.activeSessions = this.activeSessions.filter(session => {
|
||||||
|
if (fetchedSessionIds.includes(session.sessionId)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
console.log("Removing closed session '" + session.sessionId + "'");
|
||||||
|
hasChanged = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Active sessions info fetched: ', fetchedSessionIds);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// tslint:enable:no-string-literal
|
||||||
|
|
||||||
private getBasicAuth(secret: string): string {
|
private getBasicAuth(secret: string): string {
|
||||||
return 'Basic ' + this.Buffer('OPENVIDUAPP:' + secret).toString('base64');
|
return 'Basic ' + this.Buffer('OPENVIDUAPP:' + secret).toString('base64');
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { OpenViduRole } from './OpenViduRole';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See [[Connection.publishers]]
|
* See [[Connection.publishers]]
|
||||||
|
@ -31,6 +30,11 @@ export class Publisher {
|
||||||
*/
|
*/
|
||||||
streamId: string;
|
streamId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timestamp when this Publisher started publishing, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
|
||||||
|
*/
|
||||||
|
createdAt: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
|
* See properties of [Stream](/api/openvidu-browser/classes/stream.html) object in OpenVidu Browser library to find out more
|
||||||
*/
|
*/
|
||||||
|
@ -66,8 +70,12 @@ export class Publisher {
|
||||||
*/
|
*/
|
||||||
videoDimensions: string;
|
videoDimensions: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
constructor(json) {
|
constructor(json) {
|
||||||
this.streamId = json.streamId;
|
this.streamId = json.streamId;
|
||||||
|
this.createdAt = json.createdAt;
|
||||||
this.hasAudio = json.mediaOptions.hasAudio;
|
this.hasAudio = json.mediaOptions.hasAudio;
|
||||||
this.hasVideo = json.mediaOptions.hasVideo;
|
this.hasVideo = json.mediaOptions.hasVideo;
|
||||||
this.audioActive = json.mediaOptions.audioActive;
|
this.audioActive = json.mediaOptions.audioActive;
|
||||||
|
@ -77,4 +85,21 @@ export class Publisher {
|
||||||
this.videoDimensions = json.mediaOptions.videoDimensions;
|
this.videoDimensions = json.mediaOptions.videoDimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
equalTo(other: Publisher): boolean {
|
||||||
|
return (
|
||||||
|
this.streamId === other.streamId &&
|
||||||
|
this.createdAt === other.createdAt &&
|
||||||
|
this.hasAudio === other.hasAudio &&
|
||||||
|
this.hasVideo === other.hasVideo &&
|
||||||
|
this.audioActive === other.audioActive &&
|
||||||
|
this.videoActive === other.videoActive &&
|
||||||
|
this.frameRate === other.frameRate &&
|
||||||
|
this.typeOfVideo === other.typeOfVideo &&
|
||||||
|
this.videoDimensions === other.videoDimensions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
import { Connection } from './Connection';
|
import { Connection } from './Connection';
|
||||||
import { MediaMode } from './MediaMode';
|
import { MediaMode } from './MediaMode';
|
||||||
import { OpenVidu } from './OpenVidu';
|
import { OpenVidu } from './OpenVidu';
|
||||||
|
@ -25,7 +26,6 @@ import { RecordingMode } from './RecordingMode';
|
||||||
import { SessionProperties } from './SessionProperties';
|
import { SessionProperties } from './SessionProperties';
|
||||||
import { TokenOptions } from './TokenOptions';
|
import { TokenOptions } from './TokenOptions';
|
||||||
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export class Session {
|
export class Session {
|
||||||
|
|
||||||
|
@ -429,6 +429,7 @@ export class Session {
|
||||||
*/
|
*/
|
||||||
public resetSessionWithJson(json): Session {
|
public resetSessionWithJson(json): Session {
|
||||||
this.sessionId = json.sessionId;
|
this.sessionId = json.sessionId;
|
||||||
|
this.createdAt = json.createdAt;
|
||||||
this.recording = json.recording;
|
this.recording = json.recording;
|
||||||
let customSessionId: string;
|
let customSessionId: string;
|
||||||
let defaultCustomLayout: string;
|
let defaultCustomLayout: string;
|
||||||
|
@ -474,4 +475,27 @@ export class Session {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hidden
|
||||||
|
*/
|
||||||
|
equalTo(other: Session): boolean {
|
||||||
|
let equals: boolean = (
|
||||||
|
this.sessionId === other.sessionId &&
|
||||||
|
this.createdAt === other.createdAt &&
|
||||||
|
this.recording === other.recording &&
|
||||||
|
this.activeConnections.length === other.activeConnections.length &&
|
||||||
|
JSON.stringify(this.properties) === JSON.stringify(other.properties)
|
||||||
|
);
|
||||||
|
if (equals) {
|
||||||
|
let i = 0;
|
||||||
|
while (equals && i < this.activeConnections.length) {
|
||||||
|
equals = this.activeConnections[i].equalTo(other.activeConnections[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return equals;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue