more error handling in xmppconnection

This commit is contained in:
iNPUTmice 2014-11-03 10:03:45 +01:00
parent 1ea2e7dc3b
commit 27f42dfb63
1 changed files with 78 additions and 66 deletions

View File

@ -1,5 +1,19 @@
package eu.siacs.conversations.xmpp; package eu.siacs.conversations.xmpp;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseArray;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -22,31 +36,16 @@ import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import org.apache.http.conn.ssl.StrictHostnameVerifier;
import org.xmlpull.v1.XmlPullParserException;
import de.duenndns.ssl.MemorizingTrustManager; import de.duenndns.ssl.MemorizingTrustManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseArray;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.DNSHelper; import eu.siacs.conversations.utils.DNSHelper;
import eu.siacs.conversations.utils.zlib.ZLibOutputStream;
import eu.siacs.conversations.utils.zlib.ZLibInputStream; import eu.siacs.conversations.utils.zlib.ZLibInputStream;
import eu.siacs.conversations.utils.zlib.ZLibOutputStream;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Tag; import eu.siacs.conversations.xml.Tag;
import eu.siacs.conversations.xml.TagWriter; import eu.siacs.conversations.xml.TagWriter;
@ -164,38 +163,47 @@ public class XmppConnection implements Runnable {
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
return; return;
} else if (values != null) { } else if (values != null) {
int i = 0; int i = 0;
boolean socketError = true; boolean socketError = true;
while (socketError && values.size() > i) { while (socketError && values.size() > i) {
Bundle namePort = (Bundle) values.get(i); Bundle namePort = (Bundle) values.get(i);
try {
String srvRecordServer = namePort.getString("name");
int srvRecordPort = namePort.getInt("port");
String srvIpServer = namePort.getString("ipv4");
InetSocketAddress addr;
if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
}
socket = new Socket();
socket.connect(addr, 20000);
socketError = false;
} catch (UnknownHostException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
i++;
} catch (IOException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
i++;
}
}
if (socketError) {
this.changeStatus(Account.STATUS_SERVER_NOT_FOUND);
if (wakeLock.isHeld()) {
try { try {
String srvRecordServer = namePort.getString("name"); wakeLock.release();
int srvRecordPort = namePort.getInt("port"); } catch (RuntimeException re) {
String srvIpServer = namePort.getString("ipv4");
InetSocketAddress addr;
if (srvIpServer!=null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
}
socket = new Socket();
socket.connect(addr, 20000);
socketError = false;
} catch (UnknownHostException e) {
i++;
} catch (IOException e) {
i++;
} }
} }
if (socketError) { return;
throw new IOException(); }
}
} else if (result.containsKey("error") } else if (result.containsKey("error")
&& "nosrv".equals(result.getString("error", null))) { && "nosrv".equals(result.getString("error", null))) {
socket = new Socket(account.getServer(), 5222); socket = new Socket(account.getServer(), 5222);
@ -235,6 +243,7 @@ public class XmppConnection implements Runnable {
} }
return; return;
} catch (IOException e) { } catch (IOException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
@ -244,6 +253,7 @@ public class XmppConnection implements Runnable {
} }
return; return;
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
Log.d(Config.LOGTAG, "compression exception " + e.getMessage()); Log.d(Config.LOGTAG, "compression exception " + e.getMessage());
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
@ -254,8 +264,8 @@ public class XmppConnection implements Runnable {
} }
return; return;
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {
Log.d(Config.LOGTAG, account.getJid() + ": " + e.getMessage());
this.changeStatus(Account.STATUS_OFFLINE); this.changeStatus(Account.STATUS_OFFLINE);
Log.d(Config.LOGTAG, "xml exception " + e.getMessage());
if (wakeLock.isHeld()) { if (wakeLock.isHeld()) {
try { try {
wakeLock.release(); wakeLock.release();
@ -405,17 +415,17 @@ public class XmppConnection implements Runnable {
throws XmlPullParserException, IOException { throws XmlPullParserException, IOException {
Element element; Element element;
switch (packetType) { switch (packetType) {
case PACKET_IQ: case PACKET_IQ:
element = new IqPacket(); element = new IqPacket();
break; break;
case PACKET_MESSAGE: case PACKET_MESSAGE:
element = new MessagePacket(); element = new MessagePacket();
break; break;
case PACKET_PRESENCE: case PACKET_PRESENCE:
element = new PresencePacket(); element = new PresencePacket();
break; break;
default: default:
return null; return null;
} }
element.setAttributes(currentTag.getAttributes()); element.setAttributes(currentTag.getAttributes());
Tag nextTag = tagReader.readTag(); Tag nextTag = tagReader.readTag();
@ -429,7 +439,7 @@ public class XmppConnection implements Runnable {
if (packetType == PACKET_IQ if (packetType == PACKET_IQ
&& "jingle".equals(child.getName()) && "jingle".equals(child.getName())
&& ("set".equalsIgnoreCase(type) || "get" && ("set".equalsIgnoreCase(type) || "get"
.equalsIgnoreCase(type))) { .equalsIgnoreCase(type))) {
element = new JinglePacket(); element = new JinglePacket();
element.setAttributes(currentTag.getAttributes()); element.setAttributes(currentTag.getAttributes());
} }
@ -549,10 +559,14 @@ public class XmppConnection implements Runnable {
try { try {
SSLContext sc = SSLContext.getInstance("TLS"); SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, sc.init(null,
new X509TrustManager[] { this.mMemorizingTrustManager }, new X509TrustManager[]{this.mMemorizingTrustManager},
mRandom); mRandom);
SSLSocketFactory factory = sc.getSocketFactory(); SSLSocketFactory factory = sc.getSocketFactory();
if (factory == null) {
throw new IOException("SSLSocketFactory was null");
}
HostnameVerifier verifier = this.mMemorizingTrustManager HostnameVerifier verifier = this.mMemorizingTrustManager
.wrapHostnameVerifier(new StrictHostnameVerifier()); .wrapHostnameVerifier(new StrictHostnameVerifier());
SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,
@ -577,11 +591,9 @@ public class XmppConnection implements Runnable {
if (verifier != null if (verifier != null
&& !verifier.verify(account.getServer(), && !verifier.verify(account.getServer(),
sslSocket.getSession())) { sslSocket.getSession())) {
Log.d(Config.LOGTAG, account.getJid()
+ ": host mismatch in TLS connection");
sslSocket.close(); sslSocket.close();
throw new IOException(); throw new IOException("host mismatch in TLS connection");
} }
tagReader.setInputStream(sslSocket.getInputStream()); tagReader.setInputStream(sslSocket.getInputStream());
tagWriter.setOutputStream(sslSocket.getOutputStream()); tagWriter.setOutputStream(sslSocket.getOutputStream());
@ -707,14 +719,14 @@ public class XmppConnection implements Runnable {
@Override @Override
public void onIqPacketReceived(Account account, public void onIqPacketReceived(Account account,
IqPacket packet) { IqPacket packet) {
if (packet.getType() == IqPacket.TYPE_RESULT) { if (packet.getType() == IqPacket.TYPE_RESULT) {
account.setOption(Account.OPTION_REGISTER, account.setOption(Account.OPTION_REGISTER,
false); false);
changeStatus(Account.STATUS_REGISTRATION_SUCCESSFULL); changeStatus(Account.STATUS_REGISTRATION_SUCCESSFULL);
} else if (packet.hasChild("error") } else if (packet.hasChild("error")
&& (packet.findChild("error") && (packet.findChild("error")
.hasChild("conflict"))) { .hasChild("conflict"))) {
changeStatus(Account.STATUS_REGISTRATION_CONFLICT); changeStatus(Account.STATUS_REGISTRATION_CONFLICT);
} else { } else {
changeStatus(Account.STATUS_REGISTRATION_FAILED); changeStatus(Account.STATUS_REGISTRATION_FAILED);
@ -904,7 +916,7 @@ public class XmppConnection implements Runnable {
} }
private synchronized void sendPacket(final AbstractStanza packet, private synchronized void sendPacket(final AbstractStanza packet,
PacketReceived callback) { PacketReceived callback) {
if (packet.getName().equals("iq") || packet.getName().equals("message") if (packet.getName().equals("iq") || packet.getName().equals("message")
|| packet.getName().equals("presence")) { || packet.getName().equals("presence")) {
++stanzasSent; ++stanzasSent;