diff --git a/src/main/java/eu/siacs/conversations/utils/Resolver.java b/src/main/java/eu/siacs/conversations/utils/Resolver.java index df13be22c..eba1652cc 100644 --- a/src/main/java/eu/siacs/conversations/utils/Resolver.java +++ b/src/main/java/eu/siacs/conversations/utils/Resolver.java @@ -68,7 +68,21 @@ public class Resolver { } } + public static List fromHardCoded(String hostname, int port) { + Result result = new Result(); + result.hostname = DNSName.from(hostname); + result.port = port; + result.directTls = port == 443 || port == 5223; + result.authenticated = true; + return Collections.singletonList(result); + } + + public static List resolve(String domain) { + final List ipResults = fromIpAddress(domain); + if (ipResults.size() > 0) { + return ipResults; + } final List results = new ArrayList<>(); final List fallbackResults = new ArrayList<>(); Thread[] threads = new Thread[3]; @@ -120,13 +134,27 @@ public class Resolver { } } } catch (InterruptedException e) { - for(Thread thread : threads) { + for (Thread thread : threads) { thread.interrupt(); } return Collections.emptyList(); } } + private static List fromIpAddress(String domain) { + if (!IP.matches(domain)) { + return Collections.emptyList(); + } + try { + Result result = new Result(); + result.ip = InetAddress.getByName(domain); + result.port = 5222; + return Collections.singletonList(result); + } catch (UnknownHostException e) { + return Collections.emptyList(); + } + } + private static List resolveSrv(String domain, final boolean directTls) throws IOException { DNSName dnsName = DNSName.from((directTls ? DIRECT_TLS_SERVICE : STARTTLS_SERICE) + "._tcp." + domain); ResolverResult result = resolveWithFallback(dnsName, SRV.class); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index 299a37aa4..867375ef4 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -277,60 +277,15 @@ public class XmppConnection implements Runnable { } catch (Exception e) { throw new IOException(e.getMessage()); } - } else if (extended && !account.getHostname().isEmpty()) { - - this.verifiedHostname = account.getHostname(); - - try { - InetSocketAddress address = new InetSocketAddress(this.verifiedHostname, account.getPort()); - features.encryptionEnabled = address.getPort() == 5223; - if (features.encryptionEnabled) { - try { - final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier(); - localSocket = tlsFactoryVerifier.factory.createSocket(); - localSocket.connect(address, Config.SOCKET_TIMEOUT * 1000); - final SSLSession session = ((SSLSocket) localSocket).getSession(); - final String domain = account.getJid().getDomain(); - if (!tlsFactoryVerifier.verifier.verify(domain, this.verifiedHostname, session)) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed"); - throw new StateChangingException(Account.State.TLS_ERROR); - } - } catch (KeyManagementException e) { - throw new StateChangingException(Account.State.TLS_ERROR); - } - } else { - localSocket = new Socket(); - localSocket.connect(address, Config.SOCKET_TIMEOUT * 1000); - } - } catch (IOException | IllegalArgumentException e) { - throw new UnknownHostException(); - } - try { - startXmpp(localSocket); - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream"); - return; - } catch (Exception e) { - throw new IOException(e.getMessage()); - } - } else if (IP.matches(account.getServer())) { - localSocket = new Socket(); - try { - localSocket.connect(new InetSocketAddress(account.getServer(), 5222), Config.SOCKET_TIMEOUT * 1000); - } catch (IOException e) { - throw new UnknownHostException(); - } - try { - startXmpp(localSocket); - } catch (InterruptedException e) { - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream"); - return; - } catch (Exception e) { - throw new IOException(e.getMessage()); - } } else { final String domain = account.getJid().getDomain(); - final List results = Resolver.resolve(account.getJid().getDomain()); + final List results; + final boolean hardcoded = extended && !account.getHostname().isEmpty(); + if (hardcoded) { + results = Resolver.fromHardCoded(account.getHostname(), account.getPort()); + } else { + results = Resolver.resolve(domain); + } if (Thread.currentThread().isInterrupted()) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted"); return; @@ -339,10 +294,15 @@ public class XmppConnection implements Runnable { Log.e(Config.LOGTAG,account.getJid().asBareJid()+": Resolver results were empty"); return; } - final Resolver.Result storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain); - if (storedBackupResult != null && !results.contains(storedBackupResult)) { - results.add(storedBackupResult); - Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult); + final Resolver.Result storedBackupResult; + if (hardcoded) { + storedBackupResult = null; + } else { + storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain); + if (storedBackupResult != null && !results.contains(storedBackupResult)) { + results.add(storedBackupResult); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult); + } } for (Iterator iterator = results.iterator(); iterator.hasNext(); ) { final Resolver.Result result = iterator.next(); @@ -354,16 +314,17 @@ public class XmppConnection implements Runnable { // if tls is true, encryption is implied and must not be started features.encryptionEnabled = result.isDirectTls(); verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null; + Log.d(Config.LOGTAG,"verified hostname "+verifiedHostname); final InetSocketAddress addr; if (result.getIp() != null) { addr = new InetSocketAddress(result.getIp(), result.getPort()); Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() - + ": using values from dns " + result.getHostname().toString() - + "/" + result.getIp().getHostAddress() + ":" + result.getPort() + " tls: " + features.encryptionEnabled); + + ": using values from resolver " + (result.getHostname() == null ? "" : result.getHostname().toString() + + "/") + result.getIp().getHostAddress() + ":" + result.getPort() + " tls: " + features.encryptionEnabled); } else { addr = new InetSocketAddress(IDN.toASCII(result.getHostname().toString()), result.getPort()); Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() - + ": using values from dns " + + ": using values from resolver " + result.getHostname().toString() + ":" + result.getPort() + " tls: " + features.encryptionEnabled); } @@ -424,7 +385,7 @@ public class XmppConnection implements Runnable { this.changeStatus(Account.State.SERVER_NOT_FOUND); } catch (final SocksSocketFactory.SocksProxyNotFoundException e) { this.changeStatus(Account.State.TOR_NOT_AVAILABLE); - } catch (final IOException | XmlPullParserException | NoSuchAlgorithmException e) { + } catch (final IOException | XmlPullParserException e) { Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage()); this.changeStatus(Account.State.OFFLINE); this.attempt = Math.max(0, this.attempt - 1);