OpenVidu SDKs: update with improved reset process

pull/553/head
pabloFuente 2020-10-16 13:45:15 +02:00
parent 77a63a8e54
commit b4c1df1878
8 changed files with 375 additions and 240 deletions

View File

@ -18,8 +18,10 @@
package io.openvidu.java.client;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.gson.JsonArray;
@ -42,50 +44,7 @@ public class Connection {
protected List<String> subscribers = new ArrayList<>();
protected Connection(JsonObject json) {
// These properties may be null
if (!json.get("publishers").isJsonNull()) {
JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray();
jsonArrayPublishers.forEach(publisher -> {
JsonObject pubJson = publisher.getAsJsonObject();
JsonObject mediaOptions = pubJson.get("mediaOptions").getAsJsonObject();
Publisher pub = new Publisher(pubJson.get("streamId").getAsString(),
pubJson.get("createdAt").getAsLong(), mediaOptions.get("hasAudio").getAsBoolean(),
mediaOptions.get("hasVideo").getAsBoolean(), mediaOptions.get("audioActive"),
mediaOptions.get("videoActive"), mediaOptions.get("frameRate"), mediaOptions.get("typeOfVideo"),
mediaOptions.get("videoDimensions"));
this.publishers.put(pub.getStreamId(), pub);
});
}
if (!json.get("subscribers").isJsonNull()) {
JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray();
jsonArraySubscribers.forEach(subscriber -> {
this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString());
});
}
if (!json.get("createdAt").isJsonNull()) {
this.createdAt = json.get("createdAt").getAsLong();
}
if (!json.get("location").isJsonNull()) {
this.location = json.get("location").getAsString();
}
if (!json.get("platform").isJsonNull()) {
this.platform = json.get("platform").getAsString();
}
if (!json.get("clientData").isJsonNull()) {
this.clientData = json.get("clientData").getAsString();
}
// These properties won't ever be null
this.connectionId = json.get("connectionId").getAsString();
this.status = json.get("status").getAsString();
String token = json.has("token") ? json.get("token").getAsString() : null;
OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString());
String data = json.get("serverData").getAsString();
Boolean record = json.get("record").getAsBoolean();
TokenOptions tokenOptions = new TokenOptions(role, data, record, null);
this.token = new Token(token, this.connectionId, tokenOptions);
this.resetWithJson(json);
}
/**
@ -248,4 +207,81 @@ public class Connection {
this.subscribers = subscribers;
}
protected Connection resetWithJson(JsonObject json) {
if (!json.get("publishers").isJsonNull()) {
JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray();
// 1. Set to store fetched publishers and later remove closed ones
Set<String> fetchedPublisherIds = new HashSet<>();
jsonArrayPublishers.forEach(publisherJsonElement -> {
JsonObject publisherJson = publisherJsonElement.getAsJsonObject();
Publisher publisherObj = new Publisher(publisherJson);
String id = publisherObj.getStreamId();
fetchedPublisherIds.add(id);
// 2. Update existing Publisher
this.publishers.computeIfPresent(id, (pId, p) -> {
p = p.resetWithJson(publisherJson);
return p;
});
// 3. Add new Publisher
this.publishers.computeIfAbsent(id, pId -> {
return publisherObj;
});
});
// 4. Remove closed connections from local collection
this.publishers.entrySet().removeIf(entry -> !fetchedPublisherIds.contains(entry.getValue().getStreamId()));
}
if (!json.get("subscribers").isJsonNull()) {
JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray();
// 1. Array to store fetched Subscribers and later remove closed ones
Set<String> fetchedSubscriberIds = new HashSet<>();
jsonArraySubscribers.forEach(subscriber -> {
String sub = subscriber.getAsJsonObject().get("streamId").getAsString();
fetchedSubscriberIds.add(sub);
if (!this.subscribers.contains(sub)) {
// 2. Add new Subscriber
this.subscribers.add(sub);
}
});
// 3. Remove closed Subscribers from local collection
this.subscribers.removeIf(subId -> !fetchedSubscriberIds.contains(subId));
}
if (!json.get("createdAt").isJsonNull()) {
this.createdAt = json.get("createdAt").getAsLong();
}
if (!json.get("location").isJsonNull()) {
this.location = json.get("location").getAsString();
}
if (!json.get("platform").isJsonNull()) {
this.platform = json.get("platform").getAsString();
}
if (!json.get("clientData").isJsonNull()) {
this.clientData = json.get("clientData").getAsString();
}
// These properties won't ever be null
this.connectionId = json.get("connectionId").getAsString();
this.status = json.get("status").getAsString();
String token = json.has("token") ? json.get("token").getAsString() : null;
OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString());
String data = json.get("serverData").getAsString();
Boolean record = json.get("record").getAsBoolean();
TokenOptions tokenOptions = new TokenOptions(role, data, record, null);
this.token = new Token(token, this.connectionId, tokenOptions);
return this;
}
}

View File

@ -31,7 +31,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.net.ssl.SSLContext;
@ -549,44 +548,55 @@ public class OpenVidu {
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
JsonObject jsonSessions = httpResponseToJson(response);
JsonArray jsonArraySessions = jsonSessions.get("content").getAsJsonArray();
// Set to store fetched sessionIds and later remove closed sessions
Set<String> fetchedSessionIds = new HashSet<>();
// Boolean to store if any Session has changed
final boolean[] hasChanged = { false };
jsonArraySessions.forEach(session -> {
String sessionId = (session.getAsJsonObject()).get("sessionId").getAsString();
fetchedSessionIds.add(sessionId);
this.activeSessions.computeIfPresent(sessionId, (sId, s) -> {
// 1. Set to store fetched sessionIds and later remove closed ones
Set<String> fetchedSessionIds = new HashSet<>();
jsonArraySessions.forEach(sessionJsonElement -> {
JsonObject sessionJson = sessionJsonElement.getAsJsonObject();
final Session sessionObj = new Session(this, sessionJson);
String id = sessionObj.getSessionId();
fetchedSessionIds.add(id);
// 2. Update existing Session
this.activeSessions.computeIfPresent(id, (sId, s) -> {
String beforeJSON = s.toJson();
s = s.resetSessionWithJson(session.getAsJsonObject());
s = s.resetWithJson(sessionJson);
String afterJSON = s.toJson();
boolean changed = !beforeJSON.equals(afterJSON);
hasChanged[0] = hasChanged[0] || changed;
log.info("Available session '{}' info fetched. Any change: {}", sessionId, changed);
log.info("Available session '{}' info fetched. Any change: {}", id, changed);
return s;
});
this.activeSessions.computeIfAbsent(sessionId, sId -> {
log.info("New session '{}' fetched", sessionId);
// 3. Add new Session
this.activeSessions.computeIfAbsent(id, sId -> {
log.info("New session '{}' fetched", id);
hasChanged[0] = true;
return new Session(this, session.getAsJsonObject());
return sessionObj;
});
});
// Remove closed sessions from activeSessions map
this.activeSessions = this.activeSessions.entrySet().stream().filter(entry -> {
// 4. Remove closed sessions from local collection
this.activeSessions.entrySet().removeIf(entry -> {
if (fetchedSessionIds.contains(entry.getKey())) {
return true;
return false;
} else {
log.info("Removing closed session {}", entry.getKey());
hasChanged[0] = true;
return false;
return true;
}
}).collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
});
log.info("Active sessions info fetched: {}", this.activeSessions.keySet());
return hasChanged[0];
} else {
throw new OpenViduHttpException(statusCode);
}

View File

@ -17,16 +17,15 @@
package io.openvidu.java.client;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
/**
* See {@link io.openvidu.java.client.Connection#getPublishers()}.
*
* <br>
* This is a backend representation of a published media stream (see
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target="_blank"> OpenVidu
* Browser Stream class</a>).
* This is a backend representation of a published media stream (see <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target="_blank"> OpenVidu Browser Stream class</a>).
*/
public class Publisher {
@ -40,36 +39,18 @@ public class Publisher {
private String typeOfVideo;
private String videoDimensions;
protected Publisher(String streamId, long createdAt, boolean hasAudio, boolean hasVideo, JsonElement audioActive,
JsonElement videoActive, JsonElement frameRate, JsonElement typeOfVideo, JsonElement videoDimensions) {
this.streamId = streamId;
this.createdAt = createdAt;
this.hasAudio = hasAudio;
this.hasVideo = hasVideo;
if (audioActive != null && !audioActive.isJsonNull()) {
this.audioActive = audioActive.getAsBoolean();
}
if (videoActive != null && !videoActive.isJsonNull()) {
this.videoActive = videoActive.getAsBoolean();
}
if (frameRate != null && !frameRate.isJsonNull()) {
this.frameRate = frameRate.getAsInt();
}
if (typeOfVideo != null && !typeOfVideo.isJsonNull()) {
this.typeOfVideo = typeOfVideo.getAsString();
}
if (videoDimensions != null && !videoDimensions.isJsonNull()) {
this.videoDimensions = videoDimensions.getAsString();
}
protected Publisher(JsonObject json) {
this.resetWithJson(json);
}
/**
* Returns the unique identifier of the
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> associated to this Publisher. Each Publisher is paired
* with only one Stream, so you can identify each Publisher by its
* <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html#streamid" target=
* "_blank"><code>Stream.streamId</code></a>
* Returns the unique identifier of the <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> associated to this Publisher. Each Publisher is
* paired with only one Stream, so you can identify each Publisher by its
* <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html#streamid"
* target= "_blank"><code>Stream.streamId</code></a>
*/
public String getStreamId() {
return streamId;
@ -84,56 +65,70 @@ public class Publisher {
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public boolean hasVideo() {
return this.hasVideo;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public boolean hasAudio() {
return this.hasAudio;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public Boolean isAudioActive() {
return this.audioActive;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public Boolean isVideoActive() {
return this.videoActive;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public Integer getFrameRate() {
return this.frameRate;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public String getTypeOfVideo() {
return this.typeOfVideo;
}
/**
* See properties of <a href="https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html" target=
* "_blank">Stream</a> object in OpenVidu Browser library to find out more
* See properties of <a href=
* "https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/stream.html"
* target= "_blank">Stream</a> object in OpenVidu Browser library to find out
* more
*/
public String getVideoDimensions() {
return this.videoDimensions;
@ -152,4 +147,32 @@ public class Publisher {
return json;
}
protected Publisher resetWithJson(JsonObject json) {
this.streamId = json.get("streamId").getAsString();
this.createdAt = json.get("createdAt").getAsLong();
if (json.has("mediaOptions") && !json.get("mediaOptions").isJsonNull()) {
JsonObject mediaOptions = json.get("mediaOptions").getAsJsonObject();
this.hasAudio = mediaOptions.get("hasAudio").getAsBoolean();
this.hasVideo = mediaOptions.get("hasVideo").getAsBoolean();
if (mediaOptions.has("audioActive") && !mediaOptions.get("audioActive").isJsonNull()) {
this.audioActive = mediaOptions.get("audioActive").getAsBoolean();
}
if (mediaOptions.has("videoActive") && !mediaOptions.get("videoActive").isJsonNull()) {
this.videoActive = mediaOptions.get("videoActive").getAsBoolean();
}
if (mediaOptions.has("frameRate") && !mediaOptions.get("frameRate").isJsonNull()) {
this.frameRate = mediaOptions.get("frameRate").getAsInt();
}
if (mediaOptions.has("typeOfVideo") && !mediaOptions.get("typeOfVideo").isJsonNull()) {
this.typeOfVideo = mediaOptions.get("typeOfVideo").getAsString();
}
if (mediaOptions.has("videoDimensions") && !mediaOptions.get("videoDimensions").isJsonNull()) {
this.videoDimensions = mediaOptions.get("videoDimensions").getAsString();
}
}
return this;
}
}

View File

@ -19,8 +19,10 @@ package io.openvidu.java.client;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
@ -66,7 +68,7 @@ public class Session {
protected Session(OpenVidu openVidu, JsonObject json) {
this.openVidu = openVidu;
this.resetSessionWithJson(json);
this.resetWithJson(json);
}
/**
@ -282,7 +284,7 @@ public class Session {
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
this.resetSessionWithJson(httpResponseToJson(response));
this.resetWithJson(httpResponseToJson(response));
final String afterJSON = this.toJson();
boolean hasChanged = !beforeJSON.equals(afterJSON);
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
@ -694,7 +696,7 @@ public class Session {
this.recording = recording;
}
protected Session resetSessionWithJson(JsonObject json) {
protected Session resetWithJson(JsonObject json) {
this.sessionId = json.get("sessionId").getAsString();
this.createdAt = json.get("createdAt").getAsLong();
this.recording = json.get("recording").getAsBoolean();
@ -708,18 +710,37 @@ public class Session {
if (json.has("defaultCustomLayout")) {
builder.defaultCustomLayout(json.get("defaultCustomLayout").getAsString());
}
if (this.properties != null && this.properties.customSessionId() != null) {
builder.customSessionId(this.properties.customSessionId());
} else if (json.has("customSessionId")) {
if (json.has("customSessionId")) {
builder.customSessionId(json.get("customSessionId").getAsString());
}
this.properties = builder.build();
JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray();
this.connections.clear();
// 1. Set to store fetched connections and later remove closed ones
Set<String> fetchedConnectionIds = new HashSet<>();
jsonArrayConnections.forEach(connectionJsonElement -> {
Connection connectionObj = new Connection(connectionJsonElement.getAsJsonObject());
this.connections.put(connectionObj.getConnectionId(), connectionObj);
JsonObject connectionJson = connectionJsonElement.getAsJsonObject();
Connection connectionObj = new Connection(connectionJson);
String id = connectionObj.getConnectionId();
fetchedConnectionIds.add(id);
// 2. Update existing Connection
this.connections.computeIfPresent(id, (cId, c) -> {
c = c.resetWithJson(connectionJson);
return c;
});
// 3. Add new Connection
this.connections.computeIfAbsent(id, cId -> {
return connectionObj;
});
});
// 4. Remove closed connections from local collection
this.connections.entrySet()
.removeIf(entry -> !fetchedConnectionIds.contains(entry.getValue().getConnectionId()));
return this;
}

View File

@ -100,21 +100,13 @@ export class Connection {
* @hidden
*/
constructor(json) {
// These properties may be null
if (json.publishers != null) {
json.publishers.forEach(publisher => {
this.publishers.push(new Publisher(publisher));
});
this.resetWithJson(json);
}
if (json.subscribers != null) {
json.subscribers.forEach(subscriber => {
this.subscribers.push(subscriber.streamId);
});
}
this.createdAt = json.createdAt;
this.location = json.location;
this.platform = json.platform;
this.clientData = json.clientData;
/**
* @hidden
*/
resetWithJson(json): Connection {
// These properties won't ever be null
this.connectionId = json.connectionId;
@ -123,6 +115,62 @@ export class Connection {
this.role = json.role;
this.serverData = json.serverData;
this.record = json.record;
// These properties may be null
if (json.publishers != null) {
// 1. Array to store fetched Publishers and later remove closed ones
const fetchedPublisherIds: string[] = [];
json.publishers.forEach(jsonPublisher => {
const publisherObj: Publisher = new Publisher(jsonPublisher);
fetchedPublisherIds.push(publisherObj.streamId);
let storedPublisher = this.publishers.find(c => c.streamId === publisherObj.streamId);
if (!!storedPublisher) {
// 2. Update existing Publisher
storedPublisher.resetWithJson(jsonPublisher);
} else {
// 3. Add new Publisher
this.publishers.push(publisherObj);
}
});
// 4. Remove closed Publishers from local collection
for (var i = this.publishers.length - 1; i >= 0; --i) {
if (!fetchedPublisherIds.includes(this.publishers[i].streamId)) {
this.publishers.splice(i, 1);
}
}
}
if (json.subscribers != null) {
// 1. Array to store fetched Subscribers and later remove closed ones
const fetchedSubscriberIds: string[] = [];
json.subscribers.forEach(jsonSubscriber => {
fetchedSubscriberIds.push(jsonSubscriber.streamId)
if (this.subscribers.indexOf(jsonSubscriber.streamId) === -1) {
// 2. Add new Subscriber
this.subscribers.push(jsonSubscriber.streamId);
}
});
// 3. Remove closed Subscribers from local collection
for (var i = this.subscribers.length - 1; i >= 0; --i) {
if (!fetchedSubscriberIds.includes(this.subscribers[i])) {
this.subscribers.splice(i, 1);
}
}
}
this.createdAt = json.createdAt;
this.location = json.location;
this.platform = json.platform;
this.clientData = json.clientData;
return this;
}
/**

View File

@ -429,47 +429,44 @@ export class OpenVidu {
.then(res => {
if (res.status === 200) {
// Array to store fetched sessionIds and later remove closed sessions
const fetchedSessionIds: string[] = [];
// Boolean to store if any Session has changed
let hasChanged = false;
res.data.content.forEach(session => {
fetchedSessionIds.push(session.sessionId);
let sessionIndex = -1;
let storedSession = this.activeSessions.find((s, index) => {
if (s.sessionId === session.sessionId) {
sessionIndex = index;
return true;
} else {
return false;
}
});
// 1. Array to store fetched sessionIds and later remove closed ones
const fetchedSessionIds: string[] = [];
res.data.content.forEach(jsonSession => {
const fetchedSession: Session = new Session(this, jsonSession);
fetchedSessionIds.push(fetchedSession.sessionId);
let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId);
if (!!storedSession) {
const fetchedSession: Session = new Session(this).resetSessionWithJson(session);
// 2. Update existing Session
const changed: boolean = !storedSession.equalTo(fetchedSession);
if (changed) {
storedSession = fetchedSession;
this.activeSessions[sessionIndex] = storedSession;
}
storedSession.resetWithJson(jsonSession);
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
hasChanged = hasChanged || changed;
} else {
this.activeSessions.push(new Session(this, session));
console.log("New session '" + session.sessionId + "' info fetched");
// 3. Add new Session
this.activeSessions.push(fetchedSession);
console.log("New session '" + fetchedSession.sessionId + "' info fetched");
hasChanged = true;
}
});
// Remove closed sessions from activeSessions array
this.activeSessions = this.activeSessions.filter(session => {
if (fetchedSessionIds.includes(session.sessionId)) {
return true;
} else {
console.log("Removing closed session '" + session.sessionId + "'");
// 4. Remove closed sessions from local collection
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
let sessionId = this.activeSessions[i].sessionId;
if (!fetchedSessionIds.includes(sessionId)) {
console.log("Removing closed session '" + sessionId + "'");
hasChanged = true;
return false;
this.activeSessions.splice(i, 1);
}
});
}
console.log('Active sessions info fetched: ', fetchedSessionIds);
resolve(hasChanged);
} else {
@ -505,26 +502,9 @@ export class OpenVidu {
const addWebRtcStatsToConnections = (connection: Connection, connectionsExtendedInfo: any) => {
const connectionExtended = connectionsExtendedInfo.find(c => c.connectionId === connection.connectionId);
if (!!connectionExtended) {
const publisherArray = [];
connection.publishers.forEach(pub => {
const publisherExtended = connectionExtended.publishers.find(p => p.streamId === pub.streamId);
const pubAux = {};
// Standard properties
pubAux['streamId'] = pub.streamId;
pubAux['createdAt'] = pub.createdAt;
const mediaOptions = {
audioActive: pub.audioActive,
videoActive: pub.videoActive,
hasAudio: pub.hasAudio,
hasVideo: pub.hasVideo,
typeOfVideo: pub.typeOfVideo,
frameRate: pub.frameRate,
videoDimensions: pub.videoDimensions
};
pubAux['mediaOptions'] = mediaOptions;
const newPublisher = new Publisher(pubAux);
// WebRtc properties
newPublisher['webRtc'] = {
pub['webRtc'] = {
kms: {
events: publisherExtended.events,
localCandidate: publisherExtended.localCandidate,
@ -536,11 +516,10 @@ export class OpenVidu {
remoteSdp: publisherExtended.remoteSdp
}
};
newPublisher['localCandidatePair'] = parseRemoteCandidatePair(newPublisher['webRtc'].kms.remoteCandidate);
pub['localCandidatePair'] = parseRemoteCandidatePair(pub['webRtc'].kms.remoteCandidate);
if (!!publisherExtended.serverStats) {
newPublisher['webRtc'].kms.serverStats = publisherExtended.serverStats;
pub['webRtc'].kms.serverStats = publisherExtended.serverStats;
}
publisherArray.push(newPublisher);
});
const subscriberArray = [];
connection.subscribers.forEach(sub => {
@ -569,7 +548,6 @@ export class OpenVidu {
}
subscriberArray.push(subAux);
});
connection.publishers = publisherArray;
connection.subscribers = subscriberArray;
}
};
@ -601,68 +579,64 @@ export class OpenVidu {
.then(res => {
if (res.status === 200) {
// Array to store fetched sessionIds and later remove closed sessions
const fetchedSessionIds: string[] = [];
// Global changes
let globalChanges = false;
// Collection of sessionIds telling whether each one of them has changed or not
const sessionChanges: ObjMap<boolean> = {};
res.data.content.forEach(session => {
fetchedSessionIds.push(session.sessionId);
let sessionIndex = -1;
let storedSession = this.activeSessions.find((s, index) => {
if (s.sessionId === session.sessionId) {
sessionIndex = index;
return true;
} else {
return false;
}
});
if (!!storedSession) {
const fetchedSession: Session = new Session(this).resetSessionWithJson(session);
fetchedSession.activeConnections.forEach(connection => {
addWebRtcStatsToConnections(connection, session.connections.content);
});
// 1. Array to store fetched sessionIds and later remove closed ones
const fetchedSessionIds: string[] = [];
res.data.content.forEach(jsonSession => {
const fetchedSession: Session = new Session(this, jsonSession);
fetchedSession.connections.forEach(connection => {
addWebRtcStatsToConnections(connection, jsonSession.connections.content);
});
fetchedSessionIds.push(fetchedSession.sessionId);
let storedSession = this.activeSessions.find(s => s.sessionId === fetchedSession.sessionId);
if (!!storedSession) {
// 2. Update existing Session
let changed = !storedSession.equalTo(fetchedSession);
if (!changed) { // Check if server webrtc information has changed in any Publisher object (Session.equalTo does not check Publisher.webRtc auxiliary object)
fetchedSession.activeConnections.forEach((connection, index1) => {
fetchedSession.connections.forEach((connection, index1) => {
for (let index2 = 0; (index2 < connection['publishers'].length && !changed); index2++) {
changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.activeConnections[index1]['publishers'][index2]['webRtc']);
changed = changed || JSON.stringify(connection['publishers'][index2]['webRtc']) !== JSON.stringify(storedSession.connections[index1]['publishers'][index2]['webRtc']);
}
});
}
if (changed) {
storedSession = fetchedSession;
this.activeSessions[sessionIndex] = storedSession;
}
storedSession.resetWithJson(jsonSession);
storedSession.connections.forEach(connection => {
addWebRtcStatsToConnections(connection, jsonSession.connections.content);
});
console.log("Available session '" + storedSession.sessionId + "' info fetched. Any change: " + changed);
sessionChanges[storedSession.sessionId] = changed;
globalChanges = globalChanges || changed;
} else {
const newSession = new Session(this, session);
newSession.activeConnections.forEach(connection => {
addWebRtcStatsToConnections(connection, session.connections.content);
});
this.activeSessions.push(newSession);
console.log("New session '" + session.sessionId + "' info fetched");
sessionChanges[session.sessionId] = true;
// 3. Add new Session
this.activeSessions.push(fetchedSession);
console.log("New session '" + fetchedSession.sessionId + "' info fetched");
sessionChanges[fetchedSession.sessionId] = true;
globalChanges = true;
}
});
// Remove closed sessions from activeSessions array
this.activeSessions = this.activeSessions.filter(session => {
if (fetchedSessionIds.includes(session.sessionId)) {
return true;
} else {
console.log("Removing closed session '" + session.sessionId + "'");
sessionChanges[session.sessionId] = true;
// 4. Remove closed sessions from local collection
for (var i = this.activeSessions.length - 1; i >= 0; --i) {
let sessionId = this.activeSessions[i].sessionId;
if (!fetchedSessionIds.includes(sessionId)) {
console.log("Removing closed session '" + sessionId + "'");
sessionChanges[sessionId] = true;
globalChanges = true;
return false;
this.activeSessions.splice(i, 1);
}
});
}
console.log('Active sessions info fetched: ', fetchedSessionIds);
resolve({ changes: globalChanges, sessionChanges });
} else {

View File

@ -74,6 +74,13 @@ export class Publisher {
* @hidden
*/
constructor(json) {
this.resetWithJson(json);
}
/**
* @hidden
*/
resetWithJson(json): Publisher {
this.streamId = json.streamId;
this.createdAt = json.createdAt;
this.hasAudio = json.mediaOptions.hasAudio;
@ -83,6 +90,7 @@ export class Publisher {
this.frameRate = json.mediaOptions.frameRate;
this.typeOfVideo = json.mediaOptions.typeOfVideo;
this.videoDimensions = json.mediaOptions.videoDimensions;
return this;
}
/**

View File

@ -82,7 +82,7 @@ export class Session {
// Defined parameter
if (!!propertiesOrJson.sessionId) {
// Parameter is a JSON representation of Session ('sessionId' property always defined)
this.resetSessionWithJson(propertiesOrJson);
this.resetWithJson(propertiesOrJson);
} else {
// Parameter is a SessionProperties object
this.properties = propertiesOrJson;
@ -224,7 +224,7 @@ export class Session {
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server
this.resetSessionWithJson(res.data);
this.resetWithJson(res.data);
const afterJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference);
const hasChanged: boolean = !(beforeJSON === afterJSON);
console.log("Session info fetched for session '" + this.sessionId + "'. Any change: " + hasChanged);
@ -488,42 +488,57 @@ export class Session {
/**
* @hidden
*/
public resetSessionWithJson(json): Session {
public resetWithJson(json): Session {
this.sessionId = json.sessionId;
this.createdAt = json.createdAt;
this.recording = json.recording;
let customSessionId: string;
let defaultCustomLayout: string;
if (!!this.properties) {
customSessionId = this.properties.customSessionId;
defaultCustomLayout = !!json.defaultCustomLayout ? json.defaultCustomLayout : this.properties.defaultCustomLayout;
}
this.properties = {
customSessionId: json.customSessionId,
mediaMode: json.mediaMode,
recordingMode: json.recordingMode,
defaultOutputMode: json.defaultOutputMode,
defaultRecordingLayout: json.defaultRecordingLayout
defaultRecordingLayout: json.defaultRecordingLayout,
defaultCustomLayout: json.defaultCustomLayout
};
if (!!customSessionId) {
this.properties.customSessionId = customSessionId;
} else if (!!json.customSessionId) {
this.properties.customSessionId = json.customSessionId;
if (json.defaultRecordingLayout == null) {
delete this.properties.defaultRecordingLayout;
}
if (!!defaultCustomLayout) {
this.properties.defaultCustomLayout = defaultCustomLayout;
if (json.customSessionId == null) {
delete this.properties.customSessionId;
}
if (json.defaultCustomLayout == null) {
delete this.properties.defaultCustomLayout;
}
this.connections = [];
this.activeConnections = [];
// 1. Array to store fetched connections and later remove closed ones
const fetchedConnectionIds: string[] = [];
json.connections.content.forEach(jsonConnection => {
const con = new Connection(jsonConnection);
this.connections.push(con);
const connectionObj: Connection = new Connection(jsonConnection);
fetchedConnectionIds.push(connectionObj.connectionId);
let storedConnection = this.connections.find(c => c.connectionId === connectionObj.connectionId);
if (!!storedConnection) {
// 2. Update existing Connection
storedConnection.resetWithJson(jsonConnection);
} else {
// 3. Add new Connection
this.connections.push(connectionObj);
}
});
// 4. Remove closed sessions from local collection
for (var i = this.connections.length - 1; i >= 0; --i) {
if (!fetchedConnectionIds.includes(this.connections[i].connectionId)) {
this.connections.splice(i, 1);
}
}
// Order connections by time of creation
this.connections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0));
// Populate activeConnections array
this.updateActiveConnectionsArray();
return this;
}