provide extra 'network is unreachable' account state

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Account.java    |  5 
src/main/java/eu/siacs/conversations/utils/Resolver.java      | 33 ++++
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java |  3 
src/main/res/values/strings.xml                               |  1 
4 files changed, 37 insertions(+), 5 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Account.java 🔗

@@ -132,7 +132,8 @@ public class Account extends AbstractEntity {
 		POLICY_VIOLATION(true),
 		REGISTRATION_PASSWORD_TOO_WEAK(true),
 		PAYMENT_REQUIRED(true),
-		MISSING_INTERNET_PERMISSION(true);
+		MISSING_INTERNET_PERMISSION(true),
+		NETWORK_IS_UNREACHABLE(false);
 
 		private final boolean isError;
 
@@ -200,6 +201,8 @@ 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;
 			}

src/main/java/eu/siacs/conversations/utils/Resolver.java 🔗

@@ -9,6 +9,7 @@ import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 
 import de.measite.minidns.DNSClient;
@@ -23,6 +24,7 @@ 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 eu.siacs.conversations.Config;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.services.XmppConnectionService;
@@ -32,6 +34,8 @@ 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;
 
 
@@ -44,19 +48,27 @@ public class Resolver {
         DNSClient.addDnsServerLookupMechanism(new AndroidUsingLinkProperties(context));
     }
 
-    public static List<Result> resolve(String domain) {
+    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));
+            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);
         }
         try {
-            results.addAll(resolveSrv(domain,false));
+            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));
         }
         Collections.sort(results);
@@ -64,6 +76,18 @@ public class Resolver {
         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));
+            } else {
+                messages.add(inner.getMessage());
+            }
+        }
+        return messages;
+    }
+
     private static List<Result> resolveSrv(String domain, final boolean directTls) throws IOException {
         if (Thread.currentThread().isInterrupted()) {
             return Collections.emptyList();
@@ -239,5 +263,8 @@ public class Resolver {
             return createDefault(hostname,null);
         }
     }
+    public static class NetworkIsUnreachableException extends Exception {
+
+    }
 
 }

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -16,7 +16,6 @@ import org.xmlpull.v1.XmlPullParserException;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.math.BigInteger;
 import java.net.ConnectException;
 import java.net.IDN;
 import java.net.InetAddress;
@@ -420,6 +419,8 @@ 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) {

src/main/res/values/strings.xml 🔗

@@ -759,4 +759,5 @@
 	<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>
 </resources>