OpenVidu SDKs: new ConnectionOptions object

pull/550/head
pabloFuente 2020-10-13 12:28:06 +02:00
parent 5575bf60cf
commit ef9d494a70
7 changed files with 341 additions and 79 deletions

View File

@ -41,29 +41,42 @@ public class Connection {
protected List<String> subscribers = new ArrayList<>();
protected Connection(JsonObject json) {
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);
});
// 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);
});
}
JsonArray jsonArraySubscribers = json.get("subscribers").getAsJsonArray();
jsonArraySubscribers.forEach(subscriber -> {
this.subscribers.add((subscriber.getAsJsonObject()).get("streamId").getAsString());
});
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.createdAt = json.get("createdAt").getAsLong();
this.location = json.get("location").getAsString();
this.platform = json.get("platform").getAsString();
this.clientData = json.get("clientData").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();
@ -179,12 +192,36 @@ public class Connection {
return this.subscribers;
}
protected JsonObject toJson() {
JsonObject json = new JsonObject();
json.addProperty("id", this.getConnectionId());
json.addProperty("createdAt", this.createdAt());
json.addProperty("location", this.getLocation());
json.addProperty("platform", this.getPlatform());
json.addProperty("token", this.getToken());
json.addProperty("role", this.getRole().name());
json.addProperty("serverData", this.getServerData());
json.addProperty("record", this.record());
json.addProperty("clientData", this.getClientData());
JsonArray pubs = new JsonArray();
this.getPublishers().forEach(p -> {
pubs.add(p.toJson());
});
JsonArray subs = new JsonArray();
this.getSubscribers().forEach(s -> {
subs.add(s);
});
json.add("publishers", pubs);
json.add("subscribers", subs);
return json;
}
/**
* For now only properties data, role and record can be updated
*/
protected void overrideTokenOptions(TokenOptions tokenOptions) {
TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(tokenOptions.getRole())
.record(tokenOptions.record());
protected void overrideConnectionOptions(ConnectionOptions connectionOptions) {
TokenOptions.Builder modifiableTokenOptions = new TokenOptions.Builder().role(connectionOptions.getRole())
.record(connectionOptions.record());
modifiableTokenOptions.data(this.token.getData());
this.token.overrideTokenOptions(modifiableTokenOptions.build());
}

View File

@ -0,0 +1,165 @@
package io.openvidu.java.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
public class ConnectionOptions {
private OpenViduRole role;
private String data;
private Boolean record;
private KurentoOptions kurentoOptions;
/**
*
* Builder for {@link io.openvidu.java.client.ConnectionOptions}
*
*/
public static class Builder {
private OpenViduRole role = OpenViduRole.PUBLISHER;
private String data;
private Boolean record = true;
private KurentoOptions kurentoOptions;
/**
* Builder for {@link io.openvidu.java.client.ConnectionOptions}.
*/
public ConnectionOptions build() {
return new ConnectionOptions(this.role, this.data, this.record, this.kurentoOptions);
}
/**
* Call this method to set the role assigned to this Connection.
*/
public Builder role(OpenViduRole role) {
this.role = role;
return this;
}
/**
* Call this method to set the secure (server-side) data associated to this
* Connection. Every client will receive this data in property
* <code>Connection.data</code>. Object <code>Connection</code> can be retrieved
* by subscribing to event <code>connectionCreated</code> of Session object in
* your clients.
* <ul>
* <li>If you have provided no data in your clients when calling method
* <code>Session.connect(TOKEN, DATA)</code> (<code>DATA</code> not defined),
* then <code>Connection.data</code> will only have this
* {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)}
* property.</li>
* <li>If you have provided some data when calling
* <code>Session.connect(TOKEN, DATA)</code> (<code>DATA</code> defined), then
* <code>Connection.data</code> will have the following structure:
* <code>&quot;CLIENT_DATA%/%SERVER_DATA&quot;</code>, being
* <code>CLIENT_DATA</code> the second parameter passed in OpenVidu Browser in
* method <code>Session.connect</code> and <code>SERVER_DATA</code> this
* {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String)}
* property.</li>
* </ul>
*/
public Builder data(String data) {
this.data = data;
return this;
}
/**
* Call this method to flag the streams published by this Connection to be
* recorded or not. This only affects <a href=
* "https://docs.openvidu.io/en/stable/advanced-features/recording#selecting-streams-to-be-recorded"
* target="_blank">INDIVIDUAL recording</a>. If not set by default will be true.
*/
public Builder record(boolean record) {
this.record = record;
return this;
}
/**
* Call this method to set a {@link io.openvidu.java.client.KurentoOptions}
* object for this Connection.
*/
public Builder kurentoOptions(KurentoOptions kurentoOptions) {
this.kurentoOptions = kurentoOptions;
return this;
}
}
ConnectionOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) {
this.role = role;
this.data = data;
this.record = record;
this.kurentoOptions = kurentoOptions;
}
/**
* Returns the role assigned to this Connection.
*/
public OpenViduRole getRole() {
return this.role;
}
/**
* Returns the secure (server-side) metadata assigned to this Connection.
*/
public String getData() {
return this.data;
}
/**
* Whether the streams published by this Connection will be recorded or not.
* This only affects <a href=
* "https://docs.openvidu.io/en/stable/advanced-features/recording#selecting-streams-to-be-recorded"
* target="_blank">INDIVIDUAL recording</a>.
*/
public Boolean record() {
return this.record;
}
protected JsonObject toJsonObject(String sessionId) {
JsonObject json = new JsonObject();
json.addProperty("session", sessionId);
if (getRole() != null) {
json.addProperty("role", getRole().name());
} else {
json.add("role", JsonNull.INSTANCE);
}
if (getData() != null) {
json.addProperty("data", getData());
} else {
json.add("data", JsonNull.INSTANCE);
}
if (record() != null) {
json.addProperty("record", record());
} else {
json.add("record", JsonNull.INSTANCE);
}
if (this.kurentoOptions != null) {
JsonObject kurentoOptions = new JsonObject();
if (this.kurentoOptions.getVideoMaxRecvBandwidth() != null) {
kurentoOptions.addProperty("videoMaxRecvBandwidth", this.kurentoOptions.getVideoMaxRecvBandwidth());
}
if (this.kurentoOptions.getVideoMinRecvBandwidth() != null) {
kurentoOptions.addProperty("videoMinRecvBandwidth", this.kurentoOptions.getVideoMinRecvBandwidth());
}
if (this.kurentoOptions.getVideoMaxSendBandwidth() != null) {
kurentoOptions.addProperty("videoMaxSendBandwidth", this.kurentoOptions.getVideoMaxSendBandwidth());
}
if (this.kurentoOptions.getVideoMinSendBandwidth() != null) {
kurentoOptions.addProperty("videoMinSendBandwidth", this.kurentoOptions.getVideoMinSendBandwidth());
}
if (this.kurentoOptions.getAllowedFilters().length > 0) {
JsonArray allowedFilters = new JsonArray();
for (String filter : this.kurentoOptions.getAllowedFilters()) {
allowedFilters.add(filter);
}
kurentoOptions.add("allowedFilters", allowedFilters);
}
json.add("kurentoOptions", kurentoOptions);
}
return json;
}
}

View File

@ -268,7 +268,7 @@ public class Session {
* @throws OpenViduJavaClientException
*/
public boolean fetch() throws OpenViduJavaClientException, OpenViduHttpException {
String beforeJSON = this.toJson();
final String beforeJSON = this.toJson();
HttpGet request = new HttpGet(this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId);
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
@ -283,7 +283,7 @@ public class Session {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
this.resetSessionWithJson(httpResponseToJson(response));
String afterJSON = this.toJson();
final String afterJSON = this.toJson();
boolean hasChanged = !beforeJSON.equals(afterJSON);
log.info("Session info fetched for session '{}'. Any change: {}", this.sessionId, hasChanged);
return hasChanged;
@ -482,15 +482,14 @@ public class Session {
}
/**
* Updates the properties of a Connection. These properties are the ones defined
* by the {@link io.openvidu.java.client.TokenOptions} parameter when generating
* the token used to create the Connection. These are the properties that can be
* updated:
* Updates the properties of a Connection with a
* {@link io.openvidu.java.client.ConnectionOptions} object. Only these
* properties can be updated:
* <ul>
* <li>{@link io.openvidu.java.client.TokenOptions.Builder#role(OpenViduRole)
* TokenOptions.Builder.role(OpenViduRole)}</li>
* <li>{@link io.openvidu.java.client.TokenOptions.Builder#record(boolean)
* TokenOptions.Builder.record(boolean)}</li>
* <li>{@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole)
* ConnectionOptions.Builder.role(OpenViduRole)}</li>
* <li>{@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean)
* ConnectionOptions.Builder.record(boolean)}</li>
* </ul>
* <br>
*
@ -508,9 +507,9 @@ public class Session {
* 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 tokenOptions A new TokenOptions object with the updated values to
* apply
* @param connectionId The Connection (or a still not used Token) to modify
* @param connectionOptions A ConnectionOptions object with the new values to
* apply
*
* @return The updated {@link io.openvidu.java.client.Connection Connection}
* object
@ -518,7 +517,7 @@ public class Session {
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public Connection updateConnection(String connectionId, TokenOptions tokenOptions)
public Connection updateConnection(String connectionId, ConnectionOptions connectionOptions)
throws OpenViduJavaClientException, OpenViduHttpException {
HttpPatch request = new HttpPatch(
@ -526,7 +525,7 @@ public class Session {
StringEntity params;
try {
params = new StringEntity(tokenOptions.toJsonObject(this.sessionId).toString());
params = new StringEntity(connectionOptions.toJsonObject(this.sessionId).toString());
} catch (UnsupportedEncodingException e1) {
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
}
@ -549,18 +548,19 @@ public class Session {
} else {
throw new OpenViduHttpException(statusCode);
}
JsonObject json = httpResponseToJson(response);
// Update the actual Connection object with the new options
Connection existingConnection = this.activeConnections.get(connectionId);
if (existingConnection == null) {
// The updated Connection is not available in local map
Connection newConnection = new Connection(httpResponseToJson(response));
Connection newConnection = new Connection(json);
this.activeConnections.put(connectionId, newConnection);
return newConnection;
} else {
// The updated Connection was available in local map
existingConnection.overrideTokenOptions(tokenOptions);
existingConnection.overrideConnectionOptions(connectionOptions);
return existingConnection;
}
@ -717,23 +717,7 @@ public class Session {
connections.addProperty("numberOfElements", this.getActiveConnections().size());
JsonArray jsonArrayConnections = new JsonArray();
this.getActiveConnections().forEach(con -> {
JsonObject c = new JsonObject();
c.addProperty("connectionId", con.getConnectionId());
c.addProperty("role", con.getRole().name());
c.addProperty("token", con.getToken());
c.addProperty("clientData", con.getClientData());
c.addProperty("serverData", con.getServerData());
JsonArray pubs = new JsonArray();
con.getPublishers().forEach(p -> {
pubs.add(p.toJson());
});
JsonArray subs = new JsonArray();
con.getSubscribers().forEach(s -> {
subs.add(s);
});
c.add("publishers", pubs);
c.add("subscribers", subs);
jsonArrayConnections.add(c);
jsonArrayConnections.add(con.toJson());
});
connections.add("content", jsonArrayConnections);
json.add("connections", connections);

View File

@ -17,7 +17,7 @@
import { OpenViduRole } from './OpenViduRole';
import { Publisher } from './Publisher';
import { TokenOptions } from './TokenOptions';
import { ConnectionOptions } from './ConnectionOptions';
/**
* See [[Session.activeConnections]]
@ -88,6 +88,7 @@ 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));
@ -98,15 +99,17 @@ export class Connection {
this.subscribers.push(subscriber.streamId);
});
}
this.connectionId = json.connectionId;
this.createdAt = json.createdAt;
this.role = json.role;
this.serverData = json.serverData;
this.record = json.record;
this.token = json.token;
this.location = json.location;
this.platform = json.platform;
this.clientData = json.clientData;
// These properties won't ever be null
this.connectionId = json.connectionId;
this.token = json.token;
this.role = json.role;
this.serverData = json.serverData;
this.record = json.record;
}
/**
@ -145,12 +148,12 @@ export class Connection {
/**
* @hidden
*/
overrideTokenOptions(tokenOptions: TokenOptions): void {
if (tokenOptions.role != null) {
this.role = tokenOptions.role;
overrideConnectionOptions(connectionOptions: ConnectionOptions): void {
if (connectionOptions.role != null) {
this.role = connectionOptions.role;
}
if (tokenOptions.record != null) {
this.record = tokenOptions.record
if (connectionOptions.record != null) {
this.record = connectionOptions.record
}
}

View File

@ -0,0 +1,72 @@
/*
* (C) Copyright 2017-2020 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';
export interface ConnectionOptions {
/**
* The role assigned to this Connection
*
* @default PUBLISHER
*/
role?: OpenViduRole;
/**
* Secure (server-side) data associated to this Connection. Every client will receive this data in property `Connection.data`. Object `Connection` can be retrieved by subscribing to event `connectionCreated` of Session object.
* - If you have provided no data in your clients when calling method `Session.connect(TOKEN, DATA)` (`DATA` not defined), then `Connection.data` will only have this [[ConnectionOptions.data]] property.
* - If you have provided some data when calling `Session.connect(TOKEN, DATA)` (`DATA` defined), then `Connection.data` will have the following structure: `"CLIENT_DATA%/%SERVER_DATA"`, being `CLIENT_DATA` the second
* parameter passed in OpenVidu Browser in method `Session.connect` and `SERVER_DATA` this [[ConnectionOptions.data]] property.
*/
data?: string;
/**
* Whether to record the streams published by this Connection or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded)
*
* @default true
*/
record?: boolean;
/**
* **WARNING**: experimental option. This interface may change in the near future
*
* Some advanced properties setting the configuration that the WebRTC streams of the Connection will have in Kurento Media Server.
* You can adjust:
* - `videoMaxRecvBandwidth`: maximum number of Kbps that the Connection will be able to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
* (parameter `OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH`) for every incoming stream of the Connection.
* _**WARNING**: the lower value set to this property limits every other bandwidth of the WebRTC pipeline this server-to-client stream belongs to. This includes the user publishing the stream and every other user subscribed to the stream_
* - `videoMinRecvBandwidth`: minimum number of Kbps that the cConnection will try to receive from Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
* (parameter `OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH`) for every incoming stream of the Connection.
* - `videoMaxSendBandwidth`: maximum number of Kbps that the Connection will be able to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
* (parameter `OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH`) for every outgoing stream of the Connection.
* _**WARNING**: this value limits every other bandwidth of the WebRTC pipeline this client-to-server stream belongs to. This includes every other user subscribed to the stream_
* - `videoMinSendBandwidth`: minimum number of Kbps that the Connection will try to send to Kurento Media Server. 0 means unconstrained. Giving a value to this property will override
* the global configuration set in [OpenVidu Server configuration](/en/stable/reference-docs/openvidu-config/)
* (parameter `OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH`) for every outgoing stream of the Connection.
* - `allowedFilters`: names of the filters the Connection will be able to apply. See [Voice and video filters](/en/stable/advanced-features/filters/)
*/
kurentoOptions?: {
videoMaxRecvBandwidth?: number,
videoMinRecvBandwidth?: number,
videoMaxSendBandwidth?: number,
videoMinSendBandwidth?: number,
allowedFilters?: string[]
};
}

View File

@ -17,6 +17,7 @@
import axios, { AxiosError } from 'axios';
import { Connection } from './Connection';
import { ConnectionOptions } from './ConnectionOptions';
import { MediaMode } from './MediaMode';
import { OpenVidu } from './OpenVidu';
import { Publisher } from './Publisher';
@ -359,12 +360,11 @@ export class Session {
}
/**
* Updates the properties of a Connection. These properties are the ones defined
* by the [[TokenOptions]] parameter when generating the token used to create the Connection.
* These are the properties that can be updated:
* Updates the properties of a Connection with a [[ConnectionOptions]] object.
* Only these properties can be updated:
*
* - [[TokenOptions.role]]
* - [[TokenOptions.record]]
* - [[ConnectionOptions.role]]
* - [[ConnectionOptions.record]]
*
* The `connectionId` parameter can be obtained from a Connection object with
* [[Connection.connectionId]], in which case the updated properties will
@ -375,17 +375,17 @@ export class Session {
* [[Session.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 tokenOptions A new [[TokenOptions]] object with the updated values to apply
* or the [[Token.connectionId]] property of a still not used token 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
* successful and rejected with an Error object if not
* successful and rejected with an Error object if not
*/
public updateConnection(connectionId: string, tokenOptions: TokenOptions): Promise<Connection> {
public updateConnection(connectionId: string, connectionOptions: ConnectionOptions): Promise<Connection | undefined> {
return new Promise<any>((resolve, reject) => {
axios.patch(
this.ov.host + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection/" + connectionId,
tokenOptions,
connectionOptions,
{
headers: {
'Authorization': this.ov.basicAuth,
@ -412,7 +412,7 @@ export class Session {
resolve(newConnection);
} else {
// The updated Connection was available in local map
existingConnection.overrideTokenOptions(tokenOptions);
existingConnection.overrideConnectionOptions(connectionOptions);
resolve(existingConnection);
}
}).catch(error => {

View File

@ -3,6 +3,7 @@ export * from './OpenViduRole';
export * from './Session';
export * from './SessionProperties';
export * from './TokenOptions';
export * from './ConnectionOptions';
export * from './Token';
export * from './MediaMode';
export * from './RecordingLayout';