fix resolving IP if SRV violences RFC2782
This commit is contained in:
parent
e2c2ee6507
commit
fdfaae6f59
2 changed files with 69 additions and 25 deletions
|
@ -128,9 +128,13 @@ public class Resolver {
|
|||
}
|
||||
});
|
||||
threads[2] = new Thread(() -> {
|
||||
List<Result> list = resolveNoSrvRecords(DNSName.from(domain), DEFAULT_PORT_XMPP, true);
|
||||
synchronized (fallbackResults) {
|
||||
fallbackResults.addAll(list);
|
||||
try {
|
||||
final List<Result> list = resolveNoSrvRecords(DNSName.from(domain), DEFAULT_PORT_XMPP, true);
|
||||
synchronized (fallbackResults) {
|
||||
fallbackResults.addAll(list);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + ": resolving no SRV record (STARTTLS)", throwable);
|
||||
}
|
||||
});
|
||||
for (Thread thread : threads) {
|
||||
|
@ -187,7 +191,7 @@ public class Resolver {
|
|||
final List<Thread> fallbackThreads = new ArrayList<>();
|
||||
|
||||
for (SRV record : result.getAnswersOrEmptySet()) {
|
||||
if (record.name.length() == 0) {
|
||||
if (record.name.length() == 0 && record.priority == 0) {
|
||||
continue;
|
||||
}
|
||||
threads.add(new Thread(() -> {
|
||||
|
@ -198,6 +202,11 @@ public class Resolver {
|
|||
}));
|
||||
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 = result.isAuthenticData();
|
||||
ipv4s.add(resolverResult);
|
||||
}
|
||||
synchronized (results) {
|
||||
results.addAll(ipv4s);
|
||||
}
|
||||
|
@ -211,13 +220,13 @@ public class Resolver {
|
|||
fallbackResults.addAll(ipv6s);
|
||||
}
|
||||
final List<Result> ipv4s = resolveIp(record, cname.name, A.class, cnames.isAuthenticData(), directTls);
|
||||
synchronized (results) {
|
||||
synchronized (fallbackResults) {
|
||||
fallbackResults.addAll(ipv4s);
|
||||
}
|
||||
}
|
||||
Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "cname in srv (agains RFC2782) - run slow fallback");
|
||||
Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + " cname in srv (against RFC2782) - run slow fallback");
|
||||
} catch (Throwable throwable) {
|
||||
Log.i(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving srv cname-fallback records", throwable);
|
||||
Log.i(Config.LOGTAG, Resolver.class.getSimpleName() + " error resolving srv cname-fallback records", throwable);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -285,6 +294,7 @@ public class Resolver {
|
|||
} catch (Throwable throwable) {
|
||||
Log.d(Config.LOGTAG, Resolver.class.getSimpleName() + "error resolving fallback records", throwable);
|
||||
}
|
||||
results.add(Result.createDefault(dnsName, port));
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@ -315,7 +325,7 @@ public class Resolver {
|
|||
if (r.size() == 0) return null;
|
||||
|
||||
Result result;
|
||||
if (r.size() == 1) {
|
||||
if (r.size() == 1 && r.get(0).ip != null) {
|
||||
result = r.get(0);
|
||||
result.setLogID(logID);
|
||||
result.connect();
|
||||
|
@ -387,11 +397,27 @@ public class Resolver {
|
|||
result.timeRequested = System.currentTimeMillis();
|
||||
result.port = srv.port;
|
||||
result.hostname = srv.name;
|
||||
try {
|
||||
result.ip = InetAddress.getByName(result.hostname.toString());
|
||||
} catch (UnknownHostException e) {
|
||||
result.ip = null;
|
||||
e.printStackTrace();
|
||||
}
|
||||
result.directTls = directTls;
|
||||
result.priority = srv.priority;
|
||||
return result;
|
||||
}
|
||||
|
||||
static Result createDefault(final DNSName hostname, final int port) {
|
||||
InetAddress ip = null;
|
||||
try {
|
||||
ip = InetAddress.getByName(hostname.toString());
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return createDefault(hostname, ip, port);
|
||||
}
|
||||
|
||||
static Result createDefault(final DNSName hostname, final InetAddress ip, final int port) {
|
||||
Result result = new Result();
|
||||
result.timeRequested = System.currentTimeMillis();
|
||||
|
@ -464,6 +490,10 @@ public class Resolver {
|
|||
if (this.socket != null) {
|
||||
this.disconnect();
|
||||
}
|
||||
if (this.ip == null || this.port == 0) {
|
||||
Log.d(Config.LOGTAG, "Resolver did not get IP:port (" + this.ip + ":" + this.port + ")");
|
||||
return;
|
||||
}
|
||||
final InetSocketAddress addr = new InetSocketAddress(this.ip, this.port);
|
||||
this.socket = new Socket();
|
||||
try {
|
||||
|
|
|
@ -18,7 +18,6 @@ import java.io.ByteArrayInputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.IDN;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -317,20 +316,35 @@ public class XmppConnection implements Runnable {
|
|||
}
|
||||
} else {
|
||||
final String domain = account.getJid().getDomain();
|
||||
final Resolver.Result storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
|
||||
Resolver.Result result = null;
|
||||
Resolver.Result results;
|
||||
final boolean hardcoded = extended && !account.getHostname().isEmpty();
|
||||
if (hardcoded) {
|
||||
result = Resolver.fromHardCoded(account.getHostname(), account.getPort());
|
||||
} else if (storedBackupResult != null && !storedBackupResult.isOutdated()) {
|
||||
storedBackupResult.connect();
|
||||
result = storedBackupResult;
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
|
||||
results = Resolver.fromHardCoded(account.getHostname(), account.getPort());
|
||||
} else {
|
||||
results = Resolver.resolve(domain);
|
||||
}
|
||||
if (result == null || result.getSocket() == null) {
|
||||
result = Resolver.resolve(domain);
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
|
||||
return;
|
||||
}
|
||||
if (result == null) {
|
||||
if (results == null) {
|
||||
Log.e(Config.LOGTAG,account.getJid().asBareJid()+": Resolver results were empty");
|
||||
return;
|
||||
}
|
||||
final Resolver.Result storedBackupResult;
|
||||
if (hardcoded) {
|
||||
storedBackupResult = null;
|
||||
} else {
|
||||
storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
|
||||
if (storedBackupResult != null && results != storedBackupResult && !storedBackupResult.isOutdated()) {
|
||||
results = storedBackupResult;
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
|
||||
}
|
||||
}
|
||||
if (results == null || results.getSocket() == null) {
|
||||
results = Resolver.resolve(domain);
|
||||
}
|
||||
if (results == null) {
|
||||
throw new UnknownHostException();
|
||||
}
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
|
@ -339,13 +353,13 @@ public class XmppConnection implements Runnable {
|
|||
}
|
||||
try {
|
||||
// if tls is true, encryption is implied and must not be started
|
||||
features.encryptionEnabled = result.isDirectTls();
|
||||
verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null;
|
||||
features.encryptionEnabled = results.isDirectTls();
|
||||
verifiedHostname = results.isAuthenticated() ? results.getHostname().toString() : null;
|
||||
Log.d(Config.LOGTAG,"verified hostname " + verifiedHostname);
|
||||
Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
|
||||
+ ": using values from resolver " + result.toString());
|
||||
+ ": using values from resolver " + results.toString());
|
||||
|
||||
localSocket = result.getSocket();
|
||||
localSocket = results.getSocket();
|
||||
|
||||
if (features.encryptionEnabled) {
|
||||
localSocket = upgradeSocketToTls(localSocket);
|
||||
|
@ -354,8 +368,8 @@ public class XmppConnection implements Runnable {
|
|||
localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
|
||||
if (startXmpp(localSocket)) {
|
||||
localSocket.setSoTimeout(0); //reset to 0; once the connection is established we don’t want this
|
||||
if (!hardcoded && !result.equals(storedBackupResult)) {
|
||||
mXmppConnectionService.databaseBackend.saveResolverResult(domain, result);
|
||||
if (!hardcoded && !results.equals(storedBackupResult)) {
|
||||
mXmppConnectionService.databaseBackend.saveResolverResult(domain, results);
|
||||
}
|
||||
// successfully connected to server that speaks xmpp
|
||||
} else {
|
||||
|
|
Reference in a new issue