diff --git a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
index 85a327d5..9574b48c 100644
--- a/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
+++ b/openvidu-client/src/main/java/io/openvidu/client/internal/ProtocolElements.java
@@ -165,6 +165,7 @@ public class ProtocolElements {
public static final String PARTICIPANTJOINED_ROLE_PARAM = "role";
public static final String PARTICIPANTJOINED_COTURNIP_PARAM = "coturnIp";
public static final String PARTICIPANTJOINED_COTURNPORT_PARAM = "coturnPort";
+ public static final String PARTICIPANTJOINED_CUSTOM_ICE_SERVERS = "customIceServers";
public static final String PARTICIPANTJOINED_TURNUSERNAME_PARAM = "turnUsername";
public static final String PARTICIPANTJOINED_TURNCREDENTIAL_PARAM = "turnCredential";
diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java
index 3e7ba5dd..a833f3b9 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/Connection.java
@@ -192,6 +192,19 @@ public class Connection {
return this.connectionProperties.getNetworkCache();
}
+ /**
+ * Returns a list of custom ICE Servers configured for this connection.
+ *
+ * See {@link io.openvidu.java.client.ConnectionProperties.Builder#addCustomIceServer(IceServerProperties)} for more
+ * information.
+ *
+ * Only for
+ * {@link io.openvidu.java.client.ConnectionType#WEBRTC}
+ */
+ public List getCustomIceServers() {
+ return this.connectionProperties.getCustomIceServers();
+ }
+
/**
* Returns the token string associated to the Connection. This is the value that
* must be sent to the client-side to be consumed in OpenVidu Browser method
diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java
index a14e1607..a9125dec 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/ConnectionProperties.java
@@ -243,7 +243,7 @@ public class ConnectionProperties {
* The level of precedence for ICE Server configuration on every OpenVidu connection is:
*
* - Configured ICE Server using Openvidu.setAdvancedCofiguration() at openvidu-browser.
- * - Configured ICE server at
+ *
- Configured ICE server at
* {@link io.openvidu.java.client.ConnectionProperties#customIceServers ConnectionProperties.customIceServers}
* - Configured ICE Server at global configuration parameter: OPENVIDU_WEBRTC_ICE_SERVERS
* - Default deployed Coturn within OpenVidu deployment
diff --git a/openvidu-java-client/src/main/java/io/openvidu/java/client/IceServerProperties.java b/openvidu-java-client/src/main/java/io/openvidu/java/client/IceServerProperties.java
index a478a1fa..c9f72876 100644
--- a/openvidu-java-client/src/main/java/io/openvidu/java/client/IceServerProperties.java
+++ b/openvidu-java-client/src/main/java/io/openvidu/java/client/IceServerProperties.java
@@ -1,3 +1,20 @@
+/*
+ * (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.java.client;
import com.google.gson.JsonObject;
diff --git a/openvidu-node-client/src/Connection.ts b/openvidu-node-client/src/Connection.ts
index 35d8ba81..a54c36c0 100644
--- a/openvidu-node-client/src/Connection.ts
+++ b/openvidu-node-client/src/Connection.ts
@@ -18,6 +18,7 @@
import { Publisher } from './Publisher';
import { ConnectionProperties } from './ConnectionProperties';
import { OpenViduRole } from './OpenViduRole';
+import { IceServerProperties } from './IceServerProperties';
/**
* See [[Session.connections]]
@@ -138,6 +139,7 @@ export class Connection {
this.connectionProperties.adaptativeBitrate = json.adaptativeBitrate;
this.connectionProperties.onlyPlayWithSubscribers = json.onlyPlayWithSubscribers;
this.connectionProperties.networkCache = json.networkCache;
+ this.connectionProperties.customIceServers = json.customIceServers ?? []
} else {
this.connectionProperties = {
type: json.type,
@@ -148,7 +150,8 @@ export class Connection {
rtspUri: json.rtspUri,
adaptativeBitrate: json.adaptativeBitrate,
onlyPlayWithSubscribers: json.onlyPlayWithSubscribers,
- networkCache: json.networkCache
+ networkCache: json.networkCache,
+ customIceServers: json.customIceServers ?? []
}
}
this.role = json.role;
@@ -224,6 +227,7 @@ export class Connection {
this.connectionProperties.adaptativeBitrate === other.connectionProperties.adaptativeBitrate &&
this.connectionProperties.onlyPlayWithSubscribers === other.connectionProperties.onlyPlayWithSubscribers &&
this.connectionProperties.networkCache === other.connectionProperties.networkCache &&
+ this.connectionProperties.customIceServers.length === other.connectionProperties.customIceServers.length &&
this.token === other.token &&
this.location === other.location &&
this.ip === other.ip &&
@@ -238,6 +242,14 @@ export class Connection {
equals = (this.connectionProperties.kurentoOptions === other.connectionProperties.kurentoOptions);
}
}
+ if (equals) {
+ if (this.connectionProperties.customIceServers != null) {
+ const simpleIceComparator = (a: IceServerProperties, b: IceServerProperties) => (a.url > b.url) ? 1 : -1
+ const sortedIceServers = this.connectionProperties.customIceServers.sort(simpleIceComparator);
+ const sortedOtherIceServers = other.connectionProperties.customIceServers.sort(simpleIceComparator);
+ equals = JSON.stringify(sortedIceServers) === JSON.stringify(sortedOtherIceServers);
+ }
+ }
if (equals) {
equals = JSON.stringify(this.subscribers.sort()) === JSON.stringify(other.subscribers.sort());
if (equals) {
diff --git a/openvidu-node-client/src/ConnectionProperties.ts b/openvidu-node-client/src/ConnectionProperties.ts
index ca88e962..77321c19 100644
--- a/openvidu-node-client/src/ConnectionProperties.ts
+++ b/openvidu-node-client/src/ConnectionProperties.ts
@@ -15,6 +15,7 @@
*
*/
+import { IceServerProperties } from './IceServerProperties';
import { ConnectionType } from './ConnectionType';
import { OpenViduRole } from './OpenViduRole';
@@ -127,4 +128,30 @@ export interface ConnectionProperties {
*/
networkCache?: number;
+ /**
+ * On certain type of networks, clients using default OpenVidu STUN/TURN server can not be reached it because
+ * firewall rules and network topologies at the client side. This method allows you to configure your
+ * own ICE Server for specific connections if you need it. This is usually not necessary, only it is usefull for
+ * OpenVidu users behind firewalls which allows traffic from/to specific ports which may need a custom
+ * ICE Server configuration
+ *
+ * Add an ICE Server if in your use case you need this connection to use your own ICE Server deployment.
+ * When the user uses this connection, it will use the specified ICE Servers defined here.
+ *
+ * The level of precedence for ICE Server configuration on every OpenVidu connection is:
+ *
+ * 1. Configured ICE Server using Openvidu.setAdvancedCofiguration() at openvidu-browser.
+ * 2. Configured ICE server at [[ConnectionProperties.customIceServers]].
+ * 3. Configured ICE Server at global configuration parameter: `OPENVIDU_WEBRTC_ICE_SERVERS`.
+ * 4. Default deployed Coturn within OpenVidu deployment.
+ *
+ *
+ * If no value is found at level 1, level 2 will be used, and so on until level 4.
+ *
+ * This method is equivalent to level 2 of precedence.
+ *
+ * **Only for [[ConnectionType.WEBRTC]]**
+ *
+ */
+ customIceServers?: IceServerProperties[];
}
\ No newline at end of file
diff --git a/openvidu-node-client/src/IceServerProperties.ts b/openvidu-node-client/src/IceServerProperties.ts
new file mode 100644
index 00000000..3484ea04
--- /dev/null
+++ b/openvidu-node-client/src/IceServerProperties.ts
@@ -0,0 +1,42 @@
+/*
+ * (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.
+ *
+ */
+
+export interface IceServerProperties {
+
+ /**
+ * Set the url for the ICE Server you want to use.
+ * It should follow a valid format:
+ *
+ * - [https://datatracker.ietf.org/doc/html/rfc7065#section-3.1](https://datatracker.ietf.org/doc/html/rfc7065#section-3.1)
+ * - [https://datatracker.ietf.org/doc/html/rfc7064#section-3.1](https://datatracker.ietf.org/doc/html/rfc7064#section-3.1)
+ *
+ */
+ url: string;
+
+ /**
+ * Set a username for the ICE Server you want to use.
+ * This parameter should be defined only for TURN, not for STUN ICE Servers.
+ */
+ username?: string;
+
+ /**
+ * Set a credential for the ICE Server you want to use.
+ * This parameter should be defined only for TURN, not for STUN ICE Servers.
+ */
+ credential?: string;
+
+}
\ No newline at end of file
diff --git a/openvidu-node-client/src/Session.ts b/openvidu-node-client/src/Session.ts
index 9ca089a2..d006d179 100644
--- a/openvidu-node-client/src/Session.ts
+++ b/openvidu-node-client/src/Session.ts
@@ -150,7 +150,8 @@ export class Session {
rtspUri: (!!connectionProperties && !!connectionProperties.rtspUri) ? connectionProperties.rtspUri : null,
adaptativeBitrate: !!connectionProperties ? connectionProperties.adaptativeBitrate : null,
onlyPlayWithSubscribers: !!connectionProperties ? connectionProperties.onlyPlayWithSubscribers : null,
- networkCache: (!!connectionProperties && (connectionProperties.networkCache != null)) ? connectionProperties.networkCache : null
+ networkCache: (!!connectionProperties && (connectionProperties.networkCache != null)) ? connectionProperties.networkCache : null,
+ customIceServers: (!!connectionProperties && (!!connectionProperties.customIceServers != null)) ? connectionProperties.customIceServers : null
});
axios.post(
this.ov.host + OpenVidu.API_SESSIONS + '/' + this.sessionId + '/connection',
diff --git a/openvidu-node-client/src/index.ts b/openvidu-node-client/src/index.ts
index 669b4e90..80b7989c 100644
--- a/openvidu-node-client/src/index.ts
+++ b/openvidu-node-client/src/index.ts
@@ -12,4 +12,5 @@ export * from './Recording';
export * from './RecordingProperties';
export * from './Connection';
export * from './Publisher';
-export * from './VideoCodec';
\ No newline at end of file
+export * from './VideoCodec';
+export * from './IceServerProperties';
\ No newline at end of file
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
index 27f675c0..bb9c592e 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/SessionEventsHandler.java
@@ -25,6 +25,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import io.openvidu.java.client.IceServerProperties;
import org.kurento.client.GenericMediaEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -186,6 +187,11 @@ public class SessionEventsHandler {
}
result.addProperty(ProtocolElements.PARTICIPANTJOINED_COTURNIP_PARAM, openviduConfig.getCoturnIp());
result.addProperty(ProtocolElements.PARTICIPANTJOINED_COTURNPORT_PARAM, openviduConfig.getCoturnPort());
+ List customIceServers = participant.getToken().getCustomIceServers();
+ if (customIceServers!= null && !customIceServers.isEmpty()) {
+ result.add(ProtocolElements.PARTICIPANTJOINED_CUSTOM_ICE_SERVERS,
+ participant.getToken().getCustomIceServersAsJson());
+ }
if (participant.getToken().getTurnCredentials() != null) {
result.addProperty(ProtocolElements.PARTICIPANTJOINED_TURNUSERNAME_PARAM,
participant.getToken().getTurnCredentials().getUsername());
diff --git a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
index 6633a761..a9dbe3bc 100644
--- a/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
+++ b/openvidu-server/src/main/java/io/openvidu/server/core/Token.java
@@ -17,6 +17,7 @@
package io.openvidu.server.core;
+import com.google.gson.JsonArray;
import io.openvidu.java.client.*;
import org.apache.commons.lang3.RandomStringUtils;
@@ -143,6 +144,16 @@ public class Token {
return json;
}
+ public JsonArray getCustomIceServersAsJson() {
+ JsonArray customIceServersJsonList = new JsonArray();
+ if (this.connectionProperties.getCustomIceServers() != null) {
+ this.connectionProperties.getCustomIceServers().forEach((customIceServer) -> {
+ customIceServersJsonList.add(customIceServer.toJson());
+ });
+ }
+ return customIceServersJsonList;
+ }
+
public JsonObject toJsonAsParticipant() {
JsonObject json = new JsonObject();
json.addProperty("id", this.getConnectionId());