openvidu-android: Use customIceServers instead of standalone vars for TURN config

Retain support for OpenVidu v2.22 and older; these legacy properties
will stop being needed starting from OpenVidu v2.23, where
`customIceServers` will always contain all necessary TURN info.
This commit is contained in:
Juan Navarro 2022-06-15 19:16:17 +02:00
parent 17428088c5
commit 2b6d94f226
3 changed files with 136 additions and 57 deletions

View File

@ -51,8 +51,5 @@ public final class JsonConstants {
public static final String SDP_ANSWER = "sdpAnswer";
public static final String METADATA = "metadata";
public static final String TURN_HOST = "coturnIp";
public static final String TURN_PORT = "coturnPort";
public static final String TURN_USER = "turnUsername";
public static final String TURN_PASS = "turnCredential";
public static final String ICE_SERVERS = "customIceServers";
}

View File

@ -15,6 +15,7 @@ import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.MediaStreamTrack;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnection.IceServer;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.RtpTransceiver;
@ -25,6 +26,7 @@ import org.webrtc.VideoDecoderFactory;
import org.webrtc.VideoEncoderFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@ -36,9 +38,11 @@ public class Session {
private Map<String, RemoteParticipant> remoteParticipants = new HashMap<>();
private String id;
private String token;
private String iceServerUri;
private String iceServerUser;
private String iceServerPass;
private final List<IceServer> iceServersDefault =
Arrays.asList(IceServer.builder("stun:stun.l.google.com:19302").createIceServer());
private List<IceServer> iceServers = new ArrayList();
private LinearLayout views_container;
private PeerConnectionFactory peerConnectionFactory;
private CustomWebSocket websocket;
@ -47,9 +51,6 @@ public class Session {
public Session(String id, String token, LinearLayout views_container, SessionActivity activity) {
this.id = id;
this.token = token;
this.iceServerUri = "stun:stun.l.google.com:19302"; // Default value, will be updated from OpenVidu Server.
this.iceServerUser = "";
this.iceServerPass = "";
this.views_container = views_container;
this.activity = activity;
@ -76,25 +77,42 @@ public class Session {
}
public PeerConnection createLocalPeerConnection() {
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO: start block to remove after 2.23
do {
if (iceServers.isEmpty()) {
if (iceServerUri != null) {
IceServer.Builder iceServerBuilder;
try {
iceServerBuilder = IceServer.builder(iceServerUri);
} catch (IllegalArgumentException e) {
break;
}
if (iceServerUser != null) {
iceServerBuilder.setUsername(iceServerUser);
}
if (iceServerPass != null) {
iceServerBuilder.setPassword(iceServerPass);
}
iceServers.add(iceServerBuilder.createIceServer());
}
}
} while (false);
// TODO: end block to remove after 2.23
PeerConnection.IceServer iceServer = PeerConnection.IceServer
.builder(this.iceServerUri)
.setUsername(this.iceServerUser)
.setPassword(this.iceServerPass)
.createIceServer();
iceServers.add(iceServer);
PeerConnection.RTCConfiguration config =
new PeerConnection.RTCConfiguration(iceServers.isEmpty()
? iceServersDefault
: iceServers);
config.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
config.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE;
config.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE;
config.continualGatheringPolicy =
PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
config.keyType = PeerConnection.KeyType.ECDSA;
config.enableDtlsSrtp = true;
config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE;
rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE;
rtcConfig.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
rtcConfig.keyType = PeerConnection.KeyType.ECDSA;
rtcConfig.enableDtlsSrtp = true;
rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new CustomPeerConnectionObserver("local") {
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(config, new CustomPeerConnectionObserver("local") {
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
@ -128,25 +146,42 @@ public class Session {
}
public void createRemotePeerConnection(final String connectionId) {
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO: start block to remove after 2.23
do {
if (iceServers.isEmpty()) {
if (iceServerUri != null) {
IceServer.Builder iceServerBuilder;
try {
iceServerBuilder = IceServer.builder(iceServerUri);
} catch (IllegalArgumentException e) {
break;
}
if (iceServerUser != null) {
iceServerBuilder.setUsername(iceServerUser);
}
if (iceServerPass != null) {
iceServerBuilder.setPassword(iceServerPass);
}
iceServers.add(iceServerBuilder.createIceServer());
}
}
} while (false);
// TODO: end block to remove after 2.23
PeerConnection.IceServer iceServer = PeerConnection.IceServer
.builder(this.iceServerUri)
.setUsername(this.iceServerUser)
.setPassword(this.iceServerPass)
.createIceServer();
iceServers.add(iceServer);
PeerConnection.RTCConfiguration config =
new PeerConnection.RTCConfiguration(iceServers.isEmpty()
? iceServersDefault
: iceServers);
config.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
config.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE;
config.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE;
config.continualGatheringPolicy =
PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
config.keyType = PeerConnection.KeyType.ECDSA;
config.enableDtlsSrtp = true;
config.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
PeerConnection.RTCConfiguration rtcConfig = new PeerConnection.RTCConfiguration(iceServers);
rtcConfig.tcpCandidatePolicy = PeerConnection.TcpCandidatePolicy.ENABLED;
rtcConfig.bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE;
rtcConfig.rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.NEGOTIATE;
rtcConfig.continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY;
rtcConfig.keyType = PeerConnection.KeyType.ECDSA;
rtcConfig.enableDtlsSrtp = true;
rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN;
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(rtcConfig, new CustomPeerConnectionObserver("remotePeerCreation") {
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(config, new CustomPeerConnectionObserver("remotePeerCreation") {
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
super.onIceCandidate(iceCandidate);
@ -224,16 +259,26 @@ public class Session {
return this.token;
}
// TODO: start block to remove after 2.23
private String iceServerUri = null;
private String iceServerUser = null;
private String iceServerPass = null;
public void setIceServerUri(String uri) {
this.iceServerUri = uri;
iceServerUri = uri;
}
public void setIceServerUser(String user) {
this.iceServerUser = user;
iceServerUser = user;
}
public void setIceServerPass(String pass) {
this.iceServerPass = pass;
iceServerPass = pass;
}
// TODO: end block to remove after 2.23
public void setIceServers(List<IceServer> iceServers) {
this.iceServers = iceServers;
}
public LocalParticipant getLocalParticipant() {

View File

@ -21,6 +21,7 @@ import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnection.IceServer;
import org.webrtc.RtpTransceiver;
import org.webrtc.SessionDescription;
@ -31,6 +32,7 @@ import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@ -127,21 +129,56 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
this.mediaServer = result.getString(JsonConstants.MEDIA_SERVER);
if (result.has(JsonConstants.TURN_HOST) && result.has(JsonConstants.TURN_PORT)) {
final String turnHost = result.getString(JsonConstants.TURN_HOST);
final String turnPort = result.getString(JsonConstants.TURN_PORT);
if (result.has(JsonConstants.ICE_SERVERS)) {
final JSONArray jsonIceServers = result.getJSONArray(JsonConstants.ICE_SERVERS);
List<IceServer> iceServers = new ArrayList();
for (int i = 0; i < jsonIceServers.length(); i++) {
JSONObject jsonIceServer = jsonIceServers.getJSONObject(i);
List<String> urls = new ArrayList();
if (jsonIceServer.has("urls")) {
final JSONArray jsonUrls = jsonIceServer.getJSONArray("urls");
for (int j = 0; j < jsonUrls.length(); j++) {
urls.add(jsonUrls.getString(j));
}
}
if (jsonIceServer.has("url")) {
urls.add(jsonIceServer.getString("url"));
}
IceServer.Builder iceServerBuilder;
try {
iceServerBuilder = IceServer.builder(urls);
} catch (IllegalArgumentException e) {
continue;
}
if (jsonIceServer.has("username")) {
iceServerBuilder.setUsername(jsonIceServer.getString("username"));
}
if (jsonIceServer.has("credential")) {
iceServerBuilder.setPassword(jsonIceServer.getString("credential"));
}
iceServers.add(iceServerBuilder.createIceServer());
}
session.setIceServers(iceServers);
}
// TODO: start block to remove after 2.23
if (result.has("coturnIp") && result.has("coturnPort")) {
final String turnHost = result.getString("coturnIp");
final String turnPort = result.getString("coturnPort");
session.setIceServerUri("turn:" + turnHost + ":" + turnPort);
}
if (result.has(JsonConstants.TURN_USER)) {
final String turnUser = result.getString(JsonConstants.TURN_USER);
if (result.has("turnUsername")) {
final String turnUser = result.getString("turnUsername");
session.setIceServerUser(turnUser);
}
if (result.has(JsonConstants.TURN_PASS)) {
final String turnPass = result.getString(JsonConstants.TURN_PASS);
if (result.has("turnCredential")) {
final String turnPass = result.getString("turnCredential");
session.setIceServerPass(turnPass);
}
// TODO: end block to remove after 2.23
PeerConnection localPeerConnection = session.createLocalPeerConnection();
@ -291,7 +328,7 @@ public class CustomWebSocket extends AsyncTask<SessionActivity, Void, Void> impl
participantLeftEvent(params);
break;
default:
throw new JSONException("Unknown method: '" + method + "'");
throw new JSONException("Unknown server event '" + method + "'");
}
}