POST Connection API

pull/553/head
pabloFuente 2020-10-20 22:09:06 +02:00
parent 06a602cf62
commit f989b0c2ee
31 changed files with 1350 additions and 956 deletions

View File

@ -39,7 +39,8 @@ public class Connection {
private String location;
private String platform;
private String clientData;
private Token token;
private ConnectionOptions connectionOptions;
private String token;
protected Map<String, Publisher> publishers = new ConcurrentHashMap<>();
protected List<String> subscribers = new ArrayList<>();
@ -49,7 +50,7 @@ public class Connection {
}
/**
* Returns the identifier of the connection. You can call methods
* Returns the identifier of the Connection. You can call methods
* {@link io.openvidu.java.client.Session#forceDisconnect(String)} or
* {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)}
* passing this property as parameter
@ -59,7 +60,7 @@ public class Connection {
}
/**
* Returns the status of the connection. Can be:
* Returns the status of the Connection. Can be:
* <ul>
* <li><code>pending</code>: if the Connection is waiting for any user to use
* its internal token to connect to the session, calling method <a href=
@ -74,7 +75,7 @@ public class Connection {
}
/**
* Timestamp when this connection was created, in UTC milliseconds (ms since Jan
* Timestamp when this Connection was created, in UTC milliseconds (ms since Jan
* 1, 1970, 00:00:00 UTC)
*/
public Long createdAt() {
@ -82,7 +83,7 @@ public class Connection {
}
/**
* Timestamp when this connection was taken by a user (passing from status
* Timestamp when this Connection was taken by a user (passing from status
* "pending" to "active"), in UTC milliseconds (ms since Jan 1, 1970, 00:00:00
* UTC)
*/
@ -91,19 +92,19 @@ public class Connection {
}
/**
* Returns the role of the connection
* Returns the type of Connection.
*/
public OpenViduRole getRole() {
return this.token.getRole();
public ConnectionType getType() {
return this.connectionOptions.getType();
}
/**
* Returns the data associated to the connection on the server-side. This value
* Returns the data associated to the Connection on the server-side. This value
* is set with {@link io.openvidu.java.client.TokenOptions.Builder#data(String)}
* when calling {@link io.openvidu.java.client.Session#generateToken()}
*/
public String getServerData() {
return this.token.getData();
return this.connectionOptions.getData();
}
/**
@ -113,14 +114,86 @@ public class Connection {
* target="_blank">INDIVIDUAL recording</a>.
*/
public boolean record() {
return this.token.record();
return this.connectionOptions.record();
}
/**
* Returns the token string associated to the connection
* Returns the role of the Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
*/
public OpenViduRole getRole() {
return this.connectionOptions.getRole();
}
/**
* Returns the RTSP URI of the Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public String getRtspUri() {
return this.connectionOptions.getRtspUri();
}
/**
* Whether the Connection uses adaptative bitrate (and therefore adaptative
* quality) or not. For local network connections that do not require media
* transcoding this can be disabled to save CPU power. If you are not sure if
* transcoding might be necessary, setting this property to false <strong>may
* result in media connections not being established</strong>.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public boolean adaptativeBitrate() {
return this.connectionOptions.adaptativeBitrate();
}
/**
* Whether the IP camera stream of this Connection will only be enabled when
* some user is subscribed to it, or not. This allows you to reduce power
* consumption and network bandwidth in your server while nobody is asking to
* receive the camera's video. On the counterpart, first user subscribing to the
* IP camera stream will take a little longer to receive its video.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public boolean onlyPlayWithSubscribers() {
return this.connectionOptions.onlyPlayWithSubscribers();
}
/**
* Returns the size of the buffer of the endpoint receiving the IP camera's
* stream, in milliseconds. The smaller it is, the less delay the signal will
* have, but more problematic will be in unstable networks. Use short buffers
* only if there is a quality connection between the IP camera and OpenVidu
* Server.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public int getNetworkCache() {
return this.connectionOptions.getNetworkCache();
}
/**
* Returns the token string associated to the Connection
*/
public String getToken() {
return this.token.getToken();
return this.token;
}
/**
@ -180,17 +253,23 @@ public class Connection {
protected JsonObject toJson() {
JsonObject json = new JsonObject();
json.addProperty("id", this.getConnectionId());
json.addProperty("connectionId", this.getConnectionId());
json.addProperty("status", this.getStatus());
json.addProperty("createdAt", this.createdAt());
json.addProperty("activeAt", this.activeAt());
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());
json.addProperty("token", this.getToken());
JsonObject jsonConnectionOptions = this.connectionOptions.toJson("");
jsonConnectionOptions.remove("session");
json.addProperty("serverData", jsonConnectionOptions.get("data").getAsString());
jsonConnectionOptions.remove("data");
jsonConnectionOptions.entrySet().forEach(entry -> {
json.add(entry.getKey(), entry.getValue());
});
JsonArray pubs = new JsonArray();
this.getPublishers().forEach(p -> {
pubs.add(p.toJson());
@ -204,14 +283,33 @@ public class Connection {
return json;
}
/**
* For now only properties data, role and record can be updated
*/
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());
protected void overrideConnectionOptions(ConnectionOptions newConnectionOptions) {
ConnectionOptions.Builder builder = new ConnectionOptions.Builder();
// For now only properties role and record can be updated
if (newConnectionOptions.getRole() != null) {
builder.role(newConnectionOptions.getRole());
} else {
builder.role(this.connectionOptions.getRole());
}
if (newConnectionOptions.record() != null) {
builder.record(newConnectionOptions.record());
} else {
builder.record(this.connectionOptions.record());
}
// Keep old configuration in the rest of properties
builder.type(this.connectionOptions.getType()).data(this.connectionOptions.getData())
.kurentoOptions(this.connectionOptions.getKurentoOptions())
.rtspUri(this.connectionOptions.getRtspUri());
if (this.connectionOptions.adaptativeBitrate() != null) {
builder.adaptativeBitrate(this.connectionOptions.adaptativeBitrate());
}
if (this.connectionOptions.onlyPlayWithSubscribers() != null) {
builder.onlyPlayWithSubscribers(this.connectionOptions.onlyPlayWithSubscribers());
}
if (this.connectionOptions.getNetworkCache() != null) {
builder.networkCache(this.connectionOptions.getNetworkCache());
}
this.connectionOptions = builder.build();
}
protected void setSubscribers(List<String> subscribers) {
@ -220,6 +318,10 @@ public class Connection {
protected Connection resetWithJson(JsonObject json) {
this.connectionId = json.get("connectionId").getAsString();
this.status = json.get("status").getAsString();
this.token = !json.get("token").isJsonNull() ? json.get("token").getAsString() : null;
if (!json.get("publishers").isJsonNull()) {
JsonArray jsonArrayPublishers = json.get("publishers").getAsJsonArray();
@ -284,16 +386,34 @@ public class Connection {
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();
// COMMON
ConnectionType type = ConnectionType.valueOf(json.get("type").getAsString());
String data = (json.has("serverData") && !json.get("serverData").isJsonNull())
? json.get("serverData").getAsString()
: null;
Boolean record = (json.has("record") && !json.get("record").isJsonNull()) ? json.get("record").getAsBoolean()
: null;
TokenOptions tokenOptions = new TokenOptions(role, data, record, null);
this.token = new Token(token, this.connectionId, tokenOptions);
// WEBRTC
OpenViduRole role = (json.has("role") && !json.get("role").isJsonNull())
? OpenViduRole.valueOf(json.get("role").getAsString())
: null;
// IPCAM
String rtspUri = (json.has("rtspUri") && !json.get("rtspUri").isJsonNull()) ? json.get("rtspUri").getAsString()
: null;
Boolean adaptativeBitrate = (json.has("adaptativeBitrate") && !json.get("adaptativeBitrate").isJsonNull())
? json.get("adaptativeBitrate").getAsBoolean()
: null;
Boolean onlyPlayWithSubscribers = (json.has("onlyPlayWithSubscribers")
&& !json.get("onlyPlayWithSubscribers").isJsonNull())
? json.get("onlyPlayWithSubscribers").getAsBoolean()
: null;
Integer networkCache = (json.has("networkCache") && !json.get("networkCache").isJsonNull())
? json.get("networkCache").getAsInt()
: null;
this.connectionOptions = new ConnectionOptions(type, data, record, role, null, rtspUri, adaptativeBitrate,
onlyPlayWithSubscribers, networkCache);
return this;
}

View File

@ -1,15 +1,26 @@
package io.openvidu.java.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
/**
* See
* {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)}
*/
public class ConnectionOptions {
private OpenViduRole role;
private ConnectionType type;
// COMMON
private String data;
private Boolean record;
// WEBRTC
private OpenViduRole role;
private KurentoOptions kurentoOptions;
// IPCAM
private String rtspUri;
private Boolean adaptativeBitrate;
private Boolean onlyPlayWithSubscribers;
private Integer networkCache;
/**
*
@ -18,23 +29,58 @@ public class ConnectionOptions {
*/
public static class Builder {
private OpenViduRole role = OpenViduRole.PUBLISHER;
private ConnectionType type;
// COMMON
private String data;
private Boolean record = true;
private Boolean record;
// WEBRTC
private OpenViduRole role;
private KurentoOptions kurentoOptions;
// IPCAM
private String rtspUri;
private Boolean adaptativeBitrate;
private Boolean onlyPlayWithSubscribers;
private Integer networkCache;
/**
* Builder for {@link io.openvidu.java.client.ConnectionOptions}.
*/
public ConnectionOptions build() {
return new ConnectionOptions(this.role, this.data, this.record, this.kurentoOptions);
return new ConnectionOptions(this.type, this.data, this.record, this.role, this.kurentoOptions,
this.rtspUri, this.adaptativeBitrate, this.onlyPlayWithSubscribers, this.networkCache);
}
/**
* Call this method to set the role assigned to this Connection.
* Call this method to set the type of Connection. The
* {@link io.openvidu.java.client.ConnectionType} dictates what properties will
* have effect:
* <ul>
* <li>{@link io.openvidu.java.client.ConnectionType#WEBRTC}:
* {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean)
* record},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#role(OpenViduRole)
* role},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#kurentoOptions(KurentoOptions)
* kurentoOptions}</li>
* <li>{@link io.openvidu.java.client.ConnectionType#IPCAM}:
* {@link io.openvidu.java.client.ConnectionOptions.Builder#data(String) data},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#record(boolean)
* record},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#rtspUri(String)
* rtspUri},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#adaptativeBitrate(boolean)
* adaptativeBitrate},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#onlyPlayWithSubscribers(boolean)
* onlyPlayWithSubscribers},
* {@link io.openvidu.java.client.ConnectionOptions.Builder#networkCache(int)
* networkCache}</li>
* </ul>
* If not set by default will be @link
* io.openvidu.java.client.ConnectionType#WEBRTC}.
*/
public Builder role(OpenViduRole role) {
this.role = role;
public Builder type(ConnectionType type) {
this.type = type;
return this;
}
@ -76,29 +122,122 @@ public class ConnectionOptions {
return this;
}
/**
* Call this method to set the role assigned to this Connection. If not set by
* default will be {@link io.openvidu.java.client.OpenViduRole#PUBLISHER
* PUBLISHER}.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
*/
public Builder role(OpenViduRole role) {
this.role = role;
return this;
}
/**
* Call this method to set a {@link io.openvidu.java.client.KurentoOptions}
* object for this Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
*/
public Builder kurentoOptions(KurentoOptions kurentoOptions) {
this.kurentoOptions = kurentoOptions;
return this;
}
/**
* Call this method to set the RTSP URI of an IP camera. For example:
* <code>rtsp://your.camera.ip:7777/path</code>
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Builder rtspUri(String rtspUri) {
this.rtspUri = rtspUri;
return this;
}
/**
* Call this method to set whether to use adaptative bitrate (and therefore
* adaptative quality) or not. For local network connections that do not require
* media transcoding this can be disabled to save CPU power. If you are not sure
* if transcoding might be necessary, setting this property to false <strong>may
* result in media connections not being established</strong>. Default to
* <code>true</code>.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Builder adaptativeBitrate(boolean adaptativeBitrate) {
this.adaptativeBitrate = adaptativeBitrate;
return this;
}
/**
* Call this method to set whether to enable the IP camera stream only when some
* user is subscribed to it, or not. This allows you to reduce power consumption
* and network bandwidth in your server while nobody is asking to receive the
* camera's video. On the counterpart, first user subscribing to the IP camera
* stream will take a little longer to receive its video. Default to
* <code>true</code>.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Builder onlyPlayWithSubscribers(boolean onlyPlayWithSubscribers) {
this.onlyPlayWithSubscribers = onlyPlayWithSubscribers;
return this;
}
/**
* Call this method to set the size of the buffer of the endpoint receiving the
* IP camera's stream, in milliseconds. The smaller it is, the less delay the
* signal will have, but more problematic will be in unstable networks. Use
* short buffers only if there is a quality connection between the IP camera and
* OpenVidu Server. Default to <code>2000</code>.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Builder networkCache(int networkCache) {
this.networkCache = networkCache;
return this;
}
}
ConnectionOptions(OpenViduRole role, String data, Boolean record, KurentoOptions kurentoOptions) {
this.role = role;
ConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role,
KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers,
Integer networkCache) {
this.type = type;
this.data = data;
this.record = record;
this.role = role;
this.kurentoOptions = kurentoOptions;
this.rtspUri = rtspUri;
this.adaptativeBitrate = adaptativeBitrate;
this.onlyPlayWithSubscribers = onlyPlayWithSubscribers;
this.networkCache = networkCache;
}
/**
* Returns the role assigned to this Connection.
* Returns the type of Connection.
*/
public OpenViduRole getRole() {
return this.role;
public ConnectionType getType() {
return this.type;
}
/**
@ -118,13 +257,97 @@ public class ConnectionOptions {
return this.record;
}
protected JsonObject toJsonObject(String sessionId) {
/**
* Returns the role assigned to this Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
*/
public OpenViduRole getRole() {
return this.role;
}
/**
* Returns the KurentoOptions assigned to this Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#WEBRTC}</strong>
*/
public KurentoOptions getKurentoOptions() {
return this.kurentoOptions;
}
/**
* Returns the RTSP URI of this Connection.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public String getRtspUri() {
return this.rtspUri;
}
/**
* Whether this Connection uses adaptative bitrate (and therefore adaptative
* quality) or not. For local network connections that do not require media
* transcoding this can be disabled to save CPU power. If you are not sure if
* transcoding might be necessary, setting this property to false <strong>may
* result in media connections not being established</strong>.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Boolean adaptativeBitrate() {
return this.adaptativeBitrate;
}
/**
* Whether to enable the IP camera stream only when some user is subscribed to
* it. This allows you to reduce power consumption and network bandwidth in your
* server while nobody is asking to receive the camera's video. On the
* counterpart, first user subscribing to the IP camera stream will take a
* little longer to receive its video.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Boolean onlyPlayWithSubscribers() {
return this.onlyPlayWithSubscribers;
}
/**
* Size of the buffer of the endpoint receiving the IP camera's stream, in
* milliseconds. The smaller it is, the less delay the signal will have, but
* more problematic will be in unstable networks. Use short buffers only if
* there is a quality connection between the IP camera and OpenVidu Server.
*
* <br>
* <br>
* <strong>Only for
* {@link io.openvidu.java.client.ConnectionType#IPCAM}</strong>
*/
public Integer getNetworkCache() {
return this.networkCache;
}
public JsonObject toJson(String sessionId) {
JsonObject json = new JsonObject();
json.addProperty("session", sessionId);
if (getRole() != null) {
json.addProperty("role", getRole().name());
// COMMON
if (getType() != null) {
json.addProperty("type", getType().name());
} else {
json.add("role", JsonNull.INSTANCE);
json.add("type", JsonNull.INSTANCE);
}
if (getData() != null) {
json.addProperty("data", getData());
@ -136,28 +359,37 @@ public class ConnectionOptions {
} else {
json.add("record", JsonNull.INSTANCE);
}
// WEBRTC
if (getRole() != null) {
json.addProperty("role", getRole().name());
} else {
json.add("role", 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);
json.add("kurentoOptions", kurentoOptions.toJson());
} else {
json.add("kurentoOptions", JsonNull.INSTANCE);
}
// IPCAM
if (getRtspUri() != null) {
json.addProperty("rtspUri", getRtspUri());
} else {
json.add("rtspUri", JsonNull.INSTANCE);
}
if (adaptativeBitrate() != null) {
json.addProperty("adaptativeBitrate", adaptativeBitrate());
} else {
json.add("adaptativeBitrate", JsonNull.INSTANCE);
}
if (onlyPlayWithSubscribers() != null) {
json.addProperty("onlyPlayWithSubscribers", onlyPlayWithSubscribers());
} else {
json.add("onlyPlayWithSubscribers", JsonNull.INSTANCE);
}
if (getNetworkCache() != null) {
json.addProperty("networkCache", getNetworkCache());
} else {
json.add("networkCache", JsonNull.INSTANCE);
}
return json;
}

View File

@ -17,6 +17,11 @@
package io.openvidu.java.client;
import java.util.Arrays;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
/**
* See {@link io.openvidu.java.client.TokenOptions#getKurentoOptions()}
*/
@ -105,10 +110,10 @@ public class KurentoOptions {
}
/**
* Defines the maximum number of Kbps that the client owning the token 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 <a
* href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* Defines the maximum number of Kbps that the Connection will be able to
* receive from Kurento Media Server per media stream. 0 means unconstrained.
* Giving a value to this property will override the global configuration set in
* <a href="https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* target="_blank">OpenVidu Server configuration</a> (parameter
* <code>OPENVIDU_STREAMS_VIDEO_MAX_RECV_BANDWIDTH</code>) for every incoming
* stream of the user owning the token. <br>
@ -122,10 +127,10 @@ public class KurentoOptions {
}
/**
* Defines the minimum number of Kbps that the client owning the token will try
* to receive from Kurento Media Server. 0 means unconstrained. Giving a value
* to this property will override the global configuration set in <a href=
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* Defines the minimum number of Kbps that the Connection will try to receive
* from Kurento Media Server per media stream. 0 means unconstrained. Giving a
* value to this property will override the global configuration set in
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* target="_blank">OpenVidu Server configuration</a> (parameter
* <code>OPENVIDU_STREAMS_VIDEO_MIN_RECV_BANDWIDTH</code>) for every incoming
* stream of the user owning the token.
@ -135,10 +140,10 @@ public class KurentoOptions {
}
/**
* Defines the maximum number of Kbps that the client owning the token 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 <a href=
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* Defines the maximum number of Kbps that the Connection will be able to send
* to Kurento Media Server per media stream. 0 means unconstrained. Giving a
* value to this property will override the global configuration set in
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* target="_blank">OpenVidu Server configuration</a> (parameter
* <code>OPENVIDU_STREAMS_VIDEO_MAX_SEND_BANDWIDTH</code>) for every outgoing
* stream of the user owning the token. <br>
@ -151,10 +156,10 @@ public class KurentoOptions {
}
/**
* Defines the minimum number of Kbps that the client owning the token will try
* to send to Kurento Media Server. 0 means unconstrained. Giving a value to
* this property will override the global configuration set in <a href=
* "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* Defines the minimum number of Kbps that the Connection will try to send to
* Kurento Media Server per media stream. 0 means unconstrained. Giving a value
* to this property will override the global configuration set in
* <a href= "https://docs.openvidu.io/en/stable/reference-docs/openvidu-config/"
* target="_blank">OpenVidu Server configuration</a> (parameter
* <code>OPENVIDU_STREAMS_VIDEO_MIN_SEND_BANDWIDTH</code>) for every outgoing
* stream of the user owning the token.
@ -164,13 +169,50 @@ public class KurentoOptions {
}
/**
* Defines the names of the filters the user owning the token will be able to
* apply. See
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/" target= "_blank">Voice and
* video filters</a>
* Defines the names of the filters the Connection will be able to apply to its
* published streams. See
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/"
* target= "_blank">Voice and video filters</a>.
*/
public String[] getAllowedFilters() {
return allowedFilters;
}
/**
* See if the Connection can apply certain filter. See
* <a href="https://docs.openvidu.io/en/stable/advanced-features/filters/"
* target= "_blank">Voice and video filters</a>.
*/
public boolean isFilterAllowed(String filterType) {
if (filterType == null) {
return false;
}
return Arrays.stream(allowedFilters).anyMatch(filterType::equals);
}
public JsonObject toJson() {
JsonObject json = new JsonObject();
if (this.getVideoMaxRecvBandwidth() != null) {
json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth());
}
if (this.getVideoMinRecvBandwidth() != null) {
json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth());
}
if (this.getVideoMaxSendBandwidth() != null) {
json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth());
}
if (this.getVideoMinSendBandwidth() != null) {
json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth());
}
if (this.getAllowedFilters().length > 0) {
JsonArray filtersJson = new JsonArray();
String[] filters = this.getAllowedFilters();
for (String filter : filters) {
filtersJson.add(filter);
}
json.add("allowedFilters", filtersJson);
}
return json;
}
}

View File

@ -497,6 +497,10 @@ public class OpenVidu {
* since the last time method {@link io.openvidu.java.client.OpenVidu#fetch()}
* was called</strong>. Exceptions to this rule are:
* <ul>
* <li>Calling
* {@link io.openvidu.java.client.OpenVidu#createSession(SessionProperties)
* OpenVidu.createSession} automatically adds the new Session object to the
* local collection.</li>
* <li>Calling {@link io.openvidu.java.client.Session#fetch()} updates that
* specific Session status</li>
* <li>Calling {@link io.openvidu.java.client.Session#close()} automatically

View File

@ -89,8 +89,9 @@ public class Session {
}
/**
* @deprecated Use {@link Session#createToken() Session.createToken()} instead
* to get a {@link io.openvidu.java.client.Token} object.
* @deprecated Use {@link Session#createConnection() Session.createConnection()}
* instead to get a {@link io.openvidu.java.client.Connection}
* object.
*
* @return The generated token String
*
@ -99,14 +100,14 @@ public class Session {
*/
@Deprecated
public String generateToken() throws OpenViduJavaClientException, OpenViduHttpException {
return createToken().getToken();
return generateToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build());
}
/**
* @deprecated Use
* {@link Session#createToken(io.openvidu.java.client.TokenOptions)
* Session.createToken(TokenOptions)} instead to get a
* {@link io.openvidu.java.client.Token} object.
* {@link Session#createConnection(io.openvidu.java.client.ConnectionOptions)
* Session.createConnection(ConnectionOptions)} instead to get a
* {@link io.openvidu.java.client.Connection} object.
*
* @return The generated token String
*
@ -115,70 +116,6 @@ public class Session {
*/
@Deprecated
public String generateToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException {
return createToken(tokenOptions).getToken();
}
/**
* Gets a new token object associated to Session object with default values for
* {@link io.openvidu.java.client.TokenOptions}. The token string value to send
* to the client side can be retrieved with
* {@link io.openvidu.java.client.Token#getToken() Token.getToken()}. <br>
* <br>
* You can use method {@link io.openvidu.java.client.Token#getConnectionId()
* Token.getConnectionId()} to get the connection identifier that will be given
* to the user consuming the token. With <code>connectionId</code> you can call
* the following methods without having to fetch and search for the actual
* {@link io.openvidu.java.client.Connection Connection} object:
* <ul>
* <li>Call {@link io.openvidu.java.client.Session#forceDisconnect(String)
* 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.</li>
* <li>Call
* {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)
* 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
* dynamically change the connection options on the fly.</li>
* </ul>
*
* @return The generated {@link io.openvidu.java.client.Token Token} object.
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public Token createToken() throws OpenViduJavaClientException, OpenViduHttpException {
return createToken(new TokenOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build());
}
/**
* Gets a new token object associated to Session object configured with
* <code>tokenOptions</code>. The token string value to send to the client side
* can be retrieved with {@link io.openvidu.java.client.Token#getToken()
* Token.getToken()}. <br>
* <br>
* You can use method {@link io.openvidu.java.client.Token#getConnectionId()
* Token.getConnectionId()} to get the connection identifier that will be given
* to the user consuming the token. With <code>connectionId</code> you can call
* the following methods without having to fetch and search for the actual
* {@link io.openvidu.java.client.Connection Connection} object:
* <ul>
* <li>Call {@link io.openvidu.java.client.Session#forceDisconnect(String)
* 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.</li>
* <li>Call
* {@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
* dynamically change the user connection options on the fly.</li>
* </ul>
*
* @return The generated {@link io.openvidu.java.client.Token Token} object.
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public Token createToken(TokenOptions tokenOptions) throws OpenViduJavaClientException, OpenViduHttpException {
if (!this.hasSessionId()) {
this.getSessionId();
}
@ -205,8 +142,8 @@ public class Session {
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
Token token = new Token(httpResponseToJson(response));
log.info("Returning a TOKEN: {}", token.getToken());
String token = httpResponseToJson(response).get("id").getAsString();
log.info("Returning a TOKEN: {}", token);
return token;
} else {
throw new OpenViduHttpException(statusCode);
@ -216,6 +153,75 @@ public class Session {
}
}
/**
* Same as
* {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)
* but with default ConnectionOptions values.
*
* @return The generated {@link io.openvidu.java.client.Connection Connection}
* object.
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public Connection createConnection() throws OpenViduJavaClientException, OpenViduHttpException {
return createConnection(
new ConnectionOptions.Builder().data("").role(OpenViduRole.PUBLISHER).record(true).build());
}
/**
* Creates a new Connection object associated to Session object and configured
* with <code>connectionOptions</code>. Each user connecting to the Session
* requires a Connection. The token string value to send to the client side can
* be retrieved with {@link io.openvidu.java.client.Connection#getToken()
* Connection.getToken()}.
*
* @return The generated {@link io.openvidu.java.client.Connection Connection}
* object.
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
public Connection createConnection(ConnectionOptions connectionOptions)
throws OpenViduJavaClientException, OpenViduHttpException {
if (!this.hasSessionId()) {
this.getSessionId();
}
HttpPost request = new HttpPost(
this.openVidu.hostname + OpenVidu.API_SESSIONS + "/" + this.sessionId + "/connection");
StringEntity params;
try {
params = new StringEntity(connectionOptions.toJson(sessionId).toString());
} catch (UnsupportedEncodingException e1) {
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
}
request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
request.setEntity(params);
HttpResponse response;
try {
response = this.openVidu.httpClient.execute(request);
} catch (IOException e2) {
throw new OpenViduJavaClientException(e2.getMessage(), e2.getCause());
}
try {
int statusCode = response.getStatusLine().getStatusCode();
if ((statusCode == org.apache.http.HttpStatus.SC_OK)) {
Connection connection = new Connection(httpResponseToJson(response));
this.connections.put(connection.getConnectionId(), connection);
return connection;
} else {
throw new OpenViduHttpException(statusCode);
}
} finally {
EntityUtils.consumeQuietly(response.getEntity());
}
}
/**
* Gracefully closes the Session: unpublishes all streams and evicts every
* participant.
@ -298,24 +304,31 @@ public class Session {
}
/**
* Forces the user represented by <code>connection</code> to leave the session.
* OpenVidu Browser will trigger the proper events on the client-side
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
* Removes the Connection from the Session. This can translate into a forced
* eviction of a user from the Session if the Connection had status
* <code>active</code>, or into a token invalidation if no user had taken the
* Connection yet (status <code>pending</code>). <br>
* <br>
*
* In the first case, OpenVidu Browser will trigger the proper events on the
* client-side (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
* <code>sessionDisconnected</code>) with reason set to
* <code>"forceDisconnectByServer"</code>. <br>
* <br>
*
* You can get <code>connection</code> parameter with
* {@link io.openvidu.java.client.Session#fetch()} and then
* {@link io.openvidu.java.client.Session#getActiveConnections()}.<br>
* In the second case, the token of the Connection will be invalidated and no
* user will be able to connect to the session with it. <br>
* <br>
*
* 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 connection The Connection to remove
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
@ -324,35 +337,12 @@ public class Session {
}
/**
* Forces the user with Connection <code>connectionId</code> to leave the
* session, or invalidates the {@link Token} associated with that
* <code>connectionId</code> if no user has used it yet. <br>
* <br>
* Same as {@link io.openvidu.java.client.Session#forceDisconnect(Connection)
* forceDisconnect(ConnectionOptions)} but providing the
* {@link io.openvidu.java.client.Connection#getConnectionId() connectionId}
* instead of the Connection object.
*
* In the first case you can get <code>connectionId</code> parameter from
* {@link io.openvidu.java.client.Connection#getConnectionId()
* Connection.getConnectionId()}. Connection objects can be listed with
* {@link io.openvidu.java.client.Session#getActiveConnections()
* Session.getActiveConnections()} (remember to use first
* {@link io.openvidu.java.client.Session#fetch() Session.fetch()} to fetch the
* current active connections from OpenVidu Server). As a result, OpenVidu
* Browser will trigger the proper events on the client-side
* (<code>streamDestroyed</code>, <code>connectionDestroyed</code>,
* <code>sessionDisconnected</code>) with reason set to
* <code>"forceDisconnectByServer"</code>. <br>
* <br>
*
* In the second case you can get <code>connectionId</code> parameter from a
* {@link Token} with {@link Token#getConnectionId()}. As a result, the token
* will be invalidated and no user will be able to connect to the session with
* it. <br>
* <br>
*
* 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
* changes consequence of the execution of this method applied in the local
* objects.
* @param connectionId The identifier of the Connection object to remove
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
@ -400,9 +390,9 @@ public class Session {
}
/**
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
* proper events on the client-side (<code>streamDestroyed</code>) with reason
* set to <code>"forceUnpublishByServer"</code>. <br>
* Forces some Connection to unpublish a Stream. OpenVidu Browser will trigger
* the proper events in the client-side (<code>streamDestroyed</code>) with
* reason set to <code>"forceUnpublishByServer"</code>. <br>
* <br>
*
* You can get <code>publisher</code> parameter with
@ -415,10 +405,13 @@ public class Session {
*
* 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 publisher The Publisher object to unpublish
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
*/
@ -427,26 +420,12 @@ public class Session {
}
/**
* Forces some user to unpublish a Stream. OpenVidu Browser will trigger the
* proper events on the client-side (<code>streamDestroyed</code>) with reason
* set to <code>"forceUnpublishByServer"</code>. <br>
* <br>
* Same as {@link io.openvidu.java.client.Session#forceUnpublish(Publisher)
* forceUnpublish(Publisher)} but providing the
* {@link io.openvidu.java.client.Publisher#getStreamId() streamId} instead of
* the Publisher object.
*
* You can get <code>streamId</code> parameter with
* {@link io.openvidu.java.client.Session#getActiveConnections()} and then for
* each Connection you can call
* {@link io.openvidu.java.client.Connection#getPublishers()}. Finally
* {@link io.openvidu.java.client.Publisher#getStreamId()}) will give you the
* <code>streamId</code>. Remember to call
* {@link io.openvidu.java.client.Session#fetch()} before to fetch the current
* actual properties of the Session from OpenVidu Server.<br>
* <br>
*
* 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
* changes consequence of the execution of this method applied in the local
* objects.
* @param streamId The identifier of the Publisher object to remove
*
* @throws OpenViduJavaClientException
* @throws OpenViduHttpException
@ -520,7 +499,7 @@ public class Session {
StringEntity params;
try {
params = new StringEntity(connectionOptions.toJsonObject(this.sessionId).toString());
params = new StringEntity(connectionOptions.toJson(this.sessionId).toString());
} catch (UnsupportedEncodingException e1) {
throw new OpenViduJavaClientException(e1.getMessage(), e1.getCause());
}
@ -570,6 +549,11 @@ public class Session {
* 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()}.
*
* @param id The Connection to get
*
* @return The {@link io.openvidu.java.client.Connection Connection} object, or
* <code>null</code> if no Connection is found for param <code>id</code>
*/
public Connection getConnection(String id) {
return this.connections.get(id);
@ -581,6 +565,29 @@ public class Session {
* 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()}.
*
* <strong>The list of 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</strong>. Exceptions to this rule are:
* <ul>
* <li>Calling
* {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)
* createConnection(ConnectionOptions)} automatically adds the new Connection
* object to the local collection.</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
* automatically updates each affected local Connection object.</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
* automatically updates each affected local Connection object.</li>
* <li>Calling
* {@link io.openvidu.java.client.Session#updateConnection(String, ConnectionOptions)}
* automatically updates the attributes of the affected local Connection
* object.</li>
* </ul>
* <br>
* To get the list of connections with their 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<Connection> getConnections() {
return this.connections.values().stream().collect(Collectors.toList());
@ -596,6 +603,10 @@ public class Session {
* or {@link io.openvidu.java.client.OpenVidu#fetch() OpenVidu.fetch()} was
* called</strong>. Exceptions to this rule are:
* <ul>
* <li>Calling
* {@link io.openvidu.java.client.Session#createConnection(ConnectionOptions)
* createConnection(ConnectionOptions)} automatically adds the new Connection
* object to the local collection.</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceUnpublish(String)}
* automatically updates each affected local Connection object.</li>
* <li>Calling {@link io.openvidu.java.client.Session#forceDisconnect(String)}
@ -609,7 +620,7 @@ public class Session {
* To get the list of active connections with their 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()}.
* OpenVidu.fetch()} OpenVidu.fetch()}.
*/
public List<Connection> getActiveConnections() {
return this.connections.values().stream().filter(con -> "active".equals(con.getStatus()))

View File

@ -1,127 +0,0 @@
package io.openvidu.java.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
public class Token {
private String token;
private String connectionId;
private TokenOptions tokenOptions;
protected Token(String token, String connectionId, TokenOptions tokenOptions) {
this.token = token;
this.connectionId = connectionId;
this.tokenOptions = tokenOptions;
}
protected Token(JsonObject json) {
this.token = json.get("token").getAsString();
this.connectionId = json.get("connectionId").getAsString();
OpenViduRole role = OpenViduRole.valueOf(json.get("role").getAsString());
String data = json.get("data").getAsString();
Boolean record = json.get("record").getAsBoolean();
KurentoOptions kurentoOptions = null;
if (json.has("kurentoOptions")) {
JsonObject kurentoOptionsJson = json.get("kurentoOptions").getAsJsonObject();
Integer videoMaxRecvBandwidth = null;
Integer videoMinRecvBandwidth = null;
Integer videoMaxSendBandwidth = null;
Integer videoMinSendBandwidth = null;
String[] allowedFilters = null;
if (kurentoOptionsJson.has("videoMaxRecvBandwidth")) {
videoMaxRecvBandwidth = kurentoOptionsJson.get("videoMaxRecvBandwidth").getAsInt();
}
if (kurentoOptionsJson.has("videoMinRecvBandwidth")) {
videoMinRecvBandwidth = kurentoOptionsJson.get("videoMinRecvBandwidth").getAsInt();
}
if (kurentoOptionsJson.has("videoMaxSendBandwidth")) {
videoMaxSendBandwidth = kurentoOptionsJson.get("videoMaxSendBandwidth").getAsInt();
}
if (kurentoOptionsJson.has("videoMinSendBandwidth")) {
videoMinSendBandwidth = kurentoOptionsJson.get("videoMinSendBandwidth").getAsInt();
}
if (kurentoOptionsJson.has("allowedFilters")) {
JsonArray filters = kurentoOptionsJson.get("allowedFilters").getAsJsonArray();
allowedFilters = new String[filters.size()];
for (int i = 0; i < filters.size(); i++) {
allowedFilters[i] = filters.get(i).getAsString();
}
}
kurentoOptions = new KurentoOptions(videoMaxRecvBandwidth, videoMinRecvBandwidth, videoMaxSendBandwidth,
videoMinSendBandwidth, allowedFilters);
}
this.tokenOptions = new TokenOptions(role, data, record, kurentoOptions);
}
/**
* Returns the token string value that must be sent to clients. They need to use
* it to connect to the session.
*/
public String getToken() {
return this.token;
}
/**
* Returns the connection identifier that will be associated to the user
* consuming this token. This means that the future
* {@link io.openvidu.java.client.Connection Connection} object created with
* this token will have as <code>connectionId</code> this string. In other
* words, method {@link io.openvidu.java.client.Connection#getConnectionId()
* Connection.getConnectionId()} will return this same value.
*
* With <code>connectionId</code> you can call the following methods without
* having to fetch and search for the actual
* {@link io.openvidu.java.client.Connection Connection} object:
* <ul>
* <li>Call {@link io.openvidu.java.client.Session#forceDisconnect(String)
* 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.</li>
* <li>Call
* {@link io.openvidu.java.client.Session#updateConnection(String, TokenOptions)
* 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
* dynamically change the connection options on the fly.</li>
* </ul>
*
*/
public String getConnectionId() {
return this.connectionId;
}
/**
* Returns the role assigned to this token.
*/
public OpenViduRole getRole() {
return this.tokenOptions.getRole();
}
/**
* Returns the secure (server-side) metadata assigned to this token.
*/
public String getData() {
return this.tokenOptions.getData();
}
/**
* Whether the streams published by the participant owning this token 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.tokenOptions.record();
}
protected void overrideTokenOptions(TokenOptions tokenOptions) {
this.tokenOptions = tokenOptions;
}
}

View File

@ -17,12 +17,12 @@
package io.openvidu.java.client;
import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
/**
* See {@link io.openvidu.java.client.Session#generateToken(TokenOptions)}
* @deprecated Use {@link io.openvidu.java.client.ConnectionOptions
* ConnectionOptions} instead
*/
public class TokenOptions {
@ -32,9 +32,8 @@ public class TokenOptions {
private KurentoOptions kurentoOptions;
/**
*
* Builder for {@link io.openvidu.java.client.TokenOptions}
*
* @deprecated Use {@link io.openvidu.java.client.ConnectionOptions.Builder
* ConnectionOptions.Builder} instead
*/
public static class Builder {
@ -157,27 +156,7 @@ public class TokenOptions {
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);
json.add("kurentoOptions", kurentoOptions.toJson());
}
return json;
}

View File

@ -15,9 +15,9 @@
*
*/
import { OpenViduRole } from './OpenViduRole';
import { Publisher } from './Publisher';
import { ConnectionOptions } from './ConnectionOptions';
import { OpenViduRole } from 'OpenViduRole';
/**
* See [[Session.connections]]
@ -25,13 +25,13 @@ import { ConnectionOptions } from './ConnectionOptions';
export class Connection {
/**
* Identifier of the connection. You can call methods [[Session.forceDisconnect]]
* Identifier of the Connection. You can call methods [[Session.forceDisconnect]]
* or [[Session.updateConnection]] passing this property as parameter
*/
connectionId: string;
/**
* Returns the status of the connection. Can be:
* Returns the status of the Connection. Can be:
* - `pending`: if the Connection is waiting for any user to use
* its internal token to connect to the session, calling method
* [Session.connect](https://docs.openvidu.io/en/stable/api/openvidu-browser/classes/session.html#connect)
@ -43,39 +43,19 @@ export class Connection {
status: string;
/**
* Timestamp when this connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
* Timestamp when the Connection was created, in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
*/
createdAt: number;
/**
* Timestamp when this connection was taken by a user (passing from status "pending" to "active")
* Timestamp when the Connection was taken by a user (passing from status "pending" to "active")
* in UTC milliseconds (ms since Jan 1, 1970, 00:00:00 UTC)
*/
activeAt: number;
/**
* Role of the connection
*/
role: OpenViduRole;
/**
* Data associated to the connection on the server-side. This value is set with property [[TokenOptions.data]] when calling [[Session.generateToken]]
*/
serverData: string;
/**
* Whether to record the streams published by the participant owning this token or not. This only affects [INDIVIDUAL recording](/en/stable/advanced-features/recording#selecting-streams-to-be-recorded)
*/
record: boolean;
/**
* Token associated to the connection
*/
token: string;
/**
* <a href="https://docs.openvidu.io/en/stable/openvidu-pro/" target="_blank" style="display: inline-block; background-color: rgb(0, 136, 170); color: white; font-weight: bold; padding: 0px 5px; margin-right: 5px; border-radius: 3px; font-size: 13px; line-height:21px; font-family: Montserrat, sans-serif">PRO</a>
* Geo location of the connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it)
* Geo location of the Connection, with the following format: `"CITY, COUNTRY"` (`"unknown"` if it wasn't possible to locate it)
*/
location: string;
@ -85,11 +65,21 @@ export class Connection {
platform: string;
/**
* Data associated to the connection on the client-side. This value is set with second parameter of method
* Data associated to the Connection on the client-side. This value is set with second parameter of method
* [Session.connect](/en/stable/api/openvidu-browser/classes/session.html#connect) in OpenVidu Browser
*/
clientData: string;
/**
* The [[ConnectionOptions]] assigned to the Connection
*/
connectionOptions: ConnectionOptions;
/**
* Token associated to the Connection
*/
token: string;
/**
* Array of Publisher objects this particular Connection is publishing to the Session (each Publisher object has one Stream, uniquely
* identified by its `streamId`). You can call [[Session.forceUnpublish]] passing any of this values as parameter
@ -102,6 +92,15 @@ export class Connection {
*/
subscribers: string[] = [];
/**
* @hidden deprecated. Inside ConnectionOptions
*/
role?: OpenViduRole;
/**
* @hidden deprecated. Inside ConnectionOptions
*/
serverData?: string;
/**
* @hidden
*/
@ -114,15 +113,41 @@ export class Connection {
*/
resetWithJson(json): Connection {
// These properties won't ever be null
this.connectionId = json.connectionId;
this.status = json.status;
this.createdAt = json.createdAt;
this.activeAt = json.activeAt;
this.location = json.location;
this.platform = json.platform;
this.clientData = json.clientData;
this.token = json.token;
if (this.connectionOptions != null) {
this.connectionOptions.type = json.type;
this.connectionOptions.data = json.data;
this.connectionOptions.record = json.record;
this.connectionOptions.role = json.role;
this.connectionOptions.kurentoOptions = json.kurentoOptions;
this.connectionOptions.rtspUri = json.rtspUri;
this.connectionOptions.adaptativeBitrate = json.adaptativeBitrate;
this.connectionOptions.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers;
this.connectionOptions.networkCache = json.networkCache;
} else {
this.connectionOptions = {
type: json.type,
data: json.data,
record: json.record,
role: json.role,
kurentoOptions: json.kurentoOptions,
rtspUri: json.rtspUri,
adaptativeBitrate: json.adaptativeBitrate,
onlyPlayWithSubscribers: json.onlyPlayWithSubscribers,
networkCache: json.networkCache
}
}
this.role = json.role;
this.serverData = json.serverData;
this.record = json.record;
this.serverData = json.data;
// These properties may be null
// publishers may be null
if (json.publishers != null) {
// 1. Array to store fetched Publishers and later remove closed ones
@ -151,6 +176,7 @@ export class Connection {
}
// subscribers may be null
if (json.subscribers != null) {
// 1. Array to store fetched Subscribers and later remove closed ones
@ -171,12 +197,6 @@ export class Connection {
}
}
this.createdAt = json.createdAt;
this.activeAt = json.activeAt;
this.location = json.location;
this.platform = json.platform;
this.clientData = json.clientData;
return this;
}
@ -189,9 +209,15 @@ export class Connection {
this.status === other.status &&
this.createdAt === other.createdAt &&
this.activeAt === other.activeAt &&
this.role === other.role &&
this.serverData === other.serverData &&
this.record === other.record &&
this.connectionOptions.type === other.connectionOptions.type &&
this.connectionOptions.data === other.connectionOptions.data &&
this.connectionOptions.record === other.connectionOptions.record &&
this.connectionOptions.role === other.connectionOptions.role &&
this.connectionOptions.kurentoOptions === other.connectionOptions.kurentoOptions &&
this.connectionOptions.rtspUri === other.connectionOptions.rtspUri &&
this.connectionOptions.adaptativeBitrate === other.connectionOptions.adaptativeBitrate &&
this.connectionOptions.onlyPlayWithSubscribers === other.connectionOptions.onlyPlayWithSubscribers &&
this.connectionOptions.networkCache === other.connectionOptions.networkCache &&
this.token === other.token &&
this.location === other.location &&
this.platform === other.platform &&
@ -218,12 +244,13 @@ export class Connection {
/**
* @hidden
*/
overrideConnectionOptions(connectionOptions: ConnectionOptions): void {
if (connectionOptions.role != null) {
this.role = connectionOptions.role;
overrideConnectionOptions(newConnectionOptions: ConnectionOptions): void {
// For now only properties record and role
if (newConnectionOptions.record != null) {
this.connectionOptions.record = newConnectionOptions.record;
}
if (connectionOptions.record != null) {
this.record = connectionOptions.record
if (newConnectionOptions.role != null) {
this.connectionOptions.role = newConnectionOptions.role;
}
}

View File

@ -15,16 +15,20 @@
*
*/
import { ConnectionType } from 'ConnectionType';
import { OpenViduRole } from './OpenViduRole';
export interface ConnectionOptions {
/**
* The role assigned to this Connection
* Type of Connection. The [[ConnectionType]] dictates what properties will have effect:
*
* @default PUBLISHER
* - **[[ConnectionType.WEBRTC]]**: [[data]], [[record]], [[role]], [[kurentoOptions]]
* - **[[ConnectionType.IPCAM]]**: [[data]], [[record]], [[rtspUri]], [[adaptativeBitrate]], [[onlyPlayWithSubscribers]], [[networkCache]]
*
* @default WEBRTC
*/
role?: OpenViduRole;
type?: ConnectionType;
/**
* 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.
@ -41,6 +45,15 @@ export interface ConnectionOptions {
*/
record?: boolean;
/**
* The role assigned to this Connection
*
* **Only for [[ConnectionType.WEBRTC]]**
*
* @default PUBLISHER
*/
role?: OpenViduRole;
/**
* **WARNING**: experimental option. This interface may change in the near future
*
@ -61,6 +74,8 @@ export interface ConnectionOptions {
* 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/)
*
* **Only for [[ConnectionType.WEBRTC]]**
*/
kurentoOptions?: {
videoMaxRecvBandwidth?: number,
@ -69,4 +84,45 @@ export interface ConnectionOptions {
videoMinSendBandwidth?: number,
allowedFilters?: string[]
};
/**
* RTSP URI of an IP camera. For example: `rtsp://your.camera.ip:7777/path`
*
* **Only for [[ConnectionType.IPCAM]]**
*/
rtspUri?: string;
/**
* Whether to use adaptative bitrate (and therefore adaptative quality) or not. For local network connections
* that do not require media transcoding this can be disabled to save CPU power. If you are not sure if transcoding
* might be necessary, setting this property to false **may result in media connections not being established**.
*
* **Only for [[ConnectionType.IPCAM]]**
*
* @default true
*/
adaptativeBitrate?: boolean;
/**
* Whether to enable the IP camera stream only when some user is subscribed to it, or not. This allows you to reduce
* power consumption and network bandwidth in your server while nobody is asking to receive the camera's video.
* On the counterpart, first user subscribing to the IP camera stream will take a little longer to receive its video.
*
* **Only for [[ConnectionType.IPCAM]]**
*
* @default true
*/
onlyPlayWithSubscribers?: boolean;
/**
* Size of the buffer of the endpoint receiving the IP camera's stream, in milliseconds. The smaller it is, the less
* delay the signal will have, but more problematic will be in unstable networks. Use short buffers only if there is
* a quality connection between the IP camera and OpenVidu Server.
*
* **Only for [[ConnectionType.IPCAM]]**
*
* @default 2000
*/
networkCache?: number;
}

View File

@ -0,0 +1,34 @@
/*
* (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.
*
*/
/**
* See [[Session.createConnection]]
*/
export enum ConnectionType {
/**
* WebRTC connection. This is the normal type of Connection for a regular user
* connecting to a session from an application.
*/
WEBRTC = 'WEBRTC',
/**
* IP camera connection. This is the type of Connection used by IP cameras to
* connect to a session.
*/
IPCAM = 'IPCAM'
}

View File

@ -76,6 +76,7 @@ export class OpenVidu {
* Array of active sessions. **This value will remain unchanged since the last time method [[OpenVidu.fetch]]
* was called**. Exceptions to this rule are:
*
* - Calling [[OpenVidu.createSession]] automatically adds the new Session object to the local collection.
* - Calling [[Session.fetch]] updates that specific Session status
* - Calling [[Session.close]] automatically removes the Session from the list of active Sessions
* - Calling [[Session.forceDisconnect]] automatically updates the inner affected connections for that specific Session

View File

@ -25,10 +25,8 @@ import { Recording } from './Recording';
import { RecordingLayout } from './RecordingLayout';
import { RecordingMode } from './RecordingMode';
import { SessionProperties } from './SessionProperties';
import { Token } from './Token';
import { TokenOptions } from './TokenOptions';
export class Session {
/**
@ -51,6 +49,7 @@ export class Session {
* **will remain unchanged since the last time method [[Session.fetch]] or [[OpenVidu.fetch]] was called**.
* Exceptions to this rule are:
*
* - Calling [[Session.createConnection]] automatically adds the new Connection object to the local collection.
* - 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.
@ -105,37 +104,12 @@ export class Session {
}
/**
* @deprecated Use [[Session.createToken]] instead to get a [[Token]] object.
* @deprecated Use [[Session.createConnection]] instead to get a [[Connection]] object.
*
* @returns A Promise that is resolved to the generated _token_ string if success and rejected with an Error object if not
*/
public generateToken(tokenOptions?: TokenOptions): Promise<string> {
return new Promise<string>((resolve, reject) => {
this.createToken(tokenOptions).then(token => resolve(token.token)).catch(error => reject(error));
});
}
/**
* Gets a new token object associated to Session object configured with
* `tokenOptions`. The token string value to send to the client side
* is available at [[Token.token]] property.
*
* Property [[Token.connectionId]] provides the connection identifier that will be given
* to the user consuming the token. With `connectionId` you can call
* the following methods without having to fetch and search for the actual
* [[Connection]] object:
*
* - Call [[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 [[Session.updateConnection]] to update the [[Connection]] options. And this is
* valid for unused tokens, but also for already used tokens, so you can
* dynamically change the user connection options on the fly.
*
* @returns A Promise that is resolved to the generated [[Token]] object if success and rejected with an Error object if not
*/
public createToken(tokenOptions?: TokenOptions): Promise<Token> {
return new Promise<Token>((resolve, reject) => {
const data = JSON.stringify({
session: this.sessionId,
role: (!!tokenOptions && !!tokenOptions.role) ? tokenOptions.role : null,
@ -156,7 +130,51 @@ export class Session {
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server. Resolve token
resolve(new Token(res.data));
resolve(res.data.token);
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
}
}).catch(error => {
this.handleError(error, reject);
});
});
}
/**
* Creates a new Connection object associated to Session object and configured with
* `connectionOptions`. Each user connecting to the Session requires a Connection.
* The token string value to send to the client side is available at [[Connection.token]].
*
* @returns A Promise that is resolved to the generated [[Connection]] object if success and rejected with an Error object if not
*/
public createConnection(connectionOptions?: ConnectionOptions): Promise<Connection> {
return new Promise<Connection>((resolve, reject) => {
const data = JSON.stringify({
role: (!!connectionOptions && !!connectionOptions.role) ? connectionOptions.role : null,
data: (!!connectionOptions && !!connectionOptions.data) ? connectionOptions.data : null,
record: !!connectionOptions ? connectionOptions.record : null,
kurentoOptions: (!!connectionOptions && !!connectionOptions.kurentoOptions) ? connectionOptions.kurentoOptions : null
});
axios.post(
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection',
data,
{
headers: {
'Authorization': this.ov.basicAuth,
'Content-Type': 'application/json'
}
}
)
.then(res => {
if (res.status === 200) {
// SUCCESS response from openvidu-server. Store and resolve Connection
const connection = new Connection(res.data);
this.connections.push(connection);
if (connection.status === 'active') {
this.activeConnections.push(connection);
}
resolve(new Connection(res.data));
} else {
// ERROR response from openvidu-server. Resolve HTTP status
reject(new Error(res.status.toString()));
@ -240,12 +258,18 @@ export class Session {
}
/**
* Removes a Connection from the Session.
* Removes the Connection from the Session. This can translate into a forced eviction of a user from the Session if the
* Connection had status `active` or into a token invalidation if no user had taken the Connection yet (status `pending`).
*
* In the first case, OpenVidu Browser will trigger the proper events in the client-side (`streamDestroyed`, `connectionDestroyed`,
* `sessionDisconnected`) with reason set to `"forceDisconnectByServer"`.
*
* In the second case, the token of the Connection will be invalidated and no user will be able to connect to the session with it.
*
* This method automatically updates the properties of the local affected objects. This means that there is no need to call
* [[Session.fetch]] or [[OpenVidu.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
* @param connection The Connection object to remove from the session, or its `connectionId` property
*
* @returns A Promise that is resolved if the Connection was successfully removed from the Session and rejected with an Error object if not
*/
@ -308,7 +332,7 @@ export class Session {
}
/**
* Forces some user to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it).
* Forces some Connection to unpublish a Stream (identified by its `streamId` or the corresponding [[Publisher]] object owning it).
* OpenVidu Browser will trigger the proper events on the client-side (`streamDestroyed`) with reason set to `"forceUnpublishByServer"`.
*
* You can get `publisher` parameter from [[Connection.publishers]] array ([[Publisher.streamId]] for getting each `streamId` property).
@ -317,6 +341,8 @@ export class Session {
* This method automatically updates the properties of the local affected objects. This means that there is no need to call
* [[Session.fetch]] or [[OpenVidu.fetch]] to see the changes consequence of the execution of this method applied in the local objects.
*
* @param publisher The Publisher object to unpublish, or its `streamId` property
*
* @returns A Promise that is resolved if the stream was successfully unpublished and rejected with an Error object if not
*/
public forceUnpublish(publisher: string | Publisher): Promise<any> {

View File

@ -1,81 +0,0 @@
/*
* (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 { TokenOptions } from './TokenOptions';
export class Token {
/**
* The token string value that must be sent to clients. They need to use it to connect to the session.
*/
token: string;
/**
* The connection identifier that will be associated to the user
* consuming this token. This means that the future [[Connection]] object created with
* this token will have as [[Connection.connectionId]] this same value.
*
* With `connectionId` you can call the following methods without
* having to fetch and search for the actual [[Connection]] object:
*
* - Call [[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 [[Session.updateConnection]] to update the [[Connection]] options. And this is
* valid for unused tokens, but also for already used tokens, so you can
* dynamically change the connection options on the fly.
*/
connectionId: string;
/**
* The [[TokenOptions]] assigned to this token.
*/
tokenOptions: TokenOptions;
/**
* @hidden
*/
constructor(json) {
this.token = json.token;
this.connectionId = json.connectionId;
let possibleKurentoOptions;
if (!!json.kurentoOptions) {
possibleKurentoOptions = {};
if (json.kurentoOptions.videoMaxRecvBandwidth != null) {
possibleKurentoOptions['videoMaxRecvBandwidth'] = json.kurentoOptions.videoMaxRecvBandwidth;
}
if (json.kurentoOptions.videoMinRecvBandwidth != null) {
possibleKurentoOptions['videoMinRecvBandwidth'] = json.kurentoOptions.videoMinRecvBandwidth;
}
if (json.kurentoOptions.videoMaxSendBandwidth != null) {
possibleKurentoOptions['videoMaxSendBandwidth'] = json.kurentoOptions.videoMaxSendBandwidth;
}
if (json.kurentoOptions.videoMinSendBandwidth != null) {
possibleKurentoOptions['videoMinSendBandwidth'] = json.kurentoOptions.videoMinSendBandwidth;
}
if (json.kurentoOptions.allowedFilters != null) {
possibleKurentoOptions['allowedFilters'] = json.kurentoOptions.allowedFilters;
}
}
this.tokenOptions = {
role: json.role,
data: json.data,
record: json.record,
kurentoOptions: possibleKurentoOptions
};
}
}

View File

@ -18,7 +18,7 @@
import { OpenViduRole } from './OpenViduRole';
/**
* See [[Session.generateToken]]
* @deprecated Use [[ConnectionOptions]] instead
*/
export interface TokenOptions {

View File

@ -4,7 +4,7 @@ export * from './Session';
export * from './SessionProperties';
export * from './TokenOptions';
export * from './ConnectionOptions';
export * from './Token';
export * from './ConnectionType';
export * from './MediaMode';
export * from './RecordingLayout';
export * from './RecordingMode';

View File

@ -22,7 +22,6 @@ import java.util.concurrent.locks.ReentrantLock;
import com.google.gson.JsonObject;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.server.kurento.endpoint.EndpointType;
import io.openvidu.server.utils.GeoLocation;
@ -44,7 +43,6 @@ public class Participant {
active
}
protected ConnectionType type; // WEBRTC, IPCAM
protected String finalUserId; // ID to match this connection with a final user (HttpSession id)
protected String participantPrivatetId; // ID to identify the user on server (org.kurento.jsonrpc.Session.id)
protected String participantPublicId; // ID to identify the user on clients
@ -52,7 +50,6 @@ public class Participant {
protected ParticipantStatus status; // Status of the connection
protected Long activeAt; // Timestamp when this connection entered status "active"
protected String clientMetadata = ""; // Metadata provided on client side
protected String serverMetadata = ""; // Metadata provided on server side
protected Token token; // Token associated to this participant
protected GeoLocation location; // Location of the participant
protected String platform; // Platform used by the participant to connect to the session
@ -78,10 +75,9 @@ public class Participant {
*/
public Lock singleRecordingLock = new ReentrantLock();
public Participant(ConnectionType type, String finalUserId, String participantPrivatetId,
String participantPublicId, String sessionId, Token token, String clientMetadata, GeoLocation location,
String platform, EndpointType endpointType, Long activeAt) {
this.type = type;
public Participant(String finalUserId, String participantPrivatetId, String participantPublicId, String sessionId,
Token token, String clientMetadata, GeoLocation location, String platform, EndpointType endpointType,
Long activeAt) {
this.finalUserId = finalUserId;
this.participantPrivatetId = participantPrivatetId;
this.participantPublicId = participantPublicId;
@ -96,18 +92,11 @@ public class Participant {
if (clientMetadata != null) {
this.clientMetadata = clientMetadata;
}
if (!token.getServerMetadata().isEmpty()) {
this.serverMetadata = token.getServerMetadata();
}
this.location = location;
this.platform = platform;
this.endpointType = endpointType;
}
public ConnectionType getType() {
return type;
}
public String getFinalUserId() {
return finalUserId;
}
@ -145,11 +134,7 @@ public class Participant {
}
public String getServerMetadata() {
return serverMetadata;
}
public void setServerMetadata(String serverMetadata) {
this.serverMetadata = serverMetadata;
return this.token.getServerMetadata();
}
public Token getToken() {
@ -234,16 +219,16 @@ public class Participant {
public String getFullMetadata() {
String fullMetadata;
if ((!this.clientMetadata.isEmpty()) && (!this.serverMetadata.isEmpty())) {
fullMetadata = this.clientMetadata + METADATA_SEPARATOR + this.serverMetadata;
if ((!this.clientMetadata.isEmpty()) && (!this.token.getServerMetadata().isEmpty())) {
fullMetadata = this.clientMetadata + METADATA_SEPARATOR + this.token.getServerMetadata();
} else {
fullMetadata = this.clientMetadata + this.serverMetadata;
fullMetadata = this.clientMetadata + this.token.getServerMetadata();
}
return fullMetadata;
}
public void deleteIpcamProperties() {
this.clientMetadata = "";
this.clientMetadata = null;
this.token.setToken(null);
}
@ -305,9 +290,9 @@ public class Participant {
public JsonObject toJson() {
JsonObject json = new JsonObject();
// COMMON
json.addProperty("id", this.participantPublicId);
json.addProperty("object", "connection");
json.addProperty("type", this.type.name());
json.addProperty("status", this.status.name());
json.addProperty("connectionId", this.participantPublicId); // TODO: deprecated. Better use only "id"
json.addProperty("sessionId", this.sessionId);
@ -317,10 +302,14 @@ public class Participant {
json.addProperty("platform", this.platform);
if (this.token.getToken() != null) {
json.addProperty("token", this.token.getToken());
} else {
json.add("token", null);
}
json.addProperty("role", this.token.getRole().name());
json.addProperty("serverData", this.serverMetadata);
json.addProperty("record", this.token.record());
// Add all ConnectionOptions
JsonObject connectionOptionsJson = this.token.getConnectionOptionsWithFinalJsonFormat();
connectionOptionsJson.entrySet().forEach(entry -> {
json.add(entry.getKey(), entry.getValue());
});
json.addProperty("clientData", this.clientMetadata);
return json;
}

View File

@ -45,14 +45,15 @@ import com.google.gson.JsonSyntaxException;
import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code;
import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording;
import io.openvidu.java.client.SessionProperties;
import io.openvidu.server.cdr.CDREventRecording;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.coturn.CoturnCredentialsService;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
import io.openvidu.server.kurento.endpoint.EndpointType;
import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.utils.FormatChecker;
@ -160,8 +161,8 @@ public abstract class SessionManager {
public abstract void removeFilterEventListener(Session session, Participant subscriber, String streamId,
String eventType);
public abstract Participant publishIpcam(Session session, MediaOptions mediaOptions, String serverMetadata)
throws Exception;
public abstract Participant publishIpcam(Session session, MediaOptions mediaOptions,
ConnectionOptions connectionOptions) throws Exception;
public abstract void reconnectStream(Participant participant, String streamId, String sdpOffer,
Integer transactionId);
@ -301,22 +302,22 @@ public abstract class SessionManager {
}
public Token newToken(Session session, OpenViduRole role, String serverMetadata, boolean record,
KurentoTokenOptions kurentoTokenOptions) throws Exception {
KurentoOptions kurentoOptions) throws Exception {
if (!formatChecker.isServerMetadataFormatCorrect(serverMetadata)) {
log.error("Data invalid format");
throw new OpenViduException(Code.GENERIC_ERROR_CODE, "Data invalid format");
}
Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), role, serverMetadata, record,
kurentoTokenOptions);
Token tokenObj = tokenGenerator.generateToken(session.getSessionId(), serverMetadata,
record, role, kurentoOptions);
session.storeToken(tokenObj);
session.showTokens("Token created");
return tokenObj;
}
public Token newTokenForInsecureUser(Session session, String token, String serverMetadata) throws Exception {
Token tokenObj = new Token(token, session.getSessionId(), OpenViduRole.PUBLISHER,
serverMetadata != null ? serverMetadata : "", true,
this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null, null);
public Token newTokenForInsecureUser(Session session, String token, ConnectionOptions connectionOptions)
throws Exception {
Token tokenObj = new Token(token, session.getSessionId(), connectionOptions,
this.openviduConfig.isTurnadminAvailable() ? this.coturnCredentialsService.createUser() : null);
session.storeToken(tokenObj);
session.showTokens("Token created for insecure user");
return tokenObj;
@ -364,9 +365,8 @@ public abstract class SessionManager {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(ConnectionType.WEBRTC, finalUserId, participantPrivatetId,
token.getConnectionId(), sessionId, token, clientMetadata, location, platform,
EndpointType.WEBRTC_ENDPOINT, null);
Participant p = new Participant(finalUserId, participantPrivatetId, token.getConnectionId(), sessionId,
token, clientMetadata, location, platform, EndpointType.WEBRTC_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId).put(p.getParticipantPublicId(), p);
@ -386,9 +386,8 @@ public abstract class SessionManager {
public Participant newRecorderParticipant(String sessionId, String participantPrivatetId, Token token,
String clientMetadata) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(ConnectionType.WEBRTC, null, participantPrivatetId,
ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, sessionId, token, clientMetadata, null, null,
EndpointType.WEBRTC_ENDPOINT, null);
Participant p = new Participant(null, participantPrivatetId, ProtocolElements.RECORDER_PARTICIPANT_PUBLICID,
sessionId, token, clientMetadata, null, null, EndpointType.WEBRTC_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId)
.put(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID, p);
return p;
@ -400,8 +399,8 @@ public abstract class SessionManager {
public Participant newIpcamParticipant(String sessionId, String ipcamId, Token token, GeoLocation location,
String platform) {
if (this.sessionidParticipantpublicidParticipant.get(sessionId) != null) {
Participant p = new Participant(ConnectionType.IPCAM, ipcamId, ipcamId, ipcamId, sessionId, token, null,
location, platform, EndpointType.PLAYER_ENDPOINT, null);
Participant p = new Participant(ipcamId, ipcamId, ipcamId, sessionId, token, null, location, platform,
EndpointType.PLAYER_ENDPOINT, null);
this.sessionidParticipantpublicidParticipant.get(sessionId).put(ipcamId, p);
return p;
} else {

View File

@ -21,95 +21,113 @@ import org.apache.commons.lang3.RandomStringUtils;
import com.google.gson.JsonObject;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.server.core.Participant.ParticipantStatus;
import io.openvidu.server.coturn.TurnCredentials;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
public class Token {
private String token;
private String sessionId;
private Long createdAt;
private OpenViduRole role;
private String serverMetadata = "";
private boolean record;
private ConnectionOptions connectionOptions;
private TurnCredentials turnCredentials;
private KurentoTokenOptions kurentoTokenOptions;
private final String connectionId = IdentifierPrefixes.PARTICIPANT_PUBLIC_ID
+ RandomStringUtils.randomAlphabetic(1).toUpperCase() + RandomStringUtils.randomAlphanumeric(9);
public Token(String token, String sessionId, OpenViduRole role, String serverMetadata, boolean record,
TurnCredentials turnCredentials, KurentoTokenOptions kurentoTokenOptions) {
public Token(String token, String sessionId, ConnectionOptions connectionOptions, TurnCredentials turnCredentials) {
this.token = token;
this.sessionId = sessionId;
this.createdAt = System.currentTimeMillis();
this.role = role;
this.serverMetadata = serverMetadata;
this.record = record;
this.connectionOptions = connectionOptions;
this.turnCredentials = turnCredentials;
this.kurentoTokenOptions = kurentoTokenOptions;
}
public ConnectionType getType() {
return this.connectionOptions.getType();
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
public void setToken(String newToken) {
this.token = newToken;
}
public Long getCreatedAt() {
return this.createdAt;
}
public OpenViduRole getRole() {
return role;
}
public String getServerMetadata() {
return serverMetadata;
return this.connectionOptions.getData();
}
public boolean record() {
return record;
return this.connectionOptions.record();
}
public void setRecord(boolean newRecord) {
this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(), newRecord,
connectionOptions.getRole(), connectionOptions.getKurentoOptions(), connectionOptions.getRtspUri(),
connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(),
connectionOptions.getNetworkCache());
}
public OpenViduRole getRole() {
return this.connectionOptions.getRole();
}
public void setRole(OpenViduRole newRole) {
this.updateConnectionOptions(connectionOptions.getType(), connectionOptions.getData(),
connectionOptions.record(), newRole, connectionOptions.getKurentoOptions(),
connectionOptions.getRtspUri(), connectionOptions.adaptativeBitrate(),
connectionOptions.onlyPlayWithSubscribers(), connectionOptions.getNetworkCache());
}
public KurentoOptions getKurentoOptions() {
return this.connectionOptions.getKurentoOptions();
}
public String getRtspUri() {
return this.connectionOptions.getRtspUri();
}
public Boolean adaptativeBitrate() {
return this.connectionOptions.adaptativeBitrate();
}
public Boolean onlyPlayWithSubscribers() {
return this.connectionOptions.onlyPlayWithSubscribers();
}
public Integer getNetworkCache() {
return this.connectionOptions.getNetworkCache();
}
public TurnCredentials getTurnCredentials() {
return turnCredentials;
}
public KurentoTokenOptions getKurentoTokenOptions() {
return kurentoTokenOptions;
}
public String getConnectionId() {
return connectionId;
}
public void setRole(OpenViduRole role) {
this.role = role;
}
public void setRecord(boolean record) {
this.record = record;
}
public JsonObject toJson() {
JsonObject json = new JsonObject();
json.addProperty("id", this.getToken());
json.addProperty("object", "token");
json.addProperty("token", this.getToken());
json.addProperty("createdAt", this.getCreatedAt());
json.addProperty("connectionId", this.getConnectionId());
json.addProperty("createdAt", this.createdAt);
json.addProperty("session", this.sessionId);
json.addProperty("role", this.getRole().toString());
json.addProperty("data", this.getServerMetadata());
json.addProperty("record", this.record());
if (this.getKurentoTokenOptions() != null) {
json.add("kurentoOptions", this.getKurentoTokenOptions().toJson());
json.addProperty("role", this.getRole().toString());
if (this.getKurentoOptions() != null) {
json.add("kurentoOptions", this.getKurentoOptions().toJson());
}
return json;
}
@ -118,28 +136,73 @@ public class Token {
JsonObject json = new JsonObject();
json.addProperty("id", this.getConnectionId());
json.addProperty("object", "connection");
json.addProperty("type", ConnectionType.WEBRTC.name());
json.addProperty("status", ParticipantStatus.pending.name());
json.addProperty("connectionId", this.getConnectionId()); // DEPRECATED: better use id
json.addProperty("sessionId", this.sessionId);
json.addProperty("createdAt", this.createdAt);
// Add all ConnectionOptions
JsonObject connectionOptionsJson = this.getConnectionOptionsWithFinalJsonFormat();
connectionOptionsJson.entrySet().forEach(entry -> {
json.add(entry.getKey(), entry.getValue());
});
json.addProperty("token", this.getToken());
json.add("activeAt", null);
json.add("location", null);
json.add("platform", null);
json.addProperty("token", this.getToken());
json.addProperty("role", this.getRole().toString());
json.addProperty("serverData", this.getServerMetadata());
json.addProperty("record", this.record());
json.add("clientData", null);
json.add("publishers", null);
json.add("subscribers", null);
return json;
}
protected JsonObject getConnectionOptionsWithFinalJsonFormat() {
JsonObject json = this.connectionOptions.toJson(this.sessionId);
json.remove("session");
json.addProperty("serverData", json.get("data").getAsString());
json.remove("data");
return json;
}
private void updateConnectionOptions(ConnectionType type, String data, Boolean record, OpenViduRole role,
KurentoOptions kurentoOptions, String rtspUri, Boolean adaptativeBitrate, Boolean onlyPlayWithSubscribers,
Integer networkCache) {
ConnectionOptions.Builder builder = new ConnectionOptions.Builder();
if (type != null) {
builder.type(type);
}
if (data != null) {
builder.data(data);
}
if (record != null) {
builder.record(record);
}
if (role != null) {
builder.role(role);
}
if (kurentoOptions != null) {
builder.kurentoOptions(kurentoOptions);
}
if (rtspUri != null) {
builder.rtspUri(rtspUri);
}
if (adaptativeBitrate != null) {
builder.adaptativeBitrate(adaptativeBitrate);
}
if (onlyPlayWithSubscribers != null) {
builder.onlyPlayWithSubscribers(onlyPlayWithSubscribers);
}
if (networkCache != null) {
builder.networkCache(networkCache);
}
this.connectionOptions = builder.build();
}
@Override
public String toString() {
if (this.role != null)
return this.role.name();
if (this.connectionOptions.getRole() != null)
return this.connectionOptions.getRole().name();
else
return this.token;
}

View File

@ -20,13 +20,15 @@ package io.openvidu.server.core;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.server.OpenViduServer;
import io.openvidu.server.config.OpenviduBuildInfo;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.coturn.CoturnCredentialsService;
import io.openvidu.server.coturn.TurnCredentials;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
public class TokenGenerator {
@ -39,8 +41,8 @@ public class TokenGenerator {
@Autowired
protected OpenviduBuildInfo openviduBuildConfig;
public Token generateToken(String sessionId, OpenViduRole role, String serverMetadata, boolean record,
KurentoTokenOptions kurentoTokenOptions) throws Exception {
public Token generateToken(String sessionId, String serverMetadata, boolean record, OpenViduRole role,
KurentoOptions kurentoOptions) throws Exception {
String token = OpenViduServer.wsUrl;
token += "?sessionId=" + sessionId;
token += "&token=" + IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
@ -56,6 +58,8 @@ public class TokenGenerator {
token += "&turnCredential=" + turnCredentials.getCredential();
}
}
return new Token(token, sessionId, role, serverMetadata, record, turnCredentials, kurentoTokenOptions);
ConnectionOptions connectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC)
.data(serverMetadata).record(record).role(role).kurentoOptions(kurentoOptions).build();
return new Token(token, sessionId, connectionOptions, turnCredentials);
}
}

View File

@ -77,7 +77,7 @@ public class KurentoParticipant extends Participant {
public KurentoParticipant(Participant participant, KurentoSession kurentoSession,
KurentoParticipantEndpointConfig endpointConfig, OpenviduConfig openviduConfig,
RecordingManager recordingManager) {
super(participant.getType(), participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(),
super(participant.getFinalUserId(), participant.getParticipantPrivateId(), participant.getParticipantPublicId(),
kurentoSession.getSessionId(), participant.getToken(), participant.getClientMetadata(),
participant.getLocation(), participant.getPlatform(), participant.getEndpointType(),
participant.getActiveAt());

View File

@ -48,6 +48,8 @@ import com.google.gson.JsonObject;
import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code;
import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.MediaMode;
import io.openvidu.java.client.Recording;
import io.openvidu.java.client.RecordingLayout;
@ -387,7 +389,7 @@ public class KurentoSessionManager extends SessionManager {
* kurentoParticipant.getPublisher().apply(elem); }
*/
KurentoTokenOptions kurentoTokenOptions = participant.getToken().getKurentoTokenOptions();
KurentoOptions kurentoTokenOptions = participant.getToken().getKurentoOptions();
if (kurentoOptions.getFilter() != null && kurentoTokenOptions != null) {
if (kurentoTokenOptions.isFilterAllowed(kurentoOptions.getFilter().getType())) {
this.applyFilterInPublisher(kParticipant, kurentoOptions.getFilter());
@ -990,7 +992,7 @@ public class KurentoSessionManager extends SessionManager {
@Override
/* Protected by Session.closingLock.readLock */
public Participant publishIpcam(Session session, MediaOptions mediaOptions, String serverMetadata)
public Participant publishIpcam(Session session, MediaOptions mediaOptions, ConnectionOptions connectionOptions)
throws Exception {
final String sessionId = session.getSessionId();
final KurentoMediaOptions kMediaOptions = (KurentoMediaOptions) mediaOptions;
@ -1032,7 +1034,8 @@ public class KurentoSessionManager extends SessionManager {
this.newInsecureParticipant(rtspConnectionId);
String token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
+ RandomStringUtils.randomAlphanumeric(15);
this.newTokenForInsecureUser(session, token, serverMetadata);
this.newTokenForInsecureUser(session, token, connectionOptions);
final Token tokenObj = session.consumeToken(token);
Participant ipcamParticipant = this.newIpcamParticipant(sessionId, rtspConnectionId, tokenObj, location,
@ -1109,9 +1112,10 @@ public class KurentoSessionManager extends SessionManager {
Session session = this.getSession(sessionId);
return ((KurentoSession) session).getParticipantPrivateIdFromStreamId(streamId);
}
@Override
public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width, Boolean videoActive, Boolean audioActive) {
public void onVideoData(Participant participant, Integer transactionId, Integer height, Integer width,
Boolean videoActive, Boolean audioActive) {
sessionEventsHandler.onVideoData(participant, transactionId, height, width, videoActive, audioActive);
}

View File

@ -1,107 +0,0 @@
/*
* (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.
*
*/
package io.openvidu.server.kurento.core;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class KurentoTokenOptions {
private Integer videoMaxRecvBandwidth;
private Integer videoMinRecvBandwidth;
private Integer videoMaxSendBandwidth;
private Integer videoMinSendBandwidth;
private Map<String, Boolean> allowedFilters = new ConcurrentHashMap<>();
public KurentoTokenOptions(JsonObject options) {
if (options.has("videoMaxRecvBandwidth")) {
this.videoMaxRecvBandwidth = options.get("videoMaxRecvBandwidth").getAsInt();
}
if (options.has("videoMinRecvBandwidth")) {
this.videoMinRecvBandwidth = options.get("videoMinRecvBandwidth").getAsInt();
}
if (options.has("videoMaxSendBandwidth")) {
this.videoMaxSendBandwidth = options.get("videoMaxSendBandwidth").getAsInt();
}
if (options.has("videoMinSendBandwidth")) {
this.videoMinSendBandwidth = options.get("videoMinSendBandwidth").getAsInt();
}
if (options.has("allowedFilters")) {
JsonArray filters = options.get("allowedFilters").getAsJsonArray();
Iterator<JsonElement> it = filters.iterator();
while (it.hasNext()) {
this.allowedFilters.put(it.next().getAsString(), true);
}
}
}
public Integer getVideoMaxRecvBandwidth() {
return videoMaxRecvBandwidth;
}
public Integer getVideoMinRecvBandwidth() {
return videoMinRecvBandwidth;
}
public Integer getVideoMaxSendBandwidth() {
return videoMaxSendBandwidth;
}
public Integer getVideoMinSendBandwidth() {
return videoMinSendBandwidth;
}
public String[] getAllowedFilters() {
return allowedFilters.keySet().stream().toArray(String[]::new);
}
public boolean isFilterAllowed(String filterType) {
return this.allowedFilters.containsKey(filterType);
}
public JsonObject toJson() {
JsonObject json = new JsonObject();
if (this.getVideoMaxRecvBandwidth() != null) {
json.addProperty("videoMaxRecvBandwidth", this.getVideoMaxRecvBandwidth());
}
if (this.getVideoMinRecvBandwidth() != null) {
json.addProperty("videoMinRecvBandwidth", this.getVideoMinRecvBandwidth());
}
if (this.getVideoMaxSendBandwidth() != null) {
json.addProperty("videoMaxSendBandwidth", this.getVideoMaxSendBandwidth());
}
if (this.getVideoMinSendBandwidth() != null) {
json.addProperty("videoMinSendBandwidth", this.getVideoMinSendBandwidth());
}
if (this.getAllowedFilters().length > 0) {
JsonArray filtersJson = new JsonArray();
String[] filters = this.getAllowedFilters();
for (String filter : filters) {
filtersJson.add(filter);
}
json.add("allowedFilters", filtersJson);
}
return json;
}
}

View File

@ -53,11 +53,11 @@ import com.google.gson.JsonObject;
import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.core.Participant;
import io.openvidu.server.kurento.core.KurentoMediaOptions;
import io.openvidu.server.kurento.core.KurentoParticipant;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
/**
* {@link Endpoint} wrapper. Can be based on WebRtcEndpoint (that supports
@ -128,7 +128,7 @@ public abstract class MediaEndpoint {
this.openviduConfig = openviduConfig;
KurentoTokenOptions kurentoTokenOptions = this.owner.getToken().getKurentoTokenOptions();
KurentoOptions kurentoTokenOptions = this.owner.getToken().getKurentoOptions();
if (kurentoTokenOptions != null) {
this.maxRecvKbps = kurentoTokenOptions.getVideoMaxRecvBandwidth() != null
? kurentoTokenOptions.getVideoMaxRecvBandwidth()

View File

@ -64,7 +64,9 @@ public class RecorderEndpointWrapper {
this.name = StringUtils.removeEnd(nameAux, SingleStreamRecordingService.INDIVIDUAL_RECORDING_EXTENSION);
this.connectionId = json.get("connectionId").getAsString();
this.streamId = json.get("streamId").getAsString();
this.clientData = json.get("clientData").getAsString();
this.clientData = (json.has("clientData") && !json.get("clientData").isJsonNull())
? json.get("clientData").getAsString()
: null;
this.serverData = json.get("serverData").getAsString();
this.startTime = json.get("startTime").getAsLong();
this.endTime = json.get("endTime").getAsLong();

View File

@ -20,7 +20,6 @@ package io.openvidu.server.rest;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@ -45,12 +44,15 @@ import org.springframework.web.bind.annotation.RestController;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.openvidu.client.OpenViduException;
import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.MediaMode;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording.OutputMode;
@ -66,7 +68,6 @@ import io.openvidu.server.core.Session;
import io.openvidu.server.core.SessionManager;
import io.openvidu.server.core.Token;
import io.openvidu.server.kurento.core.KurentoMediaOptions;
import io.openvidu.server.kurento.core.KurentoTokenOptions;
import io.openvidu.server.recording.Recording;
import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.utils.RecordingUtils;
@ -273,45 +274,29 @@ public class SessionRestController {
public ResponseEntity<?> initializeConnection(@PathVariable("sessionId") String sessionId,
@RequestBody Map<?, ?> params) {
log.info("REST API: POST {}/sessions/{}/connection {}", RequestMappings.API, sessionId, params.toString());
log.info("REST API: POST {} {}", RequestMappings.API + "/sessions/" + sessionId + "/connection",
params.toString());
Session session = this.sessionManager.getSessionWithNotActive(sessionId);
if (session == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
String typeString;
String data;
Boolean record;
ConnectionOptions connectionOptions;
try {
typeString = (String) params.get("type");
data = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in parameter \"type\"",
"/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
connectionOptions = getConnectionOptionsFromParams(params);
} catch (Exception e) {
return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection",
HttpStatus.BAD_REQUEST);
}
ConnectionType type;
try {
if (typeString != null) {
type = ConnectionType.valueOf(typeString);
} else {
type = ConnectionType.WEBRTC;
}
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("Parameter type " + params.get("typeString") + " is not defined",
RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
}
switch (type) {
switch (connectionOptions.getType()) {
case WEBRTC:
return this.newWebrtcConnection(session, data, record, params);
return this.newWebrtcConnection(session, connectionOptions);
case IPCAM:
return this.newIpcamConnection(session, data, record, params);
return this.newIpcamConnection(session, connectionOptions);
default:
return this.generateErrorResponse("Wrong type " + typeString,
RequestMappings.API + "/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
return this.generateErrorResponse("Wrong type parameter", "/sessions/" + sessionId + "/connection",
HttpStatus.BAD_REQUEST);
}
}
@ -654,12 +639,8 @@ public class SessionRestController {
log.info("REST API: POST {}/tokens {}", RequestMappings.API, params.toString());
String sessionId;
String metadata;
Boolean record;
try {
sessionId = (String) params.get("session");
metadata = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", "/tokens", HttpStatus.BAD_REQUEST);
}
@ -675,10 +656,15 @@ public class SessionRestController {
if (session == null) {
return this.generateErrorResponse("Session " + sessionId + " not found", "/tokens", HttpStatus.NOT_FOUND);
}
Map<String, Object> map = new HashMap<>();
params.entrySet().forEach(entry -> map.put((String) entry.getKey(), entry.getValue()));
map.put("type", "WEBRTC");
ResponseEntity<?> entity = this.newWebrtcConnection(session, metadata, record, params);
ConnectionOptions connectionOptions;
try {
connectionOptions = getConnectionOptionsFromParams(params);
} catch (Exception e) {
return this.generateErrorResponse(e.getMessage(), "/sessions/" + sessionId + "/connection",
HttpStatus.BAD_REQUEST);
}
ResponseEntity<?> entity = this.newWebrtcConnection(session, connectionOptions);
JsonObject jsonResponse = JsonParser.parseString(entity.getBody().toString()).getAsJsonObject();
if (jsonResponse.has("error")) {
@ -793,57 +779,15 @@ public class SessionRestController {
return new ResponseEntity<>(HttpStatus.OK);
}
protected ResponseEntity<?> newWebrtcConnection(Session session, String serverData, Boolean record,
Map<?, ?> params) {
protected ResponseEntity<?> newWebrtcConnection(Session session, ConnectionOptions connectionOptions) {
final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection";
String roleString = null;
try {
roleString = (String) params.get("role");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
OpenViduRole role = null;
try {
if (roleString != null) {
role = OpenViduRole.valueOf(roleString);
} else {
role = OpenViduRole.PUBLISHER;
}
} catch (IllegalArgumentException e) {
return this.generateErrorResponse("Parameter role " + params.get("role") + " is not defined", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
JsonObject kurentoOptions = null;
if (params.get("kurentoOptions") != null) {
try {
kurentoOptions = JsonParser.parseString(params.get("kurentoOptions").toString()).getAsJsonObject();
} catch (Exception e) {
return this.generateErrorResponse("Error in parameter 'kurentoOptions'. It is not a valid JSON object",
REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
}
KurentoTokenOptions kurentoTokenOptions = null;
if (kurentoOptions != null) {
try {
kurentoTokenOptions = new KurentoTokenOptions(kurentoOptions);
} catch (Exception e) {
return this.generateErrorResponse("Type error in some parameter of 'kurentoOptions'", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
}
serverData = (serverData != null) ? serverData : "";
record = (record != null) ? record : true;
final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection";
// While closing a session tokens can't be generated
if (session.closingLock.readLock().tryLock()) {
try {
Token token = sessionManager.newToken(session, role, serverData, record, kurentoTokenOptions);
Token token = sessionManager.newToken(session, connectionOptions.getRole(), connectionOptions.getData(),
connectionOptions.record(), connectionOptions.getKurentoOptions());
return new ResponseEntity<>(token.toJsonAsParticipant().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (Exception e) {
@ -861,34 +805,9 @@ public class SessionRestController {
}
}
protected ResponseEntity<?> newIpcamConnection(Session session, String serverData, Boolean record,
Map<?, ?> params) {
protected ResponseEntity<?> newIpcamConnection(Session session, ConnectionOptions connectionOptions) {
final String REQUEST_PATH = RequestMappings.API + "/sessions/" + session.getSessionId() + "/connection";
String rtspUri;
Boolean adaptativeBitrate;
Boolean onlyPlayWithSubscribers;
Integer networkCache;
try {
rtspUri = (String) params.get("rtspUri");
adaptativeBitrate = (Boolean) params.get("adaptativeBitrate");
onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers");
networkCache = (Integer) params.get("networkCache");
} catch (ClassCastException e) {
return this.generateErrorResponse("Type error in some parameter", REQUEST_PATH, HttpStatus.BAD_REQUEST);
}
if (rtspUri == null) {
return this.generateErrorResponse("\"rtspUri\" parameter is mandatory", REQUEST_PATH,
HttpStatus.BAD_REQUEST);
}
adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true;
onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true;
networkCache = networkCache != null ? networkCache : 2000;
serverData = serverData != null ? serverData : "";
record = (record != null) ? record : true;
final String REQUEST_PATH = "/sessions/" + session.getSessionId() + "/connection";
boolean hasAudio = true;
boolean hasVideo = true;
@ -898,8 +817,9 @@ public class SessionRestController {
Integer frameRate = null;
String videoDimensions = null;
KurentoMediaOptions mediaOptions = new KurentoMediaOptions(true, null, hasAudio, hasVideo, audioActive,
videoActive, typeOfVideo, frameRate, videoDimensions, null, false, rtspUri, adaptativeBitrate,
onlyPlayWithSubscribers, networkCache);
videoActive, typeOfVideo, frameRate, videoDimensions, null, false, connectionOptions.getRtspUri(),
connectionOptions.adaptativeBitrate(), connectionOptions.onlyPlayWithSubscribers(),
connectionOptions.getNetworkCache());
// While closing a session IP cameras can't be published
if (session.closingLock.readLock().tryLock()) {
@ -907,7 +827,8 @@ public class SessionRestController {
if (session.isClosed()) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, serverData);
Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions,
connectionOptions);
return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (MalformedURLException e) {
@ -936,6 +857,125 @@ public class SessionRestController {
return token;
}
protected ConnectionOptions getConnectionOptionsFromParams(Map<?, ?> params) throws Exception {
ConnectionOptions.Builder builder = new ConnectionOptions.Builder();
String typeString;
String data;
Boolean record;
try {
typeString = (String) params.get("type");
data = (String) params.get("data");
record = (Boolean) params.get("record");
} catch (ClassCastException e) {
throw new Exception("Type error in some parameter: " + e.getMessage());
}
ConnectionType type;
try {
if (typeString != null) {
type = ConnectionType.valueOf(typeString);
} else {
type = ConnectionType.WEBRTC;
}
} catch (IllegalArgumentException e) {
throw new Exception("Parameter 'type' " + typeString + " is not defined");
}
data = data != null ? data : "";
record = record != null ? record : true;
// Build COMMON options
builder.type(type).data(data).record(record);
OpenViduRole role = null;
KurentoOptions kurentoOptions = null;
if (ConnectionType.WEBRTC.equals(type)) {
String roleString;
try {
roleString = (String) params.get("role");
} catch (ClassCastException e) {
throw new Exception("Type error in parameter 'role': " + e.getMessage());
}
try {
if (roleString != null) {
role = OpenViduRole.valueOf(roleString);
} else {
role = OpenViduRole.PUBLISHER;
}
} catch (IllegalArgumentException e) {
throw new Exception("Parameter role " + params.get("role") + " is not defined");
}
JsonObject kurentoOptionsJson = null;
if (params.get("kurentoOptions") != null) {
try {
kurentoOptionsJson = JsonParser.parseString(params.get("kurentoOptions").toString())
.getAsJsonObject();
} catch (Exception e) {
throw new Exception("Error in parameter 'kurentoOptions'. It is not a valid JSON object");
}
}
if (kurentoOptionsJson != null) {
try {
KurentoOptions.Builder builder2 = new KurentoOptions.Builder();
if (kurentoOptionsJson.has("videoMaxRecvBandwidth")) {
builder2.videoMaxRecvBandwidth(kurentoOptionsJson.get("videoMaxRecvBandwidth").getAsInt());
}
if (kurentoOptionsJson.has("videoMinRecvBandwidth")) {
builder2.videoMinRecvBandwidth(kurentoOptionsJson.get("videoMinRecvBandwidth").getAsInt());
}
if (kurentoOptionsJson.has("videoMaxSendBandwidth")) {
builder2.videoMaxSendBandwidth(kurentoOptionsJson.get("videoMaxSendBandwidth").getAsInt());
}
if (kurentoOptionsJson.has("videoMinSendBandwidth")) {
builder2.videoMinSendBandwidth(kurentoOptionsJson.get("videoMinSendBandwidth").getAsInt());
}
if (kurentoOptionsJson.has("allowedFilters")) {
JsonArray filters = kurentoOptionsJson.get("allowedFilters").getAsJsonArray();
String[] arrayOfFilters = new String[filters.size()];
Iterator<JsonElement> it = filters.iterator();
int index = 0;
while (it.hasNext()) {
arrayOfFilters[index] = it.next().getAsString();
index++;
}
builder2.allowedFilters(arrayOfFilters);
}
kurentoOptions = builder2.build();
} catch (Exception e) {
throw new Exception("Type error in some parameter of 'kurentoOptions': " + e.getMessage());
}
}
// Build WEBRTC options
builder.role(role).kurentoOptions(kurentoOptions);
} else if (ConnectionType.IPCAM.equals(type)) {
String rtspUri;
Boolean adaptativeBitrate;
Boolean onlyPlayWithSubscribers;
Integer networkCache;
try {
rtspUri = (String) params.get("rtspUri");
adaptativeBitrate = (Boolean) params.get("adaptativeBitrate");
onlyPlayWithSubscribers = (Boolean) params.get("onlyPlayWithSubscribers");
networkCache = (Integer) params.get("networkCache");
} catch (ClassCastException e) {
throw new Exception("Type error in some parameter: " + e.getMessage());
}
adaptativeBitrate = adaptativeBitrate != null ? adaptativeBitrate : true;
onlyPlayWithSubscribers = onlyPlayWithSubscribers != null ? onlyPlayWithSubscribers : true;
networkCache = networkCache != null ? networkCache : 2000;
// Build IPCAM options
builder.rtspUri(rtspUri).adaptativeBitrate(adaptativeBitrate)
.onlyPlayWithSubscribers(onlyPlayWithSubscribers).networkCache(networkCache).build();
}
return builder.build();
}
protected ResponseEntity<String> generateErrorResponse(String errorMessage, String path, HttpStatus status) {
JsonObject responseJson = new JsonObject();
responseJson.addProperty("timestamp", System.currentTimeMillis());

View File

@ -45,6 +45,7 @@ import com.google.gson.JsonSyntaxException;
import io.openvidu.client.OpenViduException;
import io.openvidu.client.OpenViduException.Code;
import io.openvidu.client.internal.ProtocolElements;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.core.EndReason;
import io.openvidu.server.core.IdentifierPrefixes;
@ -248,7 +249,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
token = IdentifierPrefixes.TOKEN_ID + RandomStringUtils.randomAlphabetic(1).toUpperCase()
+ RandomStringUtils.randomAlphanumeric(15);
try {
sessionManager.newTokenForInsecureUser(session, token, null);
sessionManager.newTokenForInsecureUser(session, token, new ConnectionOptions.Builder().build());
} catch (Exception e) {
throw new OpenViduException(Code.TOKEN_CANNOT_BE_CREATED_ERROR_CODE,
"Unable to create token for session " + sessionId + ": " + e.getMessage());
@ -492,7 +493,7 @@ public class RpcHandler extends DefaultJsonRpcHandler<JsonObject> {
// user's stream) or if the user is the owner of the stream and has a token
// configured with this specific filter
if (isModerator || (this.userIsStreamOwner(rpcConnection.getSessionId(), participant, streamId)
&& participant.getToken().getKurentoTokenOptions().isFilterAllowed(filterType))) {
&& participant.getToken().getKurentoOptions().isFilterAllowed(filterType))) {
JsonObject filterOptions;
try {
filterOptions = JsonParser.parseString(getStringParam(request, ProtocolElements.FILTER_OPTIONS_PARAM))

View File

@ -36,7 +36,7 @@ import org.springframework.test.context.web.WebAppConfiguration;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.server.core.Participant;
import io.openvidu.server.core.SessionManager;
import io.openvidu.server.core.Token;
@ -115,7 +115,8 @@ public class SessionGarbageCollectorIntegrationTest {
}
private void joinParticipant(String sessionId, String token) {
Token t = new Token(token, sessionId, OpenViduRole.PUBLISHER, "SERVER_METADATA", true, null, null);
ConnectionOptions connectionOptions = new ConnectionOptions.Builder().data("SERVER_METADATA").build();
Token t = new Token(token, sessionId, connectionOptions, null);
String uuid = UUID.randomUUID().toString();
String participantPrivateId = "PARTICIPANT_PRIVATE_ID_" + uuid;
String finalUserId = "FINAL_USER_ID_" + uuid;

View File

@ -110,7 +110,7 @@ public class CustomHttpClient {
public JsonObject rest(HttpMethod method, String path, String body, int status, boolean matchKeys,
boolean matchValues, boolean matchArrays, String jsonReturnedValue) throws Exception {
JsonObject jsonExpected = null;
jsonReturnedValue.replaceAll("'", "\"");
jsonReturnedValue = jsonReturnedValue.replaceAll("'", "\"");
try {
jsonExpected = JsonParser.parseString(jsonReturnedValue).getAsJsonObject();
} catch (JsonSyntaxException e1) {
@ -171,7 +171,8 @@ public class CustomHttpClient {
public static void checkSameType(JsonElement expected, JsonElement actual, String key, boolean checkAlsoSameValue)
throws Exception {
if (!expected.getClass().equals(actual.getClass())) {
throw new Exception("Expected JSON element has not the same class as the actual JSON element. Expected: "
throw new Exception("Expected JSON element \"" + key
+ "\" has not the same class as the actual JSON element. Expected: "
+ expected.getClass().getSimpleName() + ". Actual: " + actual.getClass().getSimpleName());
}
if (expected.isJsonNull()) {

View File

@ -45,6 +45,7 @@ import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import io.github.bonigarcia.wdm.WebDriverManager;
@ -63,6 +64,12 @@ import io.openvidu.test.browsers.utils.Unzipper;
public class AbstractOpenViduTestAppE2eTest {
final protected String DEFAULT_JSON_SESSION = "{'id':'STR','object':'session','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}";
final protected String DEFAULT_JSON_PENDING_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'pending','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':null,'location':null,'platform':null,'token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':null,'publishers':null,'subscribers':null}";
final protected String DEFAULT_JSON_ACTIVE_CONNECTION = "{'id':'STR','object':'connection','type':'WEBRTC','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','token':'STR','serverData':'STR','record':true,'role':'STR','kurentoOptions':null,'rtspUri':null,'adaptativeBitrate':null,'onlyPlayWithSubscribers':null,'networkCache':null,'clientData':'STR','publishers':[],'subscribers':[]}";
final protected String DEFAULT_JSON_IPCAM_CONNECTION = "{'id':'STR','object':'connection','type':'IPCAM','status':'active','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'IPCAM','token':null,'serverData':'STR','record':true,'role':null,'kurentoOptions':null,'rtspUri':'STR','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':2000,'clientData':null,'publishers':[],'subscribers':[]}";
final protected String DEFAULT_JSON_TOKEN = "{'id':'STR','token':'STR','connectionId':'STR','createdAt':0,'session':'STR','role':'STR','data':'STR','kurentoOptions':{}}";
protected static String OPENVIDU_SECRET = "MY_SECRET";
protected static String OPENVIDU_URL = "https://localhost:4443/";
protected static String APP_URL = "http://localhost:4200/";
@ -546,4 +553,17 @@ public class AbstractOpenViduTestAppE2eTest {
+ " | awk '{print $1 }' | xargs -I {} docker rm -f {}");
}
protected String mergeJson(String json, String newProperties, String[] removeProperties) {
JsonObject jsonObj = JsonParser.parseString(json.replaceAll("'", "\"")).getAsJsonObject();
JsonObject newJsonObj = JsonParser.parseString(newProperties.replaceAll("'", "\"")).getAsJsonObject();
newJsonObj.entrySet().forEach(entry -> {
jsonObj.remove(entry.getKey());
jsonObj.add(entry.getKey(), entry.getValue());
});
for (String prop : removeProperties) {
jsonObj.remove(prop);
}
return jsonObj.toString().replaceAll("\"", "'");
}
}

View File

@ -31,7 +31,6 @@ import io.openvidu.java.client.OpenViduHttpException;
import io.openvidu.java.client.OpenViduRole;
import io.openvidu.java.client.Recording;
import io.openvidu.java.client.Session;
import io.openvidu.java.client.Token;
import io.openvidu.test.browsers.utils.CustomHttpClient;
import io.openvidu.test.browsers.utils.Unzipper;
@ -212,19 +211,19 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Updating only role should let record value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'MODERATOR'}", HttpStatus.SC_OK, true, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':"
+ createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}");
mergeJson(DEFAULT_JSON_PENDING_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'MODERATOR','serverData':'','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}",
new String[0]));
// Updating only record should let role value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'record':true}", HttpStatus.SC_OK, true, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'pending','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':null,'subscribers':null,'createdAt':"
+ createdAt + ",'activeAt':null,'platform':null,'location':null,'clientData':null}");
mergeJson(DEFAULT_JSON_PENDING_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'MODERATOR','serverData':'','token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + "}",
new String[0]));
// Test with openvidu-java-client
OpenVidu OV = new OpenVidu(OpenViduTestAppE2eTest.OPENVIDU_URL, OpenViduTestAppE2eTest.OPENVIDU_SECRET);
@ -275,6 +274,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertTrue("Session object should have changed", session.fetch());
connection = session.getActiveConnections().get(0);
final Long activeAt = connection.activeAt();
Assert.assertTrue("activeAt should be greater than createdAt in Connection object", activeAt > createdAt);
Assert.assertEquals("Wrong role in Connection object", OpenViduRole.SUBSCRIBER, connection.getRole());
Assert.assertFalse("Wrong record in Connection object", connection.record());
@ -284,29 +285,37 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Updating only role should let record value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'MODERATOR'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'MODERATOR','record':false,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':"
+ activeAt + ",'serverData':''}",
new String[] { "location", "platform", "clientData" }));
// Updating only record should let role value untouched
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'record':true}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'MODERATOR','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'MODERATOR','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':"
+ activeAt + ",'serverData':''}",
new String[] { "location", "platform", "clientData" }));
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'SUBSCRIBER','record':true,'data':'OTHER DATA'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'SUBSCRIBER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'SUBSCRIBER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':"
+ activeAt + ",'serverData':''}",
new String[] { "location", "platform", "clientData" }));
restClient.rest(HttpMethod.PATCH, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenConnectionId,
"{'role':'PUBLISHER'}", HttpStatus.SC_OK, false, true, true,
"{'id':'" + tokenConnectionId
+ "','object':'connection','type':'WEBRTC','status':'active','connectionId':'"
+ tokenConnectionId + "','role':'PUBLISHER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','serverData':'','publishers':[],'subscribers':[]}");
mergeJson(DEFAULT_JSON_ACTIVE_CONNECTION,
"{'id':'" + tokenConnectionId + "','connectionId':'" + tokenConnectionId
+ "','role':'PUBLISHER','record':true,'token':'" + token
+ "','sessionId':'CUSTOM_SESSION_ID','createdAt':" + createdAt + ",'activeAt':"
+ activeAt + ",'serverData':''}",
new String[] { "location", "platform", "clientData" }));
// Test with openvidu-node-client
user.getDriver().findElement(By.id("session-api-btn-0")).click();
@ -341,7 +350,7 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertFalse("Session object should not have changed", session.fetch());
Assert.assertEquals("Wrong connectionId in Connection object", tokenConnectionId, connection.getConnectionId());
Assert.assertEquals("Wrong role in Connection object", OpenViduRole.PUBLISHER, connection.getRole());
Assert.assertTrue("Wrong record in Connection object", connection.record());
Assert.assertFalse("Wrong record in Connection object", connection.record());
Assert.assertEquals("Wrong status in Connection object", "active", connection.getStatus());
connection = session.updateConnection(tokenConnectionId,
new ConnectionOptions.Builder().role(OpenViduRole.SUBSCRIBER).build());
@ -397,9 +406,8 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
void openViduJavaClientProTest() throws Exception {
Session session = OV.createSession();
Assert.assertFalse(session.fetch());
Token token = session.createToken();
Assert.assertTrue(session.fetch());
Connection connection = session.getConnection(token.getConnectionId());
Connection connection = session.createConnection();
Assert.assertFalse(session.fetch());
Assert.assertEquals("Wrong role property", OpenViduRole.PUBLISHER, connection.getRole());
Assert.assertTrue("Wrong record property", connection.record());
session.updateConnection(connection.getConnectionId(),

View File

@ -48,11 +48,14 @@ import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mashape.unirest.http.HttpMethod;
import io.openvidu.java.client.Connection;
import io.openvidu.java.client.ConnectionOptions;
import io.openvidu.java.client.ConnectionType;
import io.openvidu.java.client.KurentoOptions;
import io.openvidu.java.client.MediaMode;
import io.openvidu.java.client.OpenVidu;
@ -66,8 +69,6 @@ import io.openvidu.java.client.RecordingMode;
import io.openvidu.java.client.RecordingProperties;
import io.openvidu.java.client.Session;
import io.openvidu.java.client.SessionProperties;
import io.openvidu.java.client.Token;
import io.openvidu.java.client.TokenOptions;
import io.openvidu.test.browsers.FirefoxUser;
import io.openvidu.test.browsers.utils.CustomHttpClient;
import io.openvidu.test.browsers.utils.layout.CustomLayoutHandler;
@ -84,10 +85,6 @@ import io.openvidu.test.browsers.utils.webhook.CustomWebhook;
@ExtendWith(SpringExtension.class)
public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
final String DEFAULT_JSON_SESSION = "{'id':'STR','object':'STR','sessionId':'STR','createdAt':0,'mediaMode':'STR','recordingMode':'STR','defaultOutputMode':'STR','defaultRecordingLayout':'STR','customSessionId':'STR','connections':{'numberOfElements':0,'content':[]},'recording':false}";
final String DEFAULT_JSON_TOKEN = "{'id':'STR','object':'STR','token':'STR','connectionId':0,'session':'STR','createdAt':0,'role':'STR','data':'STR','record':true}";
final String DEFAULT_JSON_CONNECTION = "{'id':'STR','object':'STR','type':'STR','status':'STR','connectionId':'STR','sessionId':'STR','createdAt':0,'activeAt':0,'location':'STR','platform':'STR','role':'STR','record':true,'serverData':'STR','clientData':'STR','publishers':[],'subscribers':[]}";
@BeforeAll()
protected static void setupAll() {
checkFfmpegInstallation();
@ -2141,27 +2138,19 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
KurentoOptions kurentoOptions = new KurentoOptions.Builder().videoMaxRecvBandwidth(250)
.allowedFilters(new String[] { "GStreamerFilter" }).build();
TokenOptions tokenOptionsModerator = new TokenOptions.Builder().role(OpenViduRole.MODERATOR)
ConnectionOptions moderatorConnectionOptions = new ConnectionOptions.Builder().role(OpenViduRole.MODERATOR)
.data(serverDataModerator).kurentoOptions(kurentoOptions).build();
Token tokenModerator = session.createToken(tokenOptionsModerator);
String tokenModeratorString = tokenModerator.getToken();
String connectionIdModerator = tokenModerator.getConnectionId();
Connection connectionModerator = session.createConnection(moderatorConnectionOptions);
TokenOptions tokenOptionsSubscriber = new TokenOptions.Builder().role(OpenViduRole.SUBSCRIBER)
.data(serverDataSubscriber).build();
Token tokenSubscriber = session.createToken(tokenOptionsSubscriber);
String tokenSubscriberString = tokenSubscriber.getToken();
String connectionIdSubscriber = tokenSubscriber.getConnectionId();
ConnectionOptions subscriberConnectionOptions = new ConnectionOptions.Builder().type(ConnectionType.WEBRTC)
.role(OpenViduRole.SUBSCRIBER).data(serverDataSubscriber).build();
Connection connectionSubscriber = session.createConnection(subscriberConnectionOptions);
Assert.assertTrue("Session.fetch() should return true if new pending connections", session.fetch());
Assert.assertFalse("Session.fetch() should return false after Session.createConnection", session.fetch());
Assert.assertFalse("OpenVidu.fetch() should return false after Session.fetch()", OV.fetch());
Assert.assertEquals("Wrong number of active connections", 0, session.getActiveConnections().size());
Assert.assertEquals("Wrong number of connections", 2, session.getConnections().size());
Connection connectionModerator = session.getConnection(connectionIdModerator);
Connection connectionSubscriber = session.getConnection(connectionIdSubscriber);
Assert.assertEquals("Wrong connectionId property", connectionIdModerator,
connectionModerator.getConnectionId());
Assert.assertEquals("Wrong status property", "pending", connectionModerator.getStatus());
Assert.assertEquals("Wrong role property", OpenViduRole.MODERATOR, connectionModerator.getRole());
Assert.assertTrue("Wrong record property", connectionModerator.record());
@ -2183,7 +2172,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000);
WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(tokenModeratorString);
tokeInput.sendKeys(connectionModerator.getToken());
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
@ -2198,7 +2187,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000);
tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(tokenSubscriberString);
tokeInput.sendKeys(connectionSubscriber.getToken());
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
@ -2514,8 +2503,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
}
pub = connectionModerator.getPublishers().get(0);
// TODO: test delete unused Token, update unused Token and update ongoing
// Connection
// TODO: test delete unused Connection
session.forceUnpublish(pub);
user.getEventManager().waitUntilEventReaches("streamDestroyed", 6);
@ -2528,6 +2516,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertEquals("Wrong number of Subscribers", 0, con.getSubscribers().size());
});
// Delete active Connection
session.forceDisconnect(connectionModerator);
user.getEventManager().waitUntilEventReaches("sessionDisconnected", 1);
user.getEventManager().waitUntilEventReaches("connectionDestroyed", 1);
@ -2541,6 +2530,33 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertFalse("Session.fetch() should return true", OV.fetch());
// Delete pending Connection
session = OV.createSession();
Connection con = session.createConnection();
Assert.assertEquals("Wrong number of Connections", 1, session.getConnections().size());
Assert.assertEquals("Wrong number of active Connections", 0, session.getActiveConnections().size());
Assert.assertFalse(session.fetch());
session.forceDisconnect(con);
Assert.assertEquals("Wrong number of Connections", 0, session.getConnections().size());
Assert.assertEquals("Wrong number of active Connections", 0, session.getActiveConnections().size());
Assert.assertFalse(session.fetch());
// Test IPCAM
final String rtsp = "rtsp://dummyurl.com";
Connection ipcamera = session.createConnection(new ConnectionOptions.Builder().type(ConnectionType.IPCAM)
.rtspUri(rtsp).adaptativeBitrate(false).onlyPlayWithSubscribers(false).networkCache(50).build());
Assert.assertFalse("OpenVidu.fetch() should return false", OV.fetch());
Assert.assertFalse("Session.fetch() should return false", session.fetch());
Assert.assertEquals("Wrong number of active connections", 1, session.getActiveConnections().size());
Assert.assertEquals("Wrong number of connections", 1, session.getConnections().size());
ipcamera = session.getConnection(ipcamera.getConnectionId());
Assert.assertEquals("Wrong type property of Connection object", "IPCAM", ipcamera.getType().name());
Assert.assertNull("Property role of an IPCAM connection should be null", ipcamera.getRole());
Assert.assertEquals("Wrong property rtspUri", rtsp, ipcamera.getRtspUri());
Assert.assertFalse("Wrong property adaptativeBitrate", ipcamera.adaptativeBitrate());
Assert.assertFalse("Wrong property onlyPlayWithSubscribers", ipcamera.onlyPlayWithSubscribers());
Assert.assertEquals("Wrong property networkCache", 50, ipcamera.getNetworkCache());
gracefullyLeaveParticipants(2);
}
@ -2626,31 +2642,61 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// 200
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'MODERATOR', 'data': 'SERVER_DATA', 'kurentoOptions': {'videoMaxSendBandwidth':777,'allowedFilters': ['GStreamerFilter']}}";
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
"{'id':'STR','object':'STR','connectionId':'STR','session':'STR','createdAt':0,'role':'STR','data':'STR','record':true,'token':'STR','kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}");
mergeJson(DEFAULT_JSON_TOKEN,
"{'kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['STR']}}", new String[0]));
final String token1 = res.get("token").getAsString();
final String connectionId1 = res.get("connectionId").getAsString();
final long createdAt1 = res.get("createdAt").getAsLong();
Assert.assertEquals("JSON return value from /openvidu/api/tokens should have equal srtings in 'id' and 'token'",
res.get("id").getAsString(), token1);
Assert.assertEquals("Wrong session parameter", "CUSTOM_SESSION_ID", res.get("session").getAsString());
res = restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null,
HttpStatus.SC_OK, true, true, false, "{'numberOfElements':1,'content':[]}");
JsonObject connection1 = res.getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject();
final String connectionId1 = connection1.get("id").getAsString();
final long createdAt1 = connection1.get("createdAt").getAsLong();
/** POST /openvidu/api/sessions/CUSTOM_SESSION_ID/connection **/
// 400
body = "{'type':false}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_BAD_REQUEST);
body = "{'type':'NOT_EXISTS'}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_BAD_REQUEST);
body = "{'type':'WEBRTC','role':123}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_BAD_REQUEST);
body = "{'type':'WEBRTC','role':123}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_BAD_REQUEST);
body = "{'type':'WEBRTC','role':'MODERATOR','data':true}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_BAD_REQUEST);
// 200
String kurentoOpts = "'kurentoOptions':{'videoMaxSendBandwidth':777,'allowedFilters':['GStreamerFilter']}";
body = "{'type':'WEBRTC','role':'MODERATOR','data':'SERVER_DATA'," + kurentoOpts + "}";
res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_OK, true, false, true,
mergeJson(DEFAULT_JSON_PENDING_CONNECTION, "{" + kurentoOpts + "}", new String[0]));
restClient.rest(HttpMethod.DELETE,
"/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + res.get("id").getAsString(),
HttpStatus.SC_NO_CONTENT);
// Default values
body = "{'session': 'CUSTOM_SESSION_ID'}";
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
DEFAULT_JSON_TOKEN);
final String token2 = res.get("id").getAsString();
final String connectionId2 = res.get("connectionId").getAsString();
res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", "{}",
HttpStatus.SC_OK);
final String token2 = res.get("token").getAsString();
final String connectionId2 = res.get("id").getAsString();
/** GET /openvidu/api/sessions/ID/connection (with pending connections) **/
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", null, HttpStatus.SC_OK,
true, true, false, "{'numberOfElements':2,'content':[]}");
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionId1, null,
HttpStatus.SC_OK, true, true, true,
"{'id':'" + connectionId1 + "','connectionId':'" + connectionId1
+ "','object':'connection','type':'WEBRTC','status':'pending','sessionId':'CUSTOM_SESSION_ID','token':'"
+ token1 + "','role':'MODERATOR','serverData':'SERVER_DATA','record':true,'createdAt':"
+ createdAt1
+ ",'activeAt':null,'platform':null,'location':null,'clientData':null,'publishers':null,'subscribers':null}");
mergeJson(DEFAULT_JSON_PENDING_CONNECTION,
"{'id':'" + connectionId1 + "','connectionId':'" + connectionId1
+ "','sessionId':'CUSTOM_SESSION_ID','token':'" + token1
+ "','serverData':'SERVER_DATA','role':'MODERATOR'," + kurentoOpts + ",'createdAt':"
+ createdAt1 + "}",
new String[0]));
/** POST /openvidu/api/signal (NOT ACTIVE SESSION) **/
body = "{}";
@ -2864,14 +2910,14 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
**/
body = "{'customSessionId': 'CUSTOM_SESSION_ID'}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions", body, HttpStatus.SC_OK);
body = "{'session': 'CUSTOM_SESSION_ID', 'role': 'SUBSCRIBER'}";
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
DEFAULT_JSON_TOKEN);
final String tokenAConnectionId = res.get("connectionId").getAsString();
body = "{'type': 'WEBRTC', 'role': 'SUBSCRIBER'}";
res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_PENDING_CONNECTION);
final String connectionIdA = res.get("id").getAsString();
final String tokenA = res.get("token").getAsString();
res = restClient.rest(HttpMethod.POST, "/openvidu/api/tokens", body, HttpStatus.SC_OK, true, false, true,
DEFAULT_JSON_TOKEN);
final String tokenBConnectionId = res.get("connectionId").getAsString();
res = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection", body,
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_PENDING_CONNECTION);
final String connectionIdB = res.get("connectionId").getAsString();
final String tokenB = res.get("token").getAsString();
user.getDriver().findElement(By.id("one2one-btn")).click();
@ -2895,7 +2941,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000);
// Invalidate token
restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + tokenAConnectionId,
restClient.rest(HttpMethod.DELETE, "/openvidu/api/sessions/CUSTOM_SESSION_ID/connection/" + connectionIdA,
HttpStatus.SC_NO_CONTENT);
// User should pop up invalid token
@ -2918,7 +2964,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
// connectionId should be equal to the one brought by the token
Assert.assertEquals("Wrong connectionId", tokenBConnectionId,
Assert.assertEquals("Wrong connectionId", connectionIdB,
restClient.rest(HttpMethod.GET, "/openvidu/api/sessions/CUSTOM_SESSION_ID", HttpStatus.SC_OK)
.get("connections").getAsJsonObject().get("content").getAsJsonArray().get(0).getAsJsonObject()
.get("connectionId").getAsString());
@ -3286,7 +3332,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Publish IP camera. Dummy URL because no user will subscribe to it [200]
String ipCamBody = "{'type':'IPCAM','rtspUri':'rtsp://dummyurl.com','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}";
JsonObject response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/IP_CAM_SESSION/connection",
ipCamBody, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION);
ipCamBody, HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION);
CustomWebhook.waitForEvent("sessionCreated", 1);
CustomWebhook.waitForEvent("participantJoined", 1);
@ -3294,7 +3340,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Assert.assertEquals("Wrong serverData property", "MY_IP_CAMERA", response.get("serverData").getAsString());
Assert.assertEquals("Wrong platform property", "IPCAM", response.get("platform").getAsString());
Assert.assertEquals("Wrong role property", "PUBLISHER", response.get("role").getAsString());
Assert.assertEquals("Wrong role property", JsonNull.INSTANCE, response.get("role"));
Assert.assertEquals("Wrong type property", "IPCAM", response.get("type").getAsString());
Assert.assertEquals("Wrong number of publishers in IPCAM participant", 1,
@ -3384,7 +3430,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
+ "','adaptativeBitrate':true,'onlyPlayWithSubscribers':true,'networkCache':1000,'data':'MY_IP_CAMERA'}";
restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody,
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION);
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION);
user.getEventManager().waitUntilEventReaches("connectionCreated", 2);
user.getEventManager().waitUntilEventReaches("streamCreated", 2);
@ -3411,7 +3457,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
// Publish again the IPCAM
response = restClient.rest(HttpMethod.POST, "/openvidu/api/sessions/TestSession/connection", ipCamBody,
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_CONNECTION);
HttpStatus.SC_OK, true, false, true, DEFAULT_JSON_IPCAM_CONNECTION);
user.getEventManager().waitUntilEventReaches("connectionCreated", 3);
user.getEventManager().waitUntilEventReaches("streamCreated", 3);
user.getEventManager().waitUntilEventReaches("streamPlaying", 3);
@ -3523,9 +3569,8 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
Token token = session.createToken();
// TODO: when using createConnection this below should be false!
Assert.assertTrue("Java fetch should be true", session.fetch());
Connection connection = session.createConnection();
Assert.assertFalse("Java fetch should be false", session.fetch());
Assert.assertFalse("Java fetch should be false", OV.fetch());
checkNodeFetchChanged(true, true);
checkNodeFetchChanged(true, false);
@ -3550,7 +3595,7 @@ public class OpenViduTestAppE2eTest extends AbstractOpenViduTestAppE2eTest {
Thread.sleep(1000);
WebElement tokeInput = user.getDriver().findElement(By.cssSelector("#custom-token-div input"));
tokeInput.clear();
tokeInput.sendKeys(token.getToken());
tokeInput.sendKeys(connection.getToken());
user.getDriver().findElement(By.id("save-btn")).click();
Thread.sleep(1000);
user.getDriver().findElement(By.className("join-btn")).click();