aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2017-06-24 09:52:45 +0200
committerChristian Schneppe <christian@pix-art.de>2017-06-24 09:52:45 +0200
commit356c7bec9c2900242b16d99968cdcd78e674dee9 (patch)
treec44021992d825db96fcc4f84400cd63cc8d16450
parent8e897c3d69d65155a2fa7a4ce75bfc5bc13d7233 (diff)
upgrade minidns. refactored dns utils
-rw-r--r--build.gradle2
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/AndroidUsingLinkProperties.java76
-rw-r--r--src/main/java/de/pixart/messenger/utils/DNSHelper.java299
-rw-r--r--src/main/java/de/pixart/messenger/utils/IP.java22
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java159
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java39
7 files changed, 274 insertions, 325 deletions
diff --git a/build.gradle b/build.gradle
index 166de9735..662e4c069 100644
--- a/build.gradle
+++ b/build.gradle
@@ -41,7 +41,7 @@ dependencies {
compile 'org.gnu.inet:libidn:1.15'
compile 'com.google.zxing:core:3.3.0'
compile 'com.google.zxing:android-integration:3.3.0'
- compile 'de.measite.minidns:minidns:0.1.7'
+ compile 'de.measite.minidns:minidns-hla:0.2.1'
compile 'de.timroes.android:EnhancedListView:0.3.4'
compile 'me.leolin:ShortcutBadger:1.1.17@aar'
compile 'com.kyleduo.switchbutton:library:1.2.8'
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index d5ea710e5..243b9b4f5 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -120,6 +120,7 @@ import de.pixart.messenger.utils.OnPhoneContactsLoadedListener;
import de.pixart.messenger.utils.PRNGFixes;
import de.pixart.messenger.utils.PhoneHelper;
import de.pixart.messenger.utils.ReplacingSerialSingleThreadExecutor;
+import de.pixart.messenger.utils.Resolver;
import de.pixart.messenger.utils.SerialSingleThreadExecutor;
import de.pixart.messenger.utils.XmppUri;
import de.pixart.messenger.xml.Element;
@@ -1085,6 +1086,7 @@ public class XmppConnectionService extends Service {
public void onCreate() {
ExceptionHelper.init(getApplicationContext());
PRNGFixes.apply();
+ Resolver.registerLookupMechanism(this);
this.mRandom = new SecureRandom();
updateMemorizingTrustmanager();
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
diff --git a/src/main/java/de/pixart/messenger/utils/AndroidUsingLinkProperties.java b/src/main/java/de/pixart/messenger/utils/AndroidUsingLinkProperties.java
new file mode 100644
index 000000000..b201b354b
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/utils/AndroidUsingLinkProperties.java
@@ -0,0 +1,76 @@
+package de.pixart.messenger.utils;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.RouteInfo;
+import android.os.Build;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import de.measite.minidns.dnsserverlookup.AbstractDNSServerLookupMechanism;
+import de.measite.minidns.dnsserverlookup.AndroidUsingExec;
+
+public class AndroidUsingLinkProperties extends AbstractDNSServerLookupMechanism {
+
+ private final Context context;
+
+ protected AndroidUsingLinkProperties(Context context) {
+ super(AndroidUsingLinkProperties.class.getSimpleName(), AndroidUsingExec.PRIORITY - 1);
+ this.context = context;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
+ }
+
+ @Override
+ @TargetApi(21)
+ public String[] getDnsServerAddresses() {
+ ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ Network[] networks = connectivityManager == null ? null : connectivityManager.getAllNetworks();
+ if (networks == null) {
+ return new String[0];
+ }
+ List<String> servers = new ArrayList<>();
+ for (Network network : networks) {
+ LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
+ if (linkProperties != null) {
+ if (hasDefaultRoute(linkProperties)) {
+ servers.addAll(0, getIPv4First(linkProperties.getDnsServers()));
+ } else {
+ servers.addAll(getIPv4First(linkProperties.getDnsServers()));
+ }
+ }
+ }
+ return servers.toArray(new String[servers.size()]);
+ }
+
+ private static List<String> getIPv4First(List<InetAddress> in) {
+ List<String> out = new ArrayList<>();
+ for (InetAddress addr : in) {
+ if (addr instanceof Inet4Address) {
+ out.add(0, addr.toString());
+ } else {
+ out.add(addr.toString());
+ }
+ }
+ return out;
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ private static boolean hasDefaultRoute(LinkProperties linkProperties) {
+ for (RouteInfo route : linkProperties.getRoutes()) {
+ if (route.isDefaultRoute()) {
+ return true;
+ }
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/DNSHelper.java b/src/main/java/de/pixart/messenger/utils/DNSHelper.java
deleted file mode 100644
index 70f600375..000000000
--- a/src/main/java/de/pixart/messenger/utils/DNSHelper.java
+++ /dev/null
@@ -1,299 +0,0 @@
-package de.pixart.messenger.utils;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.LinkProperties;
-import android.net.Network;
-import android.net.RouteInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.SocketTimeoutException;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Random;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-import de.measite.minidns.Client;
-import de.measite.minidns.DNSMessage;
-import de.measite.minidns.Record;
-import de.measite.minidns.Record.CLASS;
-import de.measite.minidns.Record.TYPE;
-import de.measite.minidns.record.A;
-import de.measite.minidns.record.AAAA;
-import de.measite.minidns.record.Data;
-import de.measite.minidns.record.SRV;
-import de.measite.minidns.util.NameUtil;
-import de.pixart.messenger.Config;
-import de.pixart.messenger.xmpp.jid.Jid;
-
-public class DNSHelper {
-
- public static final Pattern PATTERN_IPV4 = Pattern.compile("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
- public static final Pattern PATTERN_IPV6_HEX4DECCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
- public static final Pattern PATTERN_IPV6_6HEX4DEC = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
- public static final Pattern PATTERN_IPV6_HEXCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\\z");
- public static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z");
-
- protected static Client client = new Client();
-
- protected static Context context;
-
- public static Bundle getSRVRecord(final Jid jid, Context context) throws IOException {
- DNSHelper.context = context;
- final String host = jid.getDomainpart();
- final List<InetAddress> servers = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDnsServers(context) : getDnsServersPreLollipop();
- Bundle b = new Bundle();
- boolean interrupted = false;
- for (InetAddress server : servers) {
- if (Thread.currentThread().isInterrupted()) {
- interrupted = true;
- break;
- }
- b = queryDNS(host, server);
- if (b.containsKey("values")) {
- return b;
- }
- }
- if (!b.containsKey("values")) {
- Log.d(Config.LOGTAG, (interrupted ? "Thread interrupted during DNS query" : "all dns queries failed") + ". provide fallback A record");
- ArrayList<Parcelable> values = new ArrayList<>();
- values.add(createNamePortBundle(host, 5222, false));
- b.putParcelableArrayList("values", values);
- }
- return b;
- }
-
- @TargetApi(21)
- private static List<InetAddress> getDnsServers(Context context) {
- List<InetAddress> servers = new ArrayList<>();
- ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- Network[] networks = connectivityManager == null ? null : connectivityManager.getAllNetworks();
- if (networks == null) {
- return getDnsServersPreLollipop();
- }
- for (int i = 0; i < networks.length; ++i) {
- LinkProperties linkProperties = connectivityManager.getLinkProperties(networks[i]);
- if (linkProperties != null) {
- if (hasDefaultRoute(linkProperties)) {
- servers.addAll(0, getIPv4First(linkProperties.getDnsServers()));
- } else {
- servers.addAll(getIPv4First(linkProperties.getDnsServers()));
- }
- }
- }
- if (servers.size() > 0) {
- Log.d(Config.LOGTAG, "used lollipop variant to discover dns servers in " + networks.length + " networks");
- }
- return servers.size() > 0 ? servers : getDnsServersPreLollipop();
- }
-
- private static List<InetAddress> getIPv4First(List<InetAddress> in) {
- List<InetAddress> out = new ArrayList<>();
- for (InetAddress addr : in) {
- if (addr instanceof Inet4Address) {
- out.add(0, addr);
- } else {
- out.add(addr);
- }
- }
- return out;
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private static boolean hasDefaultRoute(LinkProperties linkProperties) {
- for (RouteInfo route : linkProperties.getRoutes()) {
- if (route.isDefaultRoute()) {
- return true;
- }
- }
- return false;
- }
-
- private static List<InetAddress> getDnsServersPreLollipop() {
- List<InetAddress> servers = new ArrayList<>();
- String[] dns = client.findDNS();
- for (int i = 0; i < dns.length; ++i) {
- try {
- servers.add(InetAddress.getByName(dns[i]));
- } catch (UnknownHostException e) {
- //ignore
- }
- }
- return servers;
- }
-
- private static class TlsSrv {
- private final SRV srv;
- private final boolean tls;
-
- public TlsSrv(SRV srv, boolean tls) {
- this.srv = srv;
- this.tls = tls;
- }
- }
-
- private static void fillSrvMaps(final String qname, final InetAddress dnsServer, final Map<Integer, List<TlsSrv>> priorities, final Map<String, List<String>> ips4, final Map<String, List<String>> ips6, final boolean tls) throws IOException {
- final DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN, dnsServer.getHostAddress());
- for (Record[] rrset : new Record[][]{message.getAnswers(), message.getAdditionalResourceRecords()}) {
- for (Record rr : rrset) {
- Data d = rr.getPayload();
- final String name = rr.getName() != null ? rr.getName().toLowerCase(Locale.US) : null;
- if (d instanceof SRV && NameUtil.idnEquals(qname, name)) {
- SRV srv = (SRV) d;
- if (!priorities.containsKey(srv.getPriority())) {
- priorities.put(srv.getPriority(), new ArrayList<TlsSrv>());
- }
- priorities.get(srv.getPriority()).add(new TlsSrv(srv, tls));
- } else if (d instanceof SRV) {
- Log.d(Config.LOGTAG, "found unrecognized SRV record with name: " + name);
- }
- if (d instanceof A) {
- A a = (A) d;
- if (!ips4.containsKey(name)) {
- ips4.put(name, new ArrayList<String>());
- }
- ips4.get(name).add(a.toString());
- }
- if (d instanceof AAAA) {
- AAAA aaaa = (AAAA) d;
- if (!ips6.containsKey(name)) {
- ips6.put(name, new ArrayList<String>());
- }
- ips6.get(name).add("[" + aaaa.toString() + "]");
- }
- }
- }
- }
-
- public static Bundle queryDNS(String host, InetAddress dnsServer) {
- Bundle bundle = new Bundle();
- try {
- client.setTimeout(Config.SOCKET_TIMEOUT * 1000);
- final String qname = "_xmpp-client._tcp." + host.toLowerCase(Locale.US);
- final String tlsQname = "_xmpps-client._tcp." + host.toLowerCase(Locale.US);
- Log.d(Config.LOGTAG, "using dns server: " + dnsServer.getHostAddress() + " to look up " + host);
-
- final Map<Integer, List<TlsSrv>> priorities = new TreeMap<>();
- final Map<String, List<String>> ips4 = new TreeMap<>();
- final Map<String, List<String>> ips6 = new TreeMap<>();
-
- fillSrvMaps(qname, dnsServer, priorities, ips4, ips6, false);
- fillSrvMaps(tlsQname, dnsServer, priorities, ips4, ips6, true);
-
- final List<TlsSrv> result = new ArrayList<>();
- for (final List<TlsSrv> s : priorities.values()) {
- result.addAll(s);
- }
-
- final ArrayList<Bundle> values = new ArrayList<>();
- if (result.size() == 0) {
- DNSMessage response;
- try {
- response = client.query(host, TYPE.A, CLASS.IN, dnsServer.getHostAddress());
- for (int i = 0; i < response.getAnswers().length; ++i) {
- values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false));
- }
- } catch (SocketTimeoutException e) {
- Log.d(Config.LOGTAG, "ignoring timeout exception when querying A record on " + dnsServer.getHostAddress());
- }
- try {
- response = client.query(host, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress());
- for (int i = 0; i < response.getAnswers().length; ++i) {
- values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false));
- }
- } catch (SocketTimeoutException e) {
- Log.d(Config.LOGTAG, "ignoring timeout exception when querying AAAA record on " + dnsServer.getHostAddress());
- }
- values.add(createNamePortBundle(host, 5222, false));
- bundle.putParcelableArrayList("values", values);
- return bundle;
- }
- for (final TlsSrv tlsSrv : result) {
- final SRV srv = tlsSrv.srv;
- final String name = srv.getName() != null ? srv.getName().toLowerCase(Locale.US) : null;
- if (ips6.containsKey(name)) {
- values.add(createNamePortBundle(name, srv.getPort(), ips6, tlsSrv.tls));
- } else {
- try {
- DNSMessage response = client.query(name, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress());
- for (int i = 0; i < response.getAnswers().length; ++i) {
- values.add(createNamePortBundle(name, srv.getPort(), response.getAnswers()[i].getPayload(), tlsSrv.tls));
- }
- } catch (SocketTimeoutException e) {
- Log.d(Config.LOGTAG, "ignoring timeout exception when querying AAAA record on " + dnsServer.getHostAddress());
- }
- }
- if (ips4.containsKey(name)) {
- values.add(createNamePortBundle(name, srv.getPort(), ips4, tlsSrv.tls));
- } else {
- DNSMessage response = client.query(name, TYPE.A, CLASS.IN, dnsServer.getHostAddress());
- for (int i = 0; i < response.getAnswers().length; ++i) {
- values.add(createNamePortBundle(name, srv.getPort(), response.getAnswers()[i].getPayload(), tlsSrv.tls));
- }
- }
- values.add(createNamePortBundle(name, srv.getPort(), tlsSrv.tls));
- }
- bundle.putParcelableArrayList("values", values);
- } catch (SocketTimeoutException e) {
- bundle.putString("error", "timeout");
- } catch (Exception e) {
- bundle.putString("error", "unhandled");
- }
- return bundle;
- }
-
- private static Bundle createNamePortBundle(String name, int port, final boolean tls) {
- Bundle namePort = new Bundle();
- namePort.putString("name", name);
- namePort.putBoolean("tls", tls);
- namePort.putInt("port", port);
- return namePort;
- }
-
- private static Bundle createNamePortBundle(String name, int port, Map<String, List<String>> ips, final boolean tls) {
- Bundle namePort = new Bundle();
- namePort.putString("name", name);
- namePort.putBoolean("tls", tls);
- namePort.putInt("port", port);
- if (ips != null) {
- List<String> ip = ips.get(name);
- Collections.shuffle(ip, new Random());
- namePort.putString("ip", ip.get(0));
- }
- return namePort;
- }
-
- private static Bundle createNamePortBundle(String name, int port, Data data, final boolean tls) {
- Bundle namePort = new Bundle();
- namePort.putString("name", name);
- namePort.putBoolean("tls", tls);
- namePort.putInt("port", port);
- if (data instanceof A) {
- namePort.putString("ip", data.toString());
- } else if (data instanceof AAAA) {
- namePort.putString("ip", "[" + data.toString() + "]");
- }
- return namePort;
- }
-
- public static boolean isIp(final String server) {
- return server != null && (
- PATTERN_IPV4.matcher(server).matches()
- || PATTERN_IPV6.matcher(server).matches()
- || PATTERN_IPV6_6HEX4DEC.matcher(server).matches()
- || PATTERN_IPV6_HEX4DECCOMPRESSED.matcher(server).matches()
- || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches());
- }
-}
diff --git a/src/main/java/de/pixart/messenger/utils/IP.java b/src/main/java/de/pixart/messenger/utils/IP.java
new file mode 100644
index 000000000..42f9ec553
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/utils/IP.java
@@ -0,0 +1,22 @@
+package de.pixart.messenger.utils;
+
+import java.util.regex.Pattern;
+
+public class IP {
+
+ private static final Pattern PATTERN_IPV4 = Pattern.compile("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
+ private static final Pattern PATTERN_IPV6_HEX4DECCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
+ private static final Pattern PATTERN_IPV6_6HEX4DEC = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z");
+ private static final Pattern PATTERN_IPV6_HEXCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\\z");
+ private static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z");
+
+ public static boolean matches(String server) {
+ return server != null && (
+ PATTERN_IPV4.matcher(server).matches()
+ || PATTERN_IPV6.matcher(server).matches()
+ || PATTERN_IPV6_6HEX4DEC.matcher(server).matches()
+ || PATTERN_IPV6_HEX4DECCOMPRESSED.matcher(server).matches()
+ || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches());
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
new file mode 100644
index 000000000..a5bcad547
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -0,0 +1,159 @@
+package de.pixart.messenger.utils;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import de.measite.minidns.DNSClient;
+import de.measite.minidns.DNSName;
+import de.measite.minidns.Question;
+import de.measite.minidns.Record;
+import de.measite.minidns.hla.DnssecResolverApi;
+import de.measite.minidns.hla.ResolverResult;
+import de.measite.minidns.record.A;
+import de.measite.minidns.record.AAAA;
+import de.measite.minidns.record.Data;
+import de.measite.minidns.record.InternetAddressRR;
+import de.measite.minidns.record.SRV;
+import de.pixart.messenger.Config;
+
+public class Resolver {
+
+ private static final String DIRECT_TLS_SERVICE = "_xmpps-client";
+ private static final String STARTTLS_SERICE = "_xmpp-client";
+
+ public static void registerLookupMechanism(Context context) {
+ DNSClient.addDnsServerLookupMechanism(new AndroidUsingLinkProperties(context));
+ }
+
+ public static List<Result> resolve(String domain) {
+ List<Result> results = new ArrayList<>();
+ try {
+ results.addAll(resolveSrv(domain, true));
+ } catch (IOException e) {
+ //ignore
+ }
+ try {
+ results.addAll(resolveSrv(domain, false));
+ } catch (IOException e) {
+ //ignore
+ }
+ if (results.size() == 0) {
+ results.add(Result.createDefault(domain));
+ }
+ Collections.sort(results);
+ return results;
+ }
+
+ private static List<Result> resolveSrv(String domain, final boolean directTls) throws IOException {
+ Question question = new Question((directTls ? DIRECT_TLS_SERVICE : STARTTLS_SERICE) + "._tcp." + domain, Record.TYPE.SRV);
+ ResolverResult<Data> result = DnssecResolverApi.INSTANCE.resolve(question);
+ List<Result> results = new ArrayList<>();
+ for (Data record : result.getAnswersOrEmptySet()) {
+ if (record instanceof SRV) {
+ SRV srvRecord = (SRV) record;
+ boolean added = results.addAll(resolveIp(srvRecord, A.class, result.isAuthenticData(), directTls));
+ added |= results.addAll(resolveIp(srvRecord, AAAA.class, result.isAuthenticData(), directTls));
+ if (!added) {
+ Result resolverResult = Result.fromRecord(srvRecord, directTls);
+ resolverResult.authenticated = resolverResult.isAuthenticated();
+ results.add(resolverResult);
+ }
+ }
+ }
+ return results;
+ }
+
+ private static <D extends InternetAddressRR> List<Result> resolveIp(SRV srv, Class<D> type, boolean authenticated, boolean directTls) {
+ List<Result> list = new ArrayList<>();
+ try {
+ ResolverResult<D> results = DnssecResolverApi.INSTANCE.resolve(srv.name, type);
+ for (D record : results.getAnswersOrEmptySet()) {
+ Result resolverResult = Result.fromRecord(srv, directTls);
+ resolverResult.authenticated = results.isAuthenticData() && authenticated;
+ resolverResult.ip = record.getInetAddress();
+ list.add(resolverResult);
+ }
+ } catch (IOException e) {
+ Log.d(Config.LOGTAG, e.getMessage());
+ //ignore. will add default record later
+ }
+ return list;
+ }
+
+ public static class Result implements Comparable<Result> {
+ private InetAddress ip;
+ private DNSName hostname;
+ private int port = 5222;
+ private boolean directTls = false;
+ private boolean authenticated = false;
+ private int priority;
+
+ public InetAddress getIp() {
+ return ip;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public DNSName getHostname() {
+ return hostname;
+ }
+
+ public boolean isDirectTls() {
+ return directTls;
+ }
+
+ public boolean isAuthenticated() {
+ return authenticated;
+ }
+
+ @Override
+ public String toString() {
+ return "Result{" +
+ "ip='" + ip + '\'' +
+ ", hostame='" + hostname.toString() + '\'' +
+ ", port=" + port +
+ ", directTls=" + directTls +
+ ", authenticated=" + authenticated +
+ ", priority=" + priority +
+ '}';
+ }
+
+ @Override
+ public int compareTo(@NonNull Result result) {
+ if (result.priority == priority) {
+ if (directTls == result.directTls) {
+ return 0;
+ } else {
+ return directTls ? 1 : -1;
+ }
+ } else {
+ return priority - result.priority;
+ }
+ }
+
+ public static Result fromRecord(SRV srv, boolean directTls) {
+ Result result = new Result();
+ result.port = srv.port;
+ result.hostname = srv.name;
+ result.directTls = directTls;
+ result.priority = srv.priority;
+ return result;
+ }
+
+ public static Result createDefault(String domain) {
+ Result result = new Result();
+ result.port = 5222;
+ result.hostname = DNSName.from(domain);
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
index f3ce20da3..a62f5c2d3 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -2,8 +2,6 @@ package de.pixart.messenger.xmpp;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.os.Bundle;
-import android.os.Parcelable;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
@@ -20,7 +18,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.ConnectException;
-import java.net.IDN;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
@@ -69,9 +66,10 @@ import de.pixart.messenger.generator.IqGenerator;
import de.pixart.messenger.services.NotificationService;
import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.ui.EditAccountActivity;
-import de.pixart.messenger.utils.DNSHelper;
+import de.pixart.messenger.utils.IP;
import de.pixart.messenger.utils.Namespace;
import de.pixart.messenger.utils.Patterns;
+import de.pixart.messenger.utils.Resolver;
import de.pixart.messenger.utils.SSLSocketHelper;
import de.pixart.messenger.utils.SocksSocketFactory;
import de.pixart.messenger.xml.Element;
@@ -357,7 +355,7 @@ public class XmppConnection implements Runnable {
} catch (Exception e) {
throw new IOException(e.getMessage());
}
- } else if (DNSHelper.isIp(account.getServer().toString())) {
+ } else if (IP.matches(account.getServer().toString())) {
localSocket = new Socket();
try {
localSocket.connect(new InetSocketAddress(account.getServer().toString(), 5222), Config.SOCKET_TIMEOUT * 1000);
@@ -373,37 +371,28 @@ public class XmppConnection implements Runnable {
throw new IOException(e.getMessage());
}
} else {
- final Bundle result = DNSHelper.getSRVRecord(account.getServer(), mXmppConnectionService);
- final ArrayList<Parcelable> values = result.getParcelableArrayList("values");
- for (Iterator<Parcelable> iterator = values.iterator(); iterator.hasNext(); ) {
+ List<Resolver.Result> results = Resolver.resolve(account.getJid().getDomainpart());
+ Log.d(Config.LOGTAG, "results: " + results);
+ for (Iterator<Resolver.Result> iterator = results.iterator(); iterator.hasNext(); ) {
+ final Resolver.Result result = iterator.next();
if (Thread.currentThread().isInterrupted()) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": Thread was interrupted");
return;
}
- final Bundle namePort = (Bundle) iterator.next();
try {
- String srvRecordServer;
- try {
- srvRecordServer = IDN.toASCII(namePort.getString("name"));
- } catch (final IllegalArgumentException e) {
- // TODO: Handle me?`
- srvRecordServer = "";
- }
- final int srvRecordPort = namePort.getInt("port");
- final String srvIpServer = namePort.getString("ip");
// if tls is true, encryption is implied and must not be started
- features.encryptionEnabled = namePort.getBoolean("tls");
+ features.encryptionEnabled = result.isDirectTls();
final InetSocketAddress addr;
- if (srvIpServer != null) {
- addr = new InetSocketAddress(srvIpServer, srvRecordPort);
+ if (result.getIp() != null) {
+ addr = new InetSocketAddress(result.getIp(), result.getPort());
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
- + ": using values from dns " + srvRecordServer
- + "[" + srvIpServer + "]:" + srvRecordPort + " tls: " + features.encryptionEnabled);
+ + ": using values from dns " + result.getHostname().toString()
+ + "[" + result.getIp().toString() + "]:" + result.getPort() + " tls: " + features.encryptionEnabled);
} else {
- addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
+ addr = new InetSocketAddress(result.getHostname().toString(), result.getPort());
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns "
- + srvRecordServer + ":" + srvRecordPort + " tls: " + features.encryptionEnabled);
+ + result.getHostname().toString() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
}
if (!features.encryptionEnabled) {