aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/pixart/messenger/xmpp/XmppConnection.java')
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/XmppConnection.java108
1 files changed, 40 insertions, 68 deletions
diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
index cbfdbc365..73cfbab86 100644
--- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
+++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java
@@ -48,7 +48,6 @@ import java.util.regex.Matcher;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509KeyManager;
@@ -77,7 +76,6 @@ import de.pixart.messenger.services.NotificationService;
import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.ui.EditAccountActivity;
import de.pixart.messenger.utils.CryptoHelper;
-import de.pixart.messenger.utils.IP;
import de.pixart.messenger.utils.Namespace;
import de.pixart.messenger.utils.Patterns;
import de.pixart.messenger.utils.Resolver;
@@ -210,7 +208,7 @@ public class XmppConnection implements Runnable {
}
}
- protected void changeStatus(final Account.State nextStatus) {
+ private void changeStatus(final Account.State nextStatus) {
synchronized (this) {
if (Thread.currentThread().isInterrupted()) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": not changing status to " + nextStatus + " because thread was interrupted");
@@ -304,69 +302,32 @@ 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();
+ } else {
+ final String domain = account.getJid().getDomain();
+ final List<Resolver.Result> results;
+ final boolean hardcoded = extended && !account.getHostname().isEmpty();
+ if (hardcoded) {
+ results = Resolver.fromHardCoded(account.getHostname(), account.getPort());
+ } else {
+ results = Resolver.resolve(domain);
}
- try {
- startXmpp(localSocket);
- } catch (InterruptedException e) {
- Log.d(Config.LOGTAG,account.getJid().asBareJid()+": thread was interrupted before beginning stream");
+ if (Thread.currentThread().isInterrupted()) {
+ Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
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");
+ if (results.size() == 0) {
+ Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": Resolver results were empty");
return;
- } catch (Exception e) {
- throw new IOException(e.getMessage());
}
- } else {
- final String domain = account.getJid().getDomain();
- List<Resolver.Result> results = Resolver.resolve(account.getJid().getDomain());
- Resolver.Result storedBackupResult;
- if (!Thread.currentThread().isInterrupted()) {
+ 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);
}
- } else {
- storedBackupResult = null;
}
for (Iterator<Resolver.Result> iterator = results.iterator(); iterator.hasNext(); ) {
final Resolver.Result result = iterator.next();
@@ -378,16 +339,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);
}
@@ -403,8 +365,8 @@ public class XmppConnection implements Runnable {
}
SSLSocketHelper.setSecurity((SSLSocket) localSocket);
- SSLSocketHelper.setSNIHost(tlsFactoryVerifier.factory, (SSLSocket) localSocket, account.getServer());
- SSLSocketHelper.setAlpnProtocol(tlsFactoryVerifier.factory, (SSLSocket) localSocket, "xmpp-client");
+ SSLSocketHelper.setHostname((SSLSocket) localSocket, account.getServer());
+ SSLSocketHelper.setApplicationProtocol((SSLSocket) localSocket, "xmpp-client");
localSocket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
@@ -415,14 +377,18 @@ public class XmppConnection implements Runnable {
}
}
}
-
+ localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
if (startXmpp(localSocket)) {
- if (!result.equals(storedBackupResult)) {
+ 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);
}
break; // successfully connected to server that speaks xmpp
} else {
localSocket.close();
+ if (!iterator.hasNext()) {
+ throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
+ }
}
} catch (final StateChangingException e) {
throw e;
@@ -446,7 +412,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);
@@ -482,6 +448,9 @@ public class XmppConnection implements Runnable {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
+ if (socket instanceof SSLSocket) {
+ SSLSocketHelper.log(account, (SSLSocket) socket);
+ }
return tag != null && tag.isStart("stream");
}
@@ -524,7 +493,7 @@ public class XmppConnection implements Runnable {
} else if (nextTag.isStart("features")) {
processStreamFeatures(nextTag);
} else if (nextTag.isStart("proceed")) {
- switchOverToTls(nextTag);
+ switchOverToTls();
} else if (nextTag.isStart("success")) {
final String challenge = tagReader.readElement(nextTag).getContent();
try {
@@ -542,7 +511,7 @@ public class XmppConnection implements Runnable {
if (tag != null && tag.isStart("stream")) {
processStream();
} else {
- throw new IOException("server didn't restart stream after successful auth");
+ throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
}
break;
} else if (nextTag.isStart("failure")) {
@@ -852,7 +821,7 @@ public class XmppConnection implements Runnable {
tagWriter.writeTag(startTLS);
}
- private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException {
+ private void switchOverToTls() throws XmlPullParserException, IOException {
tagReader.readTag();
try {
final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
@@ -869,6 +838,8 @@ public class XmppConnection implements Runnable {
}
SSLSocketHelper.setSecurity(sslSocket);
+ SSLSocketHelper.setHostname(sslSocket, account.getServer());
+ SSLSocketHelper.setApplicationProtocol(sslSocket, "xmpp-client");
if (!tlsFactoryVerifier.verifier.verify(account.getServer(), this.verifiedHostname, sslSocket.getSession())) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate verification failed");
@@ -881,9 +852,10 @@ public class XmppConnection implements Runnable {
features.encryptionEnabled = true;
final Tag tag = tagReader.readTag();
if (tag != null && tag.isStart("stream")) {
+ SSLSocketHelper.log(account, sslSocket);
processStream();
} else {
- throw new IOException("server didn't restart stream after STARTTLS");
+ throw new StateChangingException(Account.State.STREAM_OPENING_ERROR);
}
sslSocket.close();
} catch (final NoSuchAlgorithmException | KeyManagementException e1) {