From 0463230e9d4e5f87428d4de286293dd5fe909709 Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Thu, 15 Oct 2020 13:16:29 +0200 Subject: [PATCH] OpenVidu SDKs: getConnection and getConnections --- .../io/openvidu/java/client/Connection.java | 2 +- .../io/openvidu/java/client/OpenVidu.java | 2 +- .../java/io/openvidu/java/client/Session.java | 85 +++++++++------ openvidu-node-client/src/Connection.ts | 2 +- openvidu-node-client/src/OpenVidu.ts | 2 +- openvidu-node-client/src/Session.ts | 100 +++++++++++------- 6 files changed, 116 insertions(+), 77 deletions(-) diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java index a63f3849..27a8879d 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java @@ -26,7 +26,7 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; /** - * See {@link io.openvidu.java.client.Session#getActiveConnections()} + * See {@link io.openvidu.java.client.Session#getConnections()} */ public class Connection { diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java index 1ba75945..005c6430 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/OpenVidu.java @@ -537,7 +537,7 @@ public class OpenVidu { * @throws OpenViduJavaClientException */ public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException { - HttpGet request = new HttpGet(this.hostname + API_SESSIONS); + HttpGet request = new HttpGet(this.hostname + API_SESSIONS + "?pendingConnections=true"); HttpResponse response; try { diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java index b8256b14..75eef6da 100644 --- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java +++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Session.java @@ -19,7 +19,6 @@ package io.openvidu.java.client; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -49,7 +48,7 @@ public class Session { private long createdAt; private OpenVidu openVidu; private SessionProperties properties; - private Map activeConnections = new ConcurrentHashMap<>(); + private Map connections = new ConcurrentHashMap<>(); private boolean recording = false; protected Session(OpenVidu openVidu) throws OpenViduJavaClientException, OpenViduHttpException { @@ -165,7 +164,7 @@ public class Session { * Session.forceDisconnect()} to invalidate the token if no client has used it * yet or force the connected client to leave the session if it has. *
  • Call - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions) + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions) * Session.updateConnection()} to update the * {@link io.openvidu.java.client.Connection Connection} options. And this is * valid for unused tokens, but also for already used tokens, so you can @@ -254,7 +253,7 @@ public class Session { * those values to call * {@link io.openvidu.java.client.Session#forceDisconnect(Connection)}, * {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)} or - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)}.
    + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)}.
    *
    * * To update all Session objects owned by OpenVidu object at once, call @@ -269,7 +268,8 @@ public class Session { */ public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException { final String beforeJSON = this.toJson(); - HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId); + HttpGet request = new HttpGet( + this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "?pendingConnections=true"); request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"); HttpResponse response; @@ -371,13 +371,13 @@ public class Session { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { // Remove connection from activeConnections map - Connection connectionClosed = this.activeConnections.remove(connectionId); + Connection connectionClosed = this.connections.remove(connectionId); // Remove every Publisher of the closed connection from every subscriber list of // other connections if (connectionClosed != null) { for (Publisher publisher : connectionClosed.getPublishers()) { String streamId = publisher.getStreamId(); - for (Connection connection : this.activeConnections.values()) { + for (Connection connection : this.connections.values()) { connection.setSubscribers(connection.getSubscribers().stream() .filter(subscriber -> !streamId.equals(subscriber)).collect(Collectors.toList())); } @@ -464,7 +464,7 @@ public class Session { try { int statusCode = response.getStatusLine().getStatusCode(); if ((statusCode == org.apache.http.HttpStatus.SC_NO_CONTENT)) { - for (Connection connection : this.activeConnections.values()) { + for (Connection connection : this.connections.values()) { // Try to remove the Publisher from the Connection publishers collection if (connection.publishers.remove(streamId) != null) { continue; @@ -493,21 +493,14 @@ public class Session { * *
    * - * The connectionId parameter can be obtained from a Connection - * object with {@link io.openvidu.java.client.Connection#getConnectionId() - * Connection.getConnectionId()}, in which case the updated properties will - * modify an active Connection. But connectionId can also be - * obtained from a Token with {@link Token#getConnectionId()}, which allows - * modifying a still not used token.
    - *
    - * * This method automatically updates the properties of the local affected * objects. This means that there is no need to call - * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to see the + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} to see the * changes consequence of the execution of this method applied in the local * objects. * - * @param connectionId The Connection (or a still not used Token) to modify + * @param connectionId The Connection to modify * @param connectionOptions A ConnectionOptions object with the new values to * apply * @@ -551,12 +544,12 @@ public class Session { JsonObject json = httpResponseToJson(response); // Update the actual Connection object with the new options - Connection existingConnection = this.activeConnections.get(connectionId); + Connection existingConnection = this.connections.get(connectionId); if (existingConnection == null) { // The updated Connection is not available in local map Connection newConnection = new Connection(json); - this.activeConnections.put(connectionId, newConnection); + this.connections.put(connectionId, newConnection); return newConnection; } else { // The updated Connection was available in local map @@ -570,27 +563,55 @@ public class Session { } /** - * Returns the list of active connections to the session. This value - * will remain unchanged since the last time method - * {@link io.openvidu.java.client.Session#fetch()} was called. - * Exceptions to this rule are: + * Returns a Connection of the Session. This method only returns the local + * available object and does not query OpenVidu Server. To get the current + * actual value you must call first + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + */ + public Connection getConnection(String id) { + return this.connections.get(id); + } + + /** + * Returns all the Connections of the Session. This method only returns the + * local available objects and does not query OpenVidu Server. To get the + * current actual value you must call first + * {@link io.openvidu.java.client.Session#fetch() Session.fetch()} or + * {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()}. + */ + public List getConnections() { + return this.connections.values().stream().collect(Collectors.toList()); + } + + /** + * Returns the list of active Connections of the Session. These are the + * Connections returning active in response to + * {@link io.openvidu.java.client.Connection#getStatus()}. This method only + * returns the local available objects and does not query OpenVidu Server. + * The list of active Connections will remain unchanged since the last + * time method {@link io.openvidu.java.client.Session#fetch() Session.fetch()} + * or {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was + * called. Exceptions to this rule are: *
      *
    • Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)} * automatically updates each affected local Connection object.
    • *
    • Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)} * automatically updates each affected local Connection object.
    • *
    • Calling - * {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)} + * {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)} * automatically updates the attributes of the affected local Connection * object.
    • *
    *
    * To get the list of active connections with their current actual value, you - * must call first {@link io.openvidu.java.client.Session#fetch()} and then - * {@link io.openvidu.java.client.Session#getActiveConnections()}. + * must call first {@link io.openvidu.java.client.Session#fetch() + * Session.fetch()} or {@link io.openvidu.java.client.OpenVidu#fetch() + * OpenVidu.fetch()}. */ public List getActiveConnections() { - return new ArrayList<>(this.activeConnections.values()); + return this.connections.values().stream().filter(con -> "active".equals(con.getStatus())) + .collect(Collectors.toList()); } /** @@ -694,10 +715,10 @@ public class Session { } this.properties = builder.build(); JsonArray jsonArrayConnections = (json.get("connections").getAsJsonObject()).get("content").getAsJsonArray(); - this.activeConnections.clear(); + this.connections.clear(); jsonArrayConnections.forEach(connectionJsonElement -> { Connection connectionObj = new Connection(connectionJsonElement.getAsJsonObject()); - this.activeConnections.put(connectionObj.getConnectionId(), connectionObj); + this.connections.put(connectionObj.getConnectionId(), connectionObj); }); return this; } @@ -714,9 +735,9 @@ public class Session { json.addProperty("defaultRecordingLayout", this.properties.defaultRecordingLayout().name()); json.addProperty("defaultCustomLayout", this.properties.defaultCustomLayout()); JsonObject connections = new JsonObject(); - connections.addProperty("numberOfElements", this.getActiveConnections().size()); + connections.addProperty("numberOfElements", this.getConnections().size()); JsonArray jsonArrayConnections = new JsonArray(); - this.getActiveConnections().forEach(con -> { + this.getConnections().forEach(con -> { jsonArrayConnections.add(con.toJson()); }); connections.add("content", jsonArrayConnections); diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts index ce71cdc4..928f2665 100644 --- a/openvidu-node-client/src/Connection.ts +++ b/openvidu-node-client/src/Connection.ts @@ -20,7 +20,7 @@ import { Publisher } from './Publisher'; import { ConnectionOptions } from './ConnectionOptions'; /** - * See [[Session.activeConnections]] + * See [[Session.connections]] */ export class Connection { diff --git a/openvidu-node-client/src/OpenVidu.ts b/openvidu-node-client/src/OpenVidu.ts index 4f572dcb..5e21a6c1 100644 --- a/openvidu-node-client/src/OpenVidu.ts +++ b/openvidu-node-client/src/OpenVidu.ts @@ -419,7 +419,7 @@ export class OpenVidu { public fetch(): Promise { return new Promise((resolve, reject) => { axios.get( - this.host + OpenVidu.API_SESSIONS, + this.host + OpenVidu.API_SESSIONS + '?pendingConnections=true', { headers: { Authorization: this.basicAuth diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts index 79b8dfa9..6fac15ac 100644 --- a/openvidu-node-client/src/Session.ts +++ b/openvidu-node-client/src/Session.ts @@ -47,15 +47,25 @@ export class Session { properties: SessionProperties; /** - * 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: + * Array of Connections to the Session. This property always initialize as an empty array and + * **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**. + * Exceptions to this rule are: * * - Calling [[Session.forceUnpublish]] automatically updates each affected local Connection object. * - Calling [[Session.forceDisconnect]] automatically updates each affected local Connection object. * - Calling [[Session.updateConnection]] automatically updates the attributes of the affected local Connection object. * - * To get the array of active connections with their current actual value, you must call [[Session.fetch]] before consulting - * property [[activeConnections]] + * To get the array of Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]] + * before consulting property [[connections]] + */ + connections: Connection[] = []; + + /** + * Array containing the active Connections of the Session. It is a subset of [[Session.connections]] array containing only + * those Connections with property [[Connection.status]] to `active`. + * + * To get the array of active Connections with their current actual value, you must call [[Session.fetch]] or [[OpenVidu.fetch]] + * before consulting property [[activeConnections]] */ activeConnections: Connection[] = []; @@ -190,9 +200,9 @@ export class Session { } /** - * 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 of the Session ([[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]], [[Session.forceUnpublish]] or - * [[Session.updateConnection]]. + * Updates every property of the Session with the current status it has in OpenVidu Server. This is especially useful for accessing the list of + * Connections of the Session ([[Session.connections]], [[Session.activeConnections]]) and use those values to call [[Session.forceDisconnect]], + * [[Session.forceUnpublish]] or [[Session.updateConnection]]. * * To update all Session objects owned by OpenVidu object at once, call [[OpenVidu.fetch]] * @@ -203,7 +213,7 @@ export class Session { return new Promise((resolve, reject) => { const beforeJSON: string = JSON.stringify(this, this.removeCircularOpenViduReference); axios.get( - this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId, + this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '?pendingConnections=true', { headers: { 'Authorization': this.ov.basicAuth, @@ -230,22 +240,14 @@ export class Session { } /** - * Forces the user with Connection `connectionId` to leave the session, or invalidates the [[Token]] associated with that - * `connectionId` if no user has used it yet. - * - * In the first case you can get `connection` parameter from [[Session.activeConnections]] array (remember to call [[Session.fetch]] before - * to fetch the current actual properties of the Session from OpenVidu Server). As a result, OpenVidu Browser will trigger the proper - * events on the client-side (`streamDestroyed`, `connectionDestroyed`, `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`. - * - * In the second case you can get `connectionId` parameter with [[Token.connectionId]]. As a result, the token will be invalidated - * and no user will be able to connect to the session with it. + * Removes a Connection from the Session. * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @param connection The Connection object to disconnect from the session, or its `connectionId` property * - * @returns A Promise that is resolved if the user was successfully disconnected and rejected with an Error object if not + * @returns A Promise that is resolved if the Connection was successfully removed from the Session and rejected with an Error object if not */ public forceDisconnect(connection: string | Connection): Promise { return new Promise((resolve, reject) => { @@ -261,9 +263,9 @@ export class Session { .then(res => { if (res.status === 204) { // SUCCESS response from openvidu-server - // Remove connection from activeConnections array + // Remove connection from connections array let connectionClosed; - this.activeConnections = this.activeConnections.filter(con => { + this.connections = this.connections.filter(con => { if (con.connectionId !== connectionId) { return true; } else { @@ -274,7 +276,7 @@ export class Session { // Remove every Publisher of the closed connection from every subscriber list of other connections if (!!connectionClosed) { connectionClosed.publishers.forEach(publisher => { - this.activeConnections.forEach(con => { + this.connections.forEach(con => { con.subscribers = con.subscribers.filter(subscriber => { // tslint:disable:no-string-literal if (!!subscriber['streamId']) { @@ -289,8 +291,9 @@ export class Session { }); }); } 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.warn("The closed connection wasn't fetched in OpenVidu Node Client. No changes in the collection of active connections of the Session"); } + this.updateActiveConnectionsArray(); console.log("Connection '" + connectionId + "' closed"); resolve(); } else { @@ -309,10 +312,10 @@ export class Session { * 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 + * Remember to call [[Session.fetch]] or [[OpenVidu.fetch]] before to fetch the current actual properties of the Session from OpenVidu Server * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * * @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not */ @@ -331,7 +334,7 @@ export class Session { .then(res => { if (res.status === 204) { // SUCCESS response from openvidu-server - this.activeConnections.forEach(connection => { + this.connections.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 @@ -347,6 +350,7 @@ export class Session { } } }); + this.updateActiveConnectionsArray(); console.log("Stream '" + streamId + "' unpublished"); resolve(); } else { @@ -366,16 +370,10 @@ export class Session { * - [[ConnectionOptions.role]] * - [[ConnectionOptions.record]] * - * The `connectionId` parameter can be obtained from a Connection object with - * [[Connection.connectionId]], in which case the updated properties will - * modify an active Connection. But `connectionId` can also be obtained from a - * Token with [[Token.connectionId]], which allows modifying a still not used token. - * * This method automatically updates the properties of the local affected objects. This means that there is no need to call - * [[Session.fetch]] to see the changes consequence of the execution of this method applied in the local objects. + * [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects. * - * @param connectionId The [[Connection.connectionId]] property of the Connection object to modify, - * or the [[Token.connectionId]] property of a still not used token to modify + * @param connectionId The [[Connection.connectionId]] of the Connection object to modify * @param connectionOptions A new [[ConnectionOptions]] object with the updated values to apply * * @returns A Promise that is resolved to the updated [[Connection]] object if the operation was @@ -404,15 +402,17 @@ export class Session { return; } // Update the actual Connection object with the new options - const existingConnection: Connection = this.activeConnections.find(con => con.connectionId === connectionId); + const existingConnection: Connection = this.connections.find(con => con.connectionId === connectionId); if (!existingConnection) { // The updated Connection is not available in local map const newConnection: Connection = new Connection(res.data); - this.activeConnections.push(newConnection); + this.connections.push(newConnection); + this.updateActiveConnectionsArray(); resolve(newConnection); } else { // The updated Connection was available in local map existingConnection.overrideConnectionOptions(connectionOptions); + this.updateActiveConnectionsArray(); resolve(existingConnection); } }).catch(error => { @@ -513,11 +513,17 @@ export class Session { this.properties.defaultCustomLayout = defaultCustomLayout; } + this.connections = []; this.activeConnections = []; - json.connections.content.forEach(jsonConnection => this.activeConnections.push(new Connection(jsonConnection))); + json.connections.content.forEach(jsonConnection => { + const con = new Connection(jsonConnection); + this.connections.push(con); + }); // Order connections by time of creation - this.activeConnections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); + this.connections.sort((c1, c2) => (c1.createdAt > c2.createdAt) ? 1 : ((c2.createdAt > c1.createdAt) ? -1 : 0)); + // Populate activeConnections array + this.updateActiveConnectionsArray(); return this; } @@ -529,13 +535,13 @@ export class Session { this.sessionId === other.sessionId && this.createdAt === other.createdAt && this.recording === other.recording && - this.activeConnections.length === other.activeConnections.length && + this.connections.length === other.connections.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]); + while (equals && i < this.connections.length) { + equals = this.connections[i].equalTo(other.connections[i]); i++; } return equals; @@ -555,6 +561,18 @@ export class Session { } } + /** + * @hidden + */ + private updateActiveConnectionsArray() { + this.activeConnections = []; + this.connections.forEach(con => { + if (con.status === 'active') { + this.activeConnections.push(con); + } + }); + } + /** * @hidden */