aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main/java/de/pixart/messenger/entities/Account.java5
-rw-r--r--src/main/java/de/pixart/messenger/services/XmppConnectionService.java4
-rw-r--r--src/main/java/de/pixart/messenger/utils/Resolver.java248
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java2
-rw-r--r--src/main/res/values/strings.xml1
5 files changed, 148 insertions, 112 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Account.java b/src/main/java/de/pixart/messenger/entities/Account.java
index 46d036419..6fd4c1c05 100644
--- a/src/main/java/de/pixart/messenger/entities/Account.java
+++ b/src/main/java/de/pixart/messenger/entities/Account.java
@@ -139,8 +139,7 @@ public class Account extends AbstractEntity {
STREAM_ERROR,
POLICY_VIOLATION,
PAYMENT_REQUIRED,
- MISSING_INTERNET_PERMISSION(false),
- NETWORK_IS_UNREACHABLE(false);
+ MISSING_INTERNET_PERMISSION(false);
private final boolean isError;
private final boolean attemptReconnect;
@@ -218,8 +217,6 @@ public class Account extends AbstractEntity {
return R.string.payment_required;
case MISSING_INTERNET_PERMISSION:
return R.string.missing_internet_permission;
- case NETWORK_IS_UNREACHABLE:
- return R.string.network_is_unreachable;
default:
return R.string.account_status_unknown;
}
diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
index 6b957a603..b6d23668c 100644
--- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
+++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java
@@ -4216,7 +4216,7 @@ public class XmppConnectionService extends Service {
ServiceDiscoveryResult discoveryResult = new ServiceDiscoveryResult(response);
if (presence.getVer().equals(discoveryResult.getVer())) {
databaseBackend.insertDiscoveryResult(discoveryResult);
- injectServiceDiscorveryResult(a.getRoster(), presence.getHash(), presence.getVer(), discoveryResult);
+ injectServiceDiscoveryResult(a.getRoster(), presence.getHash(), presence.getVer(), discoveryResult);
} else {
Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": mismatch in caps for contact " + jid + " " + presence.getVer() + " vs " + discoveryResult.getVer());
}
@@ -4227,7 +4227,7 @@ public class XmppConnectionService extends Service {
}
}
- private void injectServiceDiscorveryResult(Roster roster, String hash, String ver, ServiceDiscoveryResult disco) {
+ private void injectServiceDiscoveryResult(Roster roster, String hash, String ver, ServiceDiscoveryResult disco) {
for (Contact contact : roster.getContacts()) {
for (Presence presence : contact.getPresences().getPresences().values()) {
if (hash.equals(presence.getHash()) && ver.equals(presence.getVer())) {
diff --git a/src/main/java/de/pixart/messenger/utils/Resolver.java b/src/main/java/de/pixart/messenger/utils/Resolver.java
index 8f8138cb3..4bae6fae7 100644
--- a/src/main/java/de/pixart/messenger/utils/Resolver.java
+++ b/src/main/java/de/pixart/messenger/utils/Resolver.java
@@ -6,14 +6,15 @@ import android.support.annotation.NonNull;
import android.util.Log;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
+import de.measite.minidns.AbstractDNSClient;
import de.measite.minidns.DNSClient;
import de.measite.minidns.DNSName;
import de.measite.minidns.Question;
@@ -23,13 +24,13 @@ import de.measite.minidns.dnsserverlookup.AndroidUsingExec;
import de.measite.minidns.hla.DnssecResolverApi;
import de.measite.minidns.hla.ResolverApi;
import de.measite.minidns.hla.ResolverResult;
+import de.measite.minidns.iterative.ReliableDNSClient;
import de.measite.minidns.record.A;
import de.measite.minidns.record.AAAA;
import de.measite.minidns.record.CNAME;
import de.measite.minidns.record.Data;
import de.measite.minidns.record.InternetAddressRR;
import de.measite.minidns.record.SRV;
-import de.measite.minidns.util.MultipleIoException;
import de.pixart.messenger.Config;
import de.pixart.messenger.R;
import de.pixart.messenger.services.XmppConnectionService;
@@ -39,8 +40,6 @@ public class Resolver {
private static final String DIRECT_TLS_SERVICE = "_xmpps-client";
private static final String STARTTLS_SERICE = "_xmpp-client";
- private static final String NETWORK_IS_UNREACHABLE = "Network is unreachable";
-
private static XmppConnectionService SERVICE = null;
@@ -49,74 +48,122 @@ public class Resolver {
DNSClient.removeDNSServerLookupMechanism(AndroidUsingExec.INSTANCE);
DNSClient.addDnsServerLookupMechanism(AndroidUsingExecLowPriority.INSTANCE);
DNSClient.addDnsServerLookupMechanism(new AndroidUsingLinkProperties(service));
+ final AbstractDNSClient client = ResolverApi.INSTANCE.getClient();
+ if (client instanceof ReliableDNSClient) {
+ disableHardcodedDnsServers((ReliableDNSClient) client);
+ }
}
- public static List<Result> resolve(String domain) throws NetworkIsUnreachableException {
- List<Result> results = new ArrayList<>();
- HashSet<String> messages = new HashSet<>();
- try {
- results.addAll(resolveSrv(domain, true));
- } catch (MultipleIoException e) {
- messages.addAll(extractMessages(e));
- } catch (Throwable throwable) {
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (direct TLS)", throwable);
- }
+ private static void disableHardcodedDnsServers(ReliableDNSClient reliableDNSClient) {
try {
- results.addAll(resolveSrv(domain, false));
- } catch (MultipleIoException e) {
- messages.addAll(extractMessages(e));
- } catch (Throwable throwable) {
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (STARTTLS)", throwable);
- }
- if (results.size() == 0) {
- if (messages.size() == 1 && messages.contains(NETWORK_IS_UNREACHABLE)) {
- throw new NetworkIsUnreachableException();
- }
- results.addAll(resolveNoSrvRecords(DNSName.from(domain), true));
+ final Field dnsClientField = ReliableDNSClient.class.getDeclaredField("dnsClient");
+ dnsClientField.setAccessible(true);
+ final DNSClient dnsClient = (DNSClient) dnsClientField.get(reliableDNSClient);
+ dnsClient.getDataSource().setTimeout(3000);
+ final Field useHardcodedDnsServers = DNSClient.class.getDeclaredField("useHardcodedDnsServers");
+ useHardcodedDnsServers.setAccessible(true);
+ useHardcodedDnsServers.setBoolean(dnsClient, false);
+ } catch (NoSuchFieldException e) {
+ Log.e(Config.LOGTAG, "Unable to disable hardcoded DNS servers", e);
+ } catch (IllegalAccessException e) {
+ Log.e(Config.LOGTAG, "Unable to disable hardcoded DNS servers", e);
}
- Collections.sort(results);
- Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + results.toString());
- return results;
}
- private static HashSet<String> extractMessages(MultipleIoException e) {
- HashSet<String> messages = new HashSet<>();
- for (Exception inner : e.getExceptions()) {
- if (inner instanceof MultipleIoException) {
- messages.addAll(extractMessages((MultipleIoException) inner));
+ public static List<Result> resolve(String domain) {
+ final List<Result> results = new ArrayList<>();
+ final List<Result> fallbackResults = new ArrayList<>();
+ Thread[] threads = new Thread[3];
+ threads[0] = new Thread(() -> {
+ try {
+ final List<Result> list = resolveSrv(domain, true);
+ synchronized (results) {
+ results.addAll(list);
+ }
+ } catch (Throwable throwable) {
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (direct TLS)", throwable);
+ }
+ });
+ threads[1] = new Thread(() -> {
+ try {
+ final List<Result> list = resolveSrv(domain, false);
+ synchronized (results) {
+ results.addAll(list);
+ }
+ } catch (Throwable throwable) {
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": error resolving SRV record (STARTTLS)", throwable);
+ }
+ });
+ threads[2] = new Thread(() -> {
+ List<Result> list = resolveNoSrvRecords(DNSName.from(domain), true);
+ synchronized (fallbackResults) {
+ fallbackResults.addAll(list);
+ }
+ });
+ for (Thread thread : threads) {
+ thread.start();
+ }
+ try {
+ threads[0].join();
+ threads[1].join();
+ if (results.size() > 0) {
+ threads[2].interrupt();
+ Collections.sort(results);
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + results.toString());
+ return results;
} else {
- messages.add(inner.getMessage());
+ threads[2].join();
+ Collections.sort(fallbackResults);
+ Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": " + fallbackResults.toString());
+ return fallbackResults;
}
+ } catch (InterruptedException e) {
+ return results;
}
- return messages;
}
private static List<Result> resolveSrv(String domain, final boolean directTls) throws IOException {
- if (Thread.currentThread().isInterrupted()) {
- return Collections.emptyList();
- }
DNSName dnsName = DNSName.from((directTls ? DIRECT_TLS_SERVICE : STARTTLS_SERICE) + "._tcp." + domain);
ResolverResult<SRV> result = resolveWithFallback(dnsName, SRV.class);
- List<Result> results = new ArrayList<>();
+ final List<Result> results = new ArrayList<>();
+ final List<Thread> threads = new ArrayList<>();
for (SRV record : result.getAnswersOrEmptySet()) {
if (record.name.length() == 0 && record.priority == 0) {
continue;
}
- final boolean addedIPv4 = results.addAll(resolveIp(record, A.class, result.isAuthenticData(), directTls));
- results.addAll(resolveIp(record, AAAA.class, result.isAuthenticData(), directTls));
- if (!addedIPv4 && !Thread.currentThread().isInterrupted()) {
- Result resolverResult = Result.fromRecord(record, directTls);
- resolverResult.authenticated = resolverResult.isAuthenticated();
- results.add(resolverResult);
+ threads.add(new Thread(() -> {
+ final List<Result> ipv4s = resolveIp(record, A.class, result.isAuthenticData(), directTls);
+ if (ipv4s.size() == 0) {
+ Result resolverResult = Result.fromRecord(record, directTls);
+ resolverResult.authenticated = resolverResult.isAuthenticated();
+ ipv4s.add(resolverResult);
+ }
+ synchronized (results) {
+ results.addAll(ipv4s);
+ }
+
+ }));
+ threads.add(new Thread(() -> {
+ final List<Result> ipv6s = resolveIp(record, AAAA.class, result.isAuthenticData(), directTls);
+ synchronized (results) {
+ results.addAll(ipv6s);
+ }
+ }));
+ }
+ for (Thread thread : threads) {
+ thread.start();
+ }
+ for (Thread thread : threads) {
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ return Collections.emptyList();
}
}
return results;
}
private static <D extends InternetAddressRR> List<Result> resolveIp(SRV srv, Class<D> type, boolean authenticated, boolean directTls) {
- if (Thread.currentThread().isInterrupted()) {
- return Collections.emptyList();
- }
List<Result> list = new ArrayList<>();
try {
ResolverResult<D> results = resolveWithFallback(srv.name, type, authenticated);
@@ -179,6 +226,56 @@ public class Resolver {
}
public static class Result implements Comparable<Result> {
+ public static final String DOMAIN = "domain";
+ public static final String IP = "ip";
+ public static final String HOSTNAME = "hostname";
+ public static final String PORT = "port";
+ public static final String PRIORITY = "priority";
+ public static final String DIRECT_TLS = "directTls";
+ public static final String AUTHENTICATED = "authenticated";
+ private InetAddress ip;
+ private DNSName hostname;
+ private int port = 5222;
+ private boolean directTls = false;
+ private boolean authenticated = false;
+ private int priority;
+
+ 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;
+ }
+
+ static Result createDefault(DNSName hostname, InetAddress ip) {
+ Result result = new Result();
+ result.port = 5222;
+ result.hostname = hostname;
+ result.ip = ip;
+ return result;
+ }
+
+ static Result createDefault(DNSName hostname) {
+ return createDefault(hostname, null);
+ }
+
+ public static Result fromCursor(Cursor cursor) {
+ final Result result = new Result();
+ try {
+ result.ip = InetAddress.getByAddress(cursor.getBlob(cursor.getColumnIndex(IP)));
+ } catch (UnknownHostException e) {
+ result.ip = null;
+ }
+ result.hostname = DNSName.from(cursor.getString(cursor.getColumnIndex(HOSTNAME)));
+ result.port = cursor.getInt(cursor.getColumnIndex(PORT));
+ result.priority = cursor.getInt(cursor.getColumnIndex(PRIORITY));
+ result.authenticated = cursor.getInt(cursor.getColumnIndex(AUTHENTICATED)) > 0;
+ result.directTls = cursor.getInt(cursor.getColumnIndex(DIRECT_TLS)) > 0;
+ return result;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -205,22 +302,6 @@ public class Resolver {
return result;
}
- public static final String DOMAIN = "domain";
-
- public static final String IP = "ip";
- public static final String HOSTNAME = "hostname";
- public static final String PORT = "port";
- public static final String PRIORITY = "priority";
- public static final String DIRECT_TLS = "directTls";
- public static final String AUTHENTICATED = "authenticated";
-
- 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;
}
@@ -276,42 +357,6 @@ public class Resolver {
}
}
- 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(DNSName hostname, InetAddress ip) {
- Result result = new Result();
- result.port = 5222;
- result.hostname = hostname;
- result.ip = ip;
- return result;
- }
-
- public static Result createDefault(DNSName hostname) {
- return createDefault(hostname, null);
- }
-
- public static Result fromCursor(Cursor cursor) {
- final Result result = new Result();
- try {
- result.ip = InetAddress.getByAddress(cursor.getBlob(cursor.getColumnIndex(IP)));
- } catch (UnknownHostException e) {
- result.ip = null;
- }
- result.hostname = DNSName.from(cursor.getString(cursor.getColumnIndex(HOSTNAME)));
- result.port = cursor.getInt(cursor.getColumnIndex(PORT));
- result.priority = cursor.getInt(cursor.getColumnIndex(PRIORITY));
- result.authenticated = cursor.getInt(cursor.getColumnIndex(AUTHENTICATED)) > 0;
- result.directTls = cursor.getInt(cursor.getColumnIndex(DIRECT_TLS)) > 0;
- return result;
- }
-
public ContentValues toContentValues() {
final ContentValues contentValues = new ContentValues();
contentValues.put(IP, ip == null ? null : ip.getAddress());
@@ -324,7 +369,4 @@ public class Resolver {
}
}
- public static class NetworkIsUnreachableException extends Exception {
-
- }
} \ 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 1def41694..cbfdbc365 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -442,8 +442,6 @@ public class XmppConnection implements Runnable {
this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION);
} catch (final StateChangingException e) {
this.changeStatus(e.state);
- } catch (final Resolver.NetworkIsUnreachableException e) {
- this.changeStatus(Account.State.NETWORK_IS_UNREACHABLE);
} catch (final UnknownHostException | ConnectException e) {
this.changeStatus(Account.State.SERVER_NOT_FOUND);
} catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 43794ee03..26a8a7112 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -699,7 +699,6 @@
<string name="yesterday">Yesterday</string>
<string name="pref_validate_hostname">Validate hostname with DNSSEC</string>
<string name="pref_validate_hostname_summary">Server certificates that contain the validated hostname are considered verified</string>
- <string name="network_is_unreachable">Network is unreachable</string>
<string name="certificate_does_not_contain_jid">Certificate does not contain a Jabber ID</string>
<string name="error_no_keys_to_trust_presence">There are no usable keys available for this contact.\nMake sure you have mutual presence subscription.</string>
<string name="mark_as_read">Mark as read</string>