Detailed changes
@@ -96,8 +96,8 @@ dependencies {
implementation "com.squareup.retrofit2:converter-gson:2.11.0"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
- implementation 'com.google.guava:guava:32.1.3-android'
- quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.13.35'
+ implementation 'com.google.guava:guava:33.4.0-android'
+ quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.13.52'
implementation 'im.conversations.webrtc:webrtc-android:129.0.0'
}
@@ -113,7 +113,7 @@ android {
defaultConfig {
minSdkVersion 23
targetSdkVersion 34
- versionCode 42134
+ versionCode 42135
versionName "2.17.12"
archivesBaseName += "-$versionName"
applicationId "eu.siacs.conversations"
@@ -1,98 +1,94 @@
package eu.siacs.conversations.xmpp.jingle;
import android.util.Log;
-
import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.primitives.Ints;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.IP;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import im.conversations.android.xmpp.model.stanza.Iq;
-
-import org.webrtc.PeerConnection;
-
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
+import org.webrtc.PeerConnection;
public final class IceServers {
- public static List<PeerConnection.IceServer> parse(final Iq response) {
- ImmutableList.Builder<PeerConnection.IceServer> listBuilder = new ImmutableList.Builder<>();
+ public static Set<PeerConnection.IceServer> parse(final Iq response) {
if (response.getType() == Iq.Type.RESULT) {
- final Element services =
- response.findChild("services", Namespace.EXTERNAL_SERVICE_DISCOVERY);
- final List<Element> children =
- services == null ? Collections.emptyList() : services.getChildren();
- for (final Element child : children) {
- if ("service".equals(child.getName())) {
- final String type = child.getAttribute("type");
- final String host = child.getAttribute("host");
- final String sport = child.getAttribute("port");
- final Integer port = sport == null ? null : Ints.tryParse(sport);
- final String transport = child.getAttribute("transport");
- final String username = child.getAttribute("username");
- final String password = child.getAttribute("password");
- if (Strings.isNullOrEmpty(host) || port == null) {
- continue;
- }
- if (port < 0 || port > 65535) {
+ return Collections.emptySet();
+ }
+ final var builder = new ImmutableSet.Builder<PeerConnection.IceServer>();
+ final Element services =
+ response.findChild("services", Namespace.EXTERNAL_SERVICE_DISCOVERY);
+ final List<Element> children =
+ services == null ? Collections.emptyList() : services.getChildren();
+ for (final Element child : children) {
+ if ("service".equals(child.getName())) {
+ final String type = child.getAttribute("type");
+ final String host = child.getAttribute("host");
+ final String sport = child.getAttribute("port");
+ final Integer port = sport == null ? null : Ints.tryParse(sport);
+ final String transport = child.getAttribute("transport");
+ final String username = child.getAttribute("username");
+ final String password = child.getAttribute("password");
+ if (Strings.isNullOrEmpty(host) || port == null) {
+ continue;
+ }
+ if (port < 0 || port > 65535) {
+ continue;
+ }
+
+ if (Arrays.asList("stun", "stuns", "turn", "turns").contains(type)
+ && Arrays.asList("udp", "tcp").contains(transport)) {
+ if (Arrays.asList("stuns", "turns").contains(type) && "udp".equals(transport)) {
+ Log.w(
+ Config.LOGTAG,
+ "skipping invalid combination of udp/tls in external services");
continue;
}
- if (Arrays.asList("stun", "stuns", "turn", "turns").contains(type)
- && Arrays.asList("udp", "tcp").contains(transport)) {
- if (Arrays.asList("stuns", "turns").contains(type)
- && "udp".equals(transport)) {
- Log.w(
- Config.LOGTAG,
- "skipping invalid combination of udp/tls in external services");
- continue;
- }
-
- // STUN URLs do not support a query section since M110
- final String uri;
- if (Arrays.asList("stun", "stuns").contains(type)) {
- uri = String.format("%s:%s:%s", type, IP.wrapIPv6(host), port);
- } else {
- uri =
- String.format(
- "%s:%s:%s?transport=%s",
- type, IP.wrapIPv6(host), port, transport);
- }
+ // STUN URLs do not support a query section since M110
+ final String uri;
+ if (Arrays.asList("stun", "stuns").contains(type)) {
+ uri = String.format("%s:%s:%s", type, IP.wrapIPv6(host), port);
+ } else {
+ uri =
+ String.format(
+ "%s:%s:%s?transport=%s",
+ type, IP.wrapIPv6(host), port, transport);
+ }
- final PeerConnection.IceServer.Builder iceServerBuilder =
- PeerConnection.IceServer.builder(uri);
- iceServerBuilder.setTlsCertPolicy(
- PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK);
- if (username != null && password != null) {
- iceServerBuilder.setUsername(username);
- iceServerBuilder.setPassword(password);
- } else if (Arrays.asList("turn", "turns").contains(type)) {
- // The WebRTC spec requires throwing an
- // InvalidAccessError when username (from libwebrtc
- // source coder)
- // https://chromium.googlesource.com/external/webrtc/+/master/pc/ice_server_parsing.cc
- Log.w(
- Config.LOGTAG,
- "skipping "
- + type
- + "/"
- + transport
- + " without username and password");
- continue;
- }
- final PeerConnection.IceServer iceServer =
- iceServerBuilder.createIceServer();
- Log.w(Config.LOGTAG, "discovered ICE Server: " + iceServer);
- listBuilder.add(iceServer);
+ final PeerConnection.IceServer.Builder iceServerBuilder =
+ PeerConnection.IceServer.builder(uri);
+ iceServerBuilder.setTlsCertPolicy(
+ PeerConnection.TlsCertPolicy.TLS_CERT_POLICY_INSECURE_NO_CHECK);
+ if (username != null && password != null) {
+ iceServerBuilder.setUsername(username);
+ iceServerBuilder.setPassword(password);
+ } else if (Arrays.asList("turn", "turns").contains(type)) {
+ // The WebRTC spec requires throwing an
+ // InvalidAccessError when username (from libwebrtc
+ // source coder)
+ // https://chromium.googlesource.com/external/webrtc/+/master/pc/ice_server_parsing.cc
+ Log.w(
+ Config.LOGTAG,
+ "skipping "
+ + type
+ + "/"
+ + transport
+ + " without username and password");
+ continue;
}
+ final PeerConnection.IceServer iceServer = iceServerBuilder.createIceServer();
+ Log.w(Config.LOGTAG, "discovered ICE Server: " + iceServer);
+ builder.add(iceServer);
}
}
}
- return listBuilder.build();
+ return builder.build();
}
}
@@ -1339,7 +1339,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
private synchronized void sendSessionAccept(
final Set<Media> media,
final SessionDescription offer,
- final List<PeerConnection.IceServer> iceServers) {
+ final Set<PeerConnection.IceServer> iceServers) {
if (isTerminated()) {
Log.w(
Config.LOGTAG,
@@ -1823,7 +1823,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
private synchronized void sendSessionInitiate(
final Set<Media> media,
final State targetState,
- final List<PeerConnection.IceServer> iceServers) {
+ final Set<PeerConnection.IceServer> iceServers) {
if (isTerminated()) {
Log.w(
Config.LOGTAG,
@@ -2320,7 +2320,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
private void setupWebRTC(
final Set<Media> media,
- final List<PeerConnection.IceServer> iceServers,
+ final Set<PeerConnection.IceServer> iceServers,
final boolean trickle)
throws WebRTCWrapper.InitializationException {
this.jingleConnectionManager.ensureConnectionIsRegistered(this);
@@ -2843,7 +2843,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
Log.w(
Config.LOGTAG,
id.account.getJid().asBareJid() + ": has no external service discovery");
- onIceServersDiscovered.onIceServersDiscovered(Collections.emptyList());
+ onIceServersDiscovered.onIceServersDiscovered(Collections.emptySet());
}
}
@@ -2956,6 +2956,6 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
private interface OnIceServersDiscovered {
- void onIceServersDiscovered(List<PeerConnection.IceServer> iceServers);
+ void onIceServersDiscovered(Set<PeerConnection.IceServer> iceServers);
}
}
@@ -12,7 +12,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericDescription;
import eu.siacs.conversations.xmpp.jingle.stanzas.GenericTransportInfo;
@@ -21,13 +20,11 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
import eu.siacs.conversations.xmpp.jingle.stanzas.OmemoVerifiedIceUdpTransportInfo;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
import im.conversations.android.xmpp.model.jingle.Jingle;
-
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-
import javax.annotation.Nonnull;
public class RtpContentMap extends AbstractContentMap<RtpDescription, IceUdpTransportInfo> {
@@ -99,7 +96,7 @@ public class RtpContentMap extends AbstractContentMap<RtpDescription, IceUdpTran
}
void requireDTLSFingerprint(final boolean requireActPass) {
- if (this.contents.size() == 0) {
+ if (this.contents.isEmpty()) {
throw new IllegalStateException("No contents available");
}
for (Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>> entry :
@@ -118,7 +115,8 @@ public class RtpContentMap extends AbstractContentMap<RtpDescription, IceUdpTran
if (setup == null) {
throw new SecurityException(
String.format(
- "Use of DTLS-SRTP (XEP-0320) is required for content %s but missing setup attribute",
+ "Use of DTLS-SRTP (XEP-0320) is required for content %s but missing"
+ + " setup attribute",
entry.getKey()));
}
if (requireActPass && setup != IceUdpTransportInfo.Setup.ACTPASS) {
@@ -127,6 +125,7 @@ public class RtpContentMap extends AbstractContentMap<RtpDescription, IceUdpTran
}
}
}
+
RtpContentMap transportInfo(
final String contentName, final IceUdpTransportInfo.Candidate candidate) {
final DescriptionTransport<RtpDescription, IceUdpTransportInfo> descriptionTransport =
@@ -2,9 +2,7 @@ package eu.siacs.conversations.xmpp.jingle;
import android.util.Log;
import android.util.Pair;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
@@ -12,7 +10,6 @@ import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
@@ -21,7 +18,6 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Group;
import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
import eu.siacs.conversations.xmpp.jingle.stanzas.WebRTCDataChannelTransportInfo;
-
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -206,6 +202,10 @@ public class SessionDescription {
entry : contentMap.contents.entrySet()) {
final String name = entry.getKey();
checkNoWhitespace(name, "content name must not contain any whitespace");
+ // https://groups.google.com/g/discuss-webrtc/c/VG406JMTBI4/m/MrSex_q7AgAJ
+ if (name.length() > 16) {
+ throw new IllegalArgumentException("mid should not be longer than 16 chars");
+ }
final DescriptionTransport<RtpDescription, IceUdpTransportInfo> descriptionTransport =
entry.getValue();
final RtpDescription description = descriptionTransport.description;
@@ -226,7 +226,7 @@ public class SessionDescription {
if (parameters.size() == 1) {
mediaAttributes.put(
"fmtp", RtpDescription.Parameter.toSdpString(id, parameters.get(0)));
- } else if (parameters.size() > 0) {
+ } else if (!parameters.isEmpty()) {
mediaAttributes.put(
"fmtp", RtpDescription.Parameter.toSdpString(id, parameters));
}
@@ -306,7 +306,7 @@ public class SessionDescription {
"A SSRC group is missing semantics attribute");
}
checkNoWhitespace(semantics, "source group semantics must not contain whitespace");
- if (groups.size() == 0) {
+ if (groups.isEmpty()) {
throw new IllegalArgumentException("A SSRC group is missing SSRC ids");
}
for (final String source : groups) {
@@ -3,18 +3,26 @@ package eu.siacs.conversations.xmpp.jingle;
import android.content.Context;
import android.os.Build;
import android.util.Log;
-
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.services.XmppConnectionService;
-
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.CandidatePairChangeEvent;
@@ -35,19 +43,6 @@ import org.webrtc.SessionDescription;
import org.webrtc.VideoTrack;
import org.webrtc.audio.JavaAudioDeviceModule;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
public class WebRTCWrapper {
private static final String EXTENDED_LOGGING_TAG = WebRTCWrapper.class.getSimpleName();
@@ -235,13 +230,13 @@ public class WebRTCWrapper {
synchronized void initializePeerConnection(
final Set<Media> media,
- final List<PeerConnection.IceServer> iceServers,
+ final Set<PeerConnection.IceServer> iceServers,
final boolean trickle)
throws InitializationException {
Preconditions.checkState(this.eglBase != null);
Preconditions.checkNotNull(media);
Preconditions.checkArgument(
- media.size() > 0, "media can not be empty when initializing peer connection");
+ !media.isEmpty(), "media can not be empty when initializing peer connection");
final boolean setUseHardwareAcousticEchoCanceler =
!HARDWARE_AEC_BLACKLIST.contains(Build.MODEL);
Log.d(
@@ -371,16 +366,16 @@ public class WebRTCWrapper {
if (videoSourceWrapper != null) {
try {
videoSourceWrapper.stopCapture();
- } catch (InterruptedException e) {
- e.printStackTrace();
+ } catch (final InterruptedException e) {
+ Log.e(Config.LOGTAG, "could not stop capturing video source", e);
}
}
}
public static PeerConnection.RTCConfiguration buildConfiguration(
- final List<PeerConnection.IceServer> iceServers, final boolean trickle) {
+ final Set<PeerConnection.IceServer> iceServers, final boolean trickle) {
final PeerConnection.RTCConfiguration rtcConfig =
- new PeerConnection.RTCConfiguration(iceServers);
+ new PeerConnection.RTCConfiguration(ImmutableList.copyOf(iceServers));
rtcConfig.tcpCandidatePolicy =
PeerConnection.TcpCandidatePolicy.DISABLED; // XEP-0176 doesn't support tcp
if (trickle) {
@@ -397,7 +392,7 @@ public class WebRTCWrapper {
}
void reconfigurePeerConnection(
- final List<PeerConnection.IceServer> iceServers, final boolean trickle) {
+ final Set<PeerConnection.IceServer> iceServers, final boolean trickle) {
requirePeerConnection().setConfiguration(buildConfiguration(iceServers, trickle));
}
@@ -1,28 +1,23 @@
package eu.siacs.conversations.xmpp.jingle.stanzas;
import android.util.Log;
-
import androidx.annotation.NonNull;
-
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
-import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.jingle.SessionDescription;
import eu.siacs.conversations.xmpp.jingle.transports.Transport;
-
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -101,7 +96,9 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
for (final Element child : this.children) {
if (Namespace.JINGLE_TRANSPORT_ICE_OPTION.equals(child.getNamespace())
&& IceOption.WELL_KNOWN.contains(child.getName())) {
- optionBuilder.add(child.getName());
+ optionBuilder.add(
+ SessionDescription.checkNoWhitespace(
+ child.getName(), "Ice options should not contain whitespace"));
}
}
return optionBuilder.build();
@@ -159,7 +156,7 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
transportInfo.setAttributes(new Hashtable<>(getAttributes()));
transportInfo.setChildren(this.getChildren());
- for(final Candidate candidate : candidates) {
+ for (final Candidate candidate : candidates) {
transportInfo.addChild(candidate);
}
return transportInfo;
@@ -220,7 +217,8 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
return null;
}
- public static Candidate fromSdpAttributeValue(final String value, final String currentUfrag) {
+ public static Candidate fromSdpAttributeValue(
+ final String value, final String currentUfrag) {
final String[] segments = value.split(" ");
if (segments.length < 6) {
return null;
@@ -1,25 +1,22 @@
package eu.siacs.conversations.xmpp.jingle.stanzas;
import android.util.Pair;
-
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
+import eu.siacs.conversations.xmpp.jingle.Media;
+import eu.siacs.conversations.xmpp.jingle.SessionDescription;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xml.Namespace;
-import eu.siacs.conversations.xmpp.jingle.Media;
-import eu.siacs.conversations.xmpp.jingle.SessionDescription;
-
public class RtpDescription extends GenericDescription {
private RtpDescription(final String media) {
@@ -291,7 +288,7 @@ public class RtpDescription extends GenericDescription {
final String channels = this.getAttribute("channels");
if (channels == null) {
return 1; // The number of channels; if omitted, it MUST be assumed to contain one
- // channel
+ // channel
}
try {
return Integer.parseInt(channels);
@@ -544,13 +541,17 @@ public class RtpDescription extends GenericDescription {
}
public List<String> getSsrcs() {
- ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
- for (Element child : this.children) {
+ final ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
+ for (final Element child : this.children) {
if ("source".equals(child.getName())) {
final String ssrc = child.getAttribute("ssrc");
- if (ssrc != null) {
- builder.add(ssrc);
+ if (Strings.isNullOrEmpty(ssrc)) {
+ continue;
}
+ builder.add(
+ SessionDescription.checkNoNewline(
+ ssrc,
+ "Source Specific media attributes can not contain newline"));
}
}
return builder.build();
@@ -5,7 +5,6 @@ import static eu.siacs.conversations.xmpp.jingle.WebRTCWrapper.logDescription;
import android.content.Context;
import android.util.Log;
-
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Closeables;
@@ -13,7 +12,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
-
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.xml.Namespace;
@@ -22,17 +20,7 @@ import eu.siacs.conversations.xmpp.jingle.IceServers;
import eu.siacs.conversations.xmpp.jingle.WebRTCWrapper;
import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo;
import eu.siacs.conversations.xmpp.jingle.stanzas.WebRTCDataChannelTransportInfo;
-
import im.conversations.android.xmpp.model.stanza.Iq;
-
-import org.webrtc.CandidatePairChangeEvent;
-import org.webrtc.DataChannel;
-import org.webrtc.IceCandidate;
-import org.webrtc.MediaStream;
-import org.webrtc.PeerConnection;
-import org.webrtc.PeerConnectionFactory;
-import org.webrtc.SessionDescription;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
@@ -46,14 +34,21 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
-
import javax.annotation.Nonnull;
+import org.webrtc.CandidatePairChangeEvent;
+import org.webrtc.DataChannel;
+import org.webrtc.IceCandidate;
+import org.webrtc.MediaStream;
+import org.webrtc.PeerConnection;
+import org.webrtc.PeerConnectionFactory;
+import org.webrtc.SessionDescription;
public class WebRTCDataChannelTransport implements Transport {
@@ -229,12 +224,12 @@ public class WebRTCDataChannelTransport implements Transport {
}
}
- private ListenableFuture<List<PeerConnection.IceServer>> getIceServers() {
+ private ListenableFuture<Set<PeerConnection.IceServer>> getIceServers() {
if (Config.DISABLE_PROXY_LOOKUP) {
- return Futures.immediateFuture(Collections.emptyList());
+ return Futures.immediateFuture(Collections.emptySet());
}
if (xmppConnection.getFeatures().externalServiceDiscovery()) {
- final SettableFuture<List<PeerConnection.IceServer>> iceServerFuture =
+ final SettableFuture<Set<PeerConnection.IceServer>> iceServerFuture =
SettableFuture.create();
final Iq request = new Iq(Iq.Type.GET);
request.setTo(this.account.getDomain());
@@ -254,12 +249,12 @@ public class WebRTCDataChannelTransport implements Transport {
});
return iceServerFuture;
} else {
- return Futures.immediateFuture(Collections.emptyList());
+ return Futures.immediateFuture(Collections.emptySet());
}
}
private PeerConnection createPeerConnection(
- final List<PeerConnection.IceServer> iceServers, final boolean trickle) {
+ final Set<PeerConnection.IceServer> iceServers, final boolean trickle) {
final PeerConnection.RTCConfiguration rtcConfig = buildConfiguration(iceServers, trickle);
final PeerConnection peerConnection =
requirePeerConnectionFactory()