diff --git a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/constants/JsonConstants.java b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/constants/JsonConstants.java index 5a268ea4..07dfc7aa 100644 --- a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/constants/JsonConstants.java +++ b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/constants/JsonConstants.java @@ -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"; } diff --git a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/openvidu/Session.java b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/openvidu/Session.java index e20d31ed..42f32a18 100644 --- a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/openvidu/Session.java +++ b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/openvidu/Session.java @@ -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 remoteParticipants = new HashMap<>(); private String id; private String token; - private String iceServerUri; - private String iceServerUser; - private String iceServerPass; + + private final List iceServersDefault = + Arrays.asList(IceServer.builder("stun:stun.l.google.com:19302").createIceServer()); + private List 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 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 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 iceServers) { + this.iceServers = iceServers; } public LocalParticipant getLocalParticipant() { diff --git a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/websocket/CustomWebSocket.java b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/websocket/CustomWebSocket.java index c40df3ba..b9de74a6 100644 --- a/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/websocket/CustomWebSocket.java +++ b/openvidu-android/app/src/main/java/io/openvidu/openvidu_android/websocket/CustomWebSocket.java @@ -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 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 iceServers = new ArrayList(); + + for (int i = 0; i < jsonIceServers.length(); i++) { + JSONObject jsonIceServer = jsonIceServers.getJSONObject(i); + List 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 impl participantLeftEvent(params); break; default: - throw new JSONException("Unknown method: '" + method + "'"); + throw new JSONException("Unknown server event '" + method + "'"); } }