diff options
Diffstat (limited to '')
-rw-r--r-- | src/eu/siacs/conversations/xmpp/XmppConnection.java | 204 |
1 files changed, 120 insertions, 84 deletions
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 932b16f2..ae6b6f72 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -32,6 +32,7 @@ import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.util.Log; import android.util.SparseArray; +import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; @@ -58,7 +59,6 @@ import eu.siacs.conversations.xmpp.stanzas.streammgmt.ResumePacket; public class XmppConnection implements Runnable { protected Account account; - private static final String LOGTAG = "xmppService"; private WakeLock wakeLock; @@ -67,7 +67,7 @@ public class XmppConnection implements Runnable { private Socket socket; private XmlReader tagReader; private TagWriter tagWriter; - + private Features features = new Features(this); private boolean shouldBind = true; @@ -78,7 +78,7 @@ public class XmppConnection implements Runnable { private String streamId = null; private int smVersion = 3; private SparseArray<String> messageReceipts = new SparseArray<String>(); - + private boolean usingCompression = false; private int stanzasReceived = 0; @@ -109,8 +109,8 @@ public class XmppConnection implements Runnable { this.mRandom = service.getRNG(); this.mMemorizingTrustManager = service.getMemorizingTrustManager(); this.account = account; - this.wakeLock = service.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, - account.getJid()); + this.wakeLock = service.getPowerManager().newWakeLock( + PowerManager.PARTIAL_WAKE_LOCK, account.getJid()); tagWriter = new TagWriter(); } @@ -133,7 +133,7 @@ public class XmppConnection implements Runnable { } protected void connect() { - Log.d(LOGTAG, account.getJid() + ": connecting"); + Log.d(Config.LOGTAG, account.getJid() + ": connecting"); usingCompression = false; lastConnect = SystemClock.elapsedRealtime(); lastPingSent = SystemClock.elapsedRealtime(); @@ -147,7 +147,7 @@ public class XmppConnection implements Runnable { this.changeStatus(Account.STATUS_CONNECTING); Bundle namePort = DNSHelper.getSRVRecord(account.getServer()); if ("timeout".equals(namePort.getString("error"))) { - Log.d(LOGTAG, account.getJid() + ": dns timeout"); + Log.d(Config.LOGTAG, account.getJid() + ": dns timeout"); this.changeStatus(Account.STATUS_OFFLINE); return; } @@ -156,13 +156,14 @@ public class XmppConnection implements Runnable { int srvRecordPort = namePort.getInt("port"); if (srvRecordServer != null) { if (srvIpServer != null) { - Log.d(LOGTAG, account.getJid() + ": using values from dns " - + srvRecordServer + "[" + srvIpServer + "]:" - + srvRecordPort); + Log.d(Config.LOGTAG, account.getJid() + + ": using values from dns " + srvRecordServer + + "[" + srvIpServer + "]:" + srvRecordPort); socket = new Socket(srvIpServer, srvRecordPort); } else { - Log.d(LOGTAG, account.getJid() + ": using values from dns " - + srvRecordServer + ":" + srvRecordPort); + Log.d(Config.LOGTAG, account.getJid() + + ": using values from dns " + srvRecordServer + + ":" + srvRecordPort); socket = new Socket(srvRecordServer, srvRecordPort); } } else { @@ -180,7 +181,8 @@ public class XmppConnection implements Runnable { processStream(nextTag); break; } else { - Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName()); + Log.d(Config.LOGTAG, + "found unexpected tag: " + nextTag.getName()); return; } } @@ -190,27 +192,39 @@ public class XmppConnection implements Runnable { } catch (UnknownHostException e) { this.changeStatus(Account.STATUS_SERVER_NOT_FOUND); if (wakeLock.isHeld()) { - try { wakeLock.release();} catch (RuntimeException re) {} + try { + wakeLock.release(); + } catch (RuntimeException re) { + } } return; } catch (IOException e) { this.changeStatus(Account.STATUS_OFFLINE); if (wakeLock.isHeld()) { - try { wakeLock.release();} catch (RuntimeException re) {} + try { + wakeLock.release(); + } catch (RuntimeException re) { + } } return; } catch (NoSuchAlgorithmException e) { this.changeStatus(Account.STATUS_OFFLINE); - Log.d(LOGTAG, "compression exception " + e.getMessage()); + Log.d(Config.LOGTAG, "compression exception " + e.getMessage()); if (wakeLock.isHeld()) { - try { wakeLock.release();} catch (RuntimeException re) {} + try { + wakeLock.release(); + } catch (RuntimeException re) { + } } return; } catch (XmlPullParserException e) { this.changeStatus(Account.STATUS_OFFLINE); - Log.d(LOGTAG, "xml exception " + e.getMessage()); + Log.d(Config.LOGTAG, "xml exception " + e.getMessage()); if (wakeLock.isHeld()) { - try { wakeLock.release();} catch (RuntimeException re) {} + try { + wakeLock.release(); + } catch (RuntimeException re) { + } } return; } @@ -235,7 +249,7 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("compressed")) { switchOverToZLib(nextTag); } else if (nextTag.isStart("success")) { - Log.d(LOGTAG, account.getJid() + ": logged in"); + Log.d(Config.LOGTAG, account.getJid() + ": logged in"); tagReader.readTag(); tagReader.reset(); sendStartStream(); @@ -250,17 +264,18 @@ public class XmppConnection implements Runnable { response.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-sasl"); response.setContent(CryptoHelper.saslDigestMd5(account, - challange,mRandom)); + challange, mRandom)); tagWriter.writeElement(response); } else if (nextTag.isStart("enabled")) { Element enabled = tagReader.readElement(nextTag); if ("true".equals(enabled.getAttribute("resume"))) { this.streamId = enabled.getAttribute("id"); - Log.d(LOGTAG, account.getJid() + ": stream managment(" - + smVersion + ") enabled (resumable)"); + Log.d(Config.LOGTAG, account.getJid() + + ": stream managment(" + smVersion + + ") enabled (resumable)"); } else { - Log.d(LOGTAG, account.getJid() + ": stream managment(" - + smVersion + ") enabled"); + Log.d(Config.LOGTAG, account.getJid() + + ": stream managment(" + smVersion + ") enabled"); } this.lastSessionStarted = SystemClock.elapsedRealtime(); this.stanzasReceived = 0; @@ -272,22 +287,25 @@ public class XmppConnection implements Runnable { String h = resumed.getAttribute("h"); try { int serverCount = Integer.parseInt(h); - if (serverCount!=stanzasSent) { - Log.d(LOGTAG,account.getJid() + ": session resumed with lost packages"); + if (serverCount != stanzasSent) { + Log.d(Config.LOGTAG, account.getJid() + + ": session resumed with lost packages"); stanzasSent = serverCount; } else { - Log.d(LOGTAG, account.getJid() + ": session resumed"); + Log.d(Config.LOGTAG, account.getJid() + + ": session resumed"); } - if (acknowledgedListener!=null) { - for(int i = 0; i < messageReceipts.size(); ++i) { - if (serverCount>=messageReceipts.keyAt(i)) { - acknowledgedListener.onMessageAcknowledged(account, messageReceipts.valueAt(i)); + if (acknowledgedListener != null) { + for (int i = 0; i < messageReceipts.size(); ++i) { + if (serverCount >= messageReceipts.keyAt(i)) { + acknowledgedListener.onMessageAcknowledged( + account, messageReceipts.valueAt(i)); } } } messageReceipts.clear(); } catch (NumberFormatException e) { - + } changeStatus(Account.STATUS_ONLINE); } else if (nextTag.isStart("r")) { @@ -301,13 +319,14 @@ public class XmppConnection implements Runnable { String msgId = this.messageReceipts.get(serverSequence); if (msgId != null) { if (this.acknowledgedListener != null) { - this.acknowledgedListener.onMessageAcknowledged(account, msgId); + this.acknowledgedListener.onMessageAcknowledged( + account, msgId); } this.messageReceipts.remove(serverSequence); } } else if (nextTag.isStart("failed")) { tagReader.readElement(nextTag); - Log.d(LOGTAG, account.getJid() + ": resumption failed"); + Log.d(Config.LOGTAG, account.getJid() + ": resumption failed"); streamId = null; if (account.getStatus() != Account.STATUS_ONLINE) { sendBindRequest(); @@ -347,7 +366,7 @@ public class XmppConnection implements Runnable { } element.setAttributes(currentTag.getAttributes()); Tag nextTag = tagReader.readTag(); - if (nextTag==null) { + if (nextTag == null) { throw new IOException("interrupted mid tag"); } while (!nextTag.isEnd(element.getName())) { @@ -361,7 +380,7 @@ public class XmppConnection implements Runnable { element.addChild(child); } nextTag = tagReader.readTag(); - if (nextTag==null) { + if (nextTag == null) { throw new IOException("interrupted mid tag"); } } @@ -446,7 +465,7 @@ public class XmppConnection implements Runnable { .setInputStream(new ZLibInputStream(tagReader.getInputStream())); sendStartStream(); - Log.d(LOGTAG, account.getJid() + ": compression enabled"); + Log.d(Config.LOGTAG, account.getJid() + ": compression enabled"); usingCompression = true; processStream(tagReader.readTag()); } @@ -462,23 +481,30 @@ public class XmppConnection implements Runnable { tagReader.readTag(); try { SSLContext sc = SSLContext.getInstance("TLS"); - sc.init(null, new X509TrustManager[] { this.mMemorizingTrustManager }, mRandom); + sc.init(null, + new X509TrustManager[] { this.mMemorizingTrustManager }, + mRandom); SSLSocketFactory factory = sc.getSocketFactory(); - - HostnameVerifier verifier = this.mMemorizingTrustManager.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()); + + HostnameVerifier verifier = this.mMemorizingTrustManager + .wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()); SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket, socket.getInetAddress().getHostAddress(), socket.getPort(), true); - - if (verifier != null && !verifier.verify(account.getServer(), sslSocket.getSession())) { - Log.d(LOGTAG, account.getJid() + ": host mismatch in TLS connection"); + + if (verifier != null + && !verifier.verify(account.getServer(), + sslSocket.getSession())) { + Log.d(Config.LOGTAG, account.getJid() + + ": host mismatch in TLS connection"); sslSocket.close(); throw new IOException(); } tagReader.setInputStream(sslSocket.getInputStream()); tagWriter.setOutputStream(sslSocket.getOutputStream()); sendStartStream(); - Log.d(LOGTAG, account.getJid() + ": TLS connection established"); + Log.d(Config.LOGTAG, account.getJid() + + ": TLS connection established"); processStream(tagReader.readTag()); sslSocket.close(); } catch (NoSuchAlgorithmException e1) { @@ -604,7 +630,7 @@ public class XmppConnection implements Runnable { changeStatus(Account.STATUS_REGISTRATION_CONFLICT); } else { changeStatus(Account.STATUS_REGISTRATION_FAILED); - Log.d(LOGTAG, packet.toString()); + Log.d(Config.LOGTAG, packet.toString()); } disconnect(true); } @@ -612,7 +638,7 @@ public class XmppConnection implements Runnable { } else { changeStatus(Account.STATUS_REGISTRATION_FAILED); disconnect(true); - Log.d(LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid() + ": could not register. instructions are" + instructions.getContent()); } @@ -628,9 +654,9 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { Element bind = packet.findChild("bind"); - if (bind!=null) { + if (bind != null) { Element jid = bind.findChild("jid"); - if (jid!=null) { + if (jid != null) { account.setResource(jid.getContent().split("/")[1]); if (streamFeatures.hasChild("sm", "urn:xmpp:sm:3")) { smVersion = 3; @@ -638,7 +664,8 @@ public class XmppConnection implements Runnable { tagWriter.writeStanzaAsync(enable); stanzasSent = 0; messageReceipts.clear(); - } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { + } else if (streamFeatures.hasChild("sm", + "urn:xmpp:sm:2")) { smVersion = 2; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); @@ -660,7 +687,8 @@ public class XmppConnection implements Runnable { } }); if (this.streamFeatures.hasChild("session")) { - Log.d(LOGTAG, account.getJid() + ": sending deprecated session"); + Log.d(Config.LOGTAG, account.getJid() + + ": sending deprecated session"); IqPacket startSession = new IqPacket(IqPacket.TYPE_SET); startSession.addChild("session", "urn:ietf:params:xml:ns:xmpp-session"); @@ -725,10 +753,10 @@ public class XmppConnection implements Runnable { @Override public void onIqPacketReceived(Account account, IqPacket packet) { if (!packet.hasChild("error")) { - Log.d(LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid() + ": successfully enabled carbons"); } else { - Log.d(LOGTAG, account.getJid() + Log.d(Config.LOGTAG, account.getJid() + ": error enableing carbons " + packet.toString()); } } @@ -736,7 +764,7 @@ public class XmppConnection implements Runnable { } private void processStreamError(Tag currentTag) { - Log.d(LOGTAG, "processStreamError"); + Log.d(Config.LOGTAG, "processStreamError"); } private void sendStartStream() throws IOException { @@ -778,15 +806,18 @@ public class XmppConnection implements Runnable { public void sendPresencePacket(PresencePacket packet) { this.sendPacket(packet, null); } - + private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) { - if (packet.getName().equals("iq") || packet.getName().equals("message") || packet.getName().equals("presence")) { + if (packet.getName().equals("iq") || packet.getName().equals("message") + || packet.getName().equals("presence")) { ++stanzasSent; } tagWriter.writeStanzaAsync(packet); - if (packet instanceof MessagePacket && packet.getId() != null && this.streamId != null) { - Log.d(LOGTAG,"request delivery report for stanza "+stanzasSent); + if (packet instanceof MessagePacket && packet.getId() != null + && this.streamId != null) { + Log.d(Config.LOGTAG, "request delivery report for stanza " + + stanzasSent); this.messageReceipts.put(stanzasSent, packet.getId()); tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion)); } @@ -837,14 +868,14 @@ public class XmppConnection implements Runnable { public void setOnBindListener(OnBindListener listener) { this.bindListener = listener; } - + public void setOnMessageAcknowledgeListener(OnMessageAcknowledged listener) { this.acknowledgedListener = listener; } public void disconnect(boolean force) { changeStatus(Account.STATUS_OFFLINE); - Log.d(LOGTAG, "disconnecting"); + Log.d(Config.LOGTAG, "disconnecting"); try { if (force) { socket.close(); @@ -858,20 +889,21 @@ public class XmppConnection implements Runnable { tagWriter.finish(); try { while (!tagWriter.finished()) { - Log.d(LOGTAG, "not yet finished"); + Log.d(Config.LOGTAG, "not yet finished"); Thread.sleep(100); } tagWriter.writeTag(Tag.end("stream:stream")); } catch (IOException e) { - Log.d(LOGTAG, "io exception during disconnect"); + Log.d(Config.LOGTAG, + "io exception during disconnect"); } catch (InterruptedException e) { - Log.d(LOGTAG, "interrupted"); + Log.d(Config.LOGTAG, "interrupted"); } } } }).start(); } catch (IOException e) { - Log.d(LOGTAG, "io exception during disconnect"); + Log.d(Config.LOGTAG, "io exception during disconnect"); } } @@ -884,10 +916,10 @@ public class XmppConnection implements Runnable { } return items; } - + public String findDiscoItemByFeature(String feature) { List<String> items = findDiscoItemsByFeature(feature); - if (items.size()>=1) { + if (items.size() >= 1) { return items.get(0); } return null; @@ -896,7 +928,7 @@ public class XmppConnection implements Runnable { public void r() { this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion)); } - + public String getMucServer() { return findDiscoItemByFeature("http://jabber.org/protocol/muc"); } @@ -910,28 +942,29 @@ public class XmppConnection implements Runnable { public int getAttempt() { return this.attempt; } - + public Features getFeatures() { return this.features; } - + public class Features { XmppConnection connection; + public Features(XmppConnection connection) { this.connection = connection; } - + private boolean hasDiscoFeature(String server, String feature) { if (!connection.disco.containsKey(server)) { return false; } return connection.disco.get(server).contains(feature); } - + public boolean carbons() { return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2"); } - + public boolean sm() { if (connection.streamFeatures == null) { return false; @@ -939,19 +972,21 @@ public class XmppConnection implements Runnable { return connection.streamFeatures.hasChild("sm"); } } - + public boolean csi() { if (connection.streamFeatures == null) { return false; } else { - return connection.streamFeatures.hasChild("csi","urn:xmpp:csi:0"); + return connection.streamFeatures.hasChild("csi", + "urn:xmpp:csi:0"); } } - + public boolean pubsub() { - return hasDiscoFeature(account.getServer(), "http://jabber.org/protocol/pubsub#publish"); + return hasDiscoFeature(account.getServer(), + "http://jabber.org/protocol/pubsub#publish"); } - + public boolean rosterVersioning() { if (connection.streamFeatures == null) { return false; @@ -959,11 +994,12 @@ public class XmppConnection implements Runnable { return connection.streamFeatures.hasChild("ver"); } } - + public boolean streamhost() { - return connection.findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null; + return connection + .findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null; } - + public boolean compression() { return connection.usingCompression; } @@ -978,15 +1014,15 @@ public class XmppConnection implements Runnable { } return System.currentTimeMillis() - diff; } - + public long getLastConnect() { return this.lastConnect; } - + public long getLastPingSent() { return this.lastPingSent; } - + public long getLastPacketReceived() { return this.lastPaketReceived; } @@ -994,7 +1030,7 @@ public class XmppConnection implements Runnable { public void sendActive() { this.sendPacket(new ActivePacket(), null); } - + public void sendInactive() { this.sendPacket(new InactivePacket(), null); } |