diff options
Diffstat (limited to 'src/eu/siacs/conversations/xmpp')
4 files changed, 91 insertions, 8 deletions
diff --git a/src/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java b/src/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java new file mode 100644 index 00000000..5f670d93 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/OnMessageAcknowledged.java @@ -0,0 +1,7 @@ +package eu.siacs.conversations.xmpp; + +import eu.siacs.conversations.entities.Account; + +public interface OnMessageAcknowledged { + public void onMessageAcknowledged(Account account, String id); +} diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index ba7a9245..932b16f2 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -31,6 +31,7 @@ import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.util.Log; +import android.util.SparseArray; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.utils.CryptoHelper; @@ -47,6 +48,8 @@ import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.PresencePacket; +import eu.siacs.conversations.xmpp.stanzas.csi.ActivePacket; +import eu.siacs.conversations.xmpp.stanzas.csi.InactivePacket; import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket; import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket; import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket; @@ -74,6 +77,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; @@ -98,6 +102,7 @@ public class XmppConnection implements Runnable { private OnMessagePacketReceived messageListener = null; private OnStatusChanged statusListener = null; private OnBindListener bindListener = null; + private OnMessageAcknowledged acknowledgedListener = null; private MemorizingTrustManager mMemorizingTrustManager; public XmppConnection(Account account, XmppConnectionService service) { @@ -248,7 +253,6 @@ public class XmppConnection implements Runnable { challange,mRandom)); tagWriter.writeElement(response); } else if (nextTag.isStart("enabled")) { - this.stanzasSent = 0; Element enabled = tagReader.readElement(nextTag); if ("true".equals(enabled.getAttribute("resume"))) { this.streamId = enabled.getAttribute("id"); @@ -264,9 +268,27 @@ public class XmppConnection implements Runnable { tagWriter.writeStanzaAsync(r); } else if (nextTag.isStart("resumed")) { lastPaketReceived = SystemClock.elapsedRealtime(); - Log.d(LOGTAG, account.getJid() + ": session resumed"); - tagReader.readElement(nextTag); - sendPing(); + Element resumed = tagReader.readElement(nextTag); + String h = resumed.getAttribute("h"); + try { + int serverCount = Integer.parseInt(h); + if (serverCount!=stanzasSent) { + Log.d(LOGTAG,account.getJid() + ": session resumed with lost packages"); + stanzasSent = serverCount; + } else { + Log.d(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)); + } + } + } + messageReceipts.clear(); + } catch (NumberFormatException e) { + + } changeStatus(Account.STATUS_ONLINE); } else if (nextTag.isStart("r")) { tagReader.readElement(nextTag); @@ -276,8 +298,12 @@ public class XmppConnection implements Runnable { Element ack = tagReader.readElement(nextTag); lastPaketReceived = SystemClock.elapsedRealtime(); int serverSequence = Integer.parseInt(ack.getAttribute("h")); - if (serverSequence > this.stanzasSent) { - this.stanzasSent = serverSequence; + String msgId = this.messageReceipts.get(serverSequence); + if (msgId != null) { + if (this.acknowledgedListener != null) { + this.acknowledgedListener.onMessageAcknowledged(account, msgId); + } + this.messageReceipts.remove(serverSequence); } } else if (nextTag.isStart("failed")) { tagReader.readElement(nextTag); @@ -610,10 +636,14 @@ public class XmppConnection implements Runnable { smVersion = 3; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); + stanzasSent = 0; + messageReceipts.clear(); } else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) { smVersion = 2; EnablePacket enable = new EnablePacket(smVersion); tagWriter.writeStanzaAsync(enable); + stanzasSent = 0; + messageReceipts.clear(); } sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryItems(account.getServer()); @@ -751,9 +781,15 @@ public class XmppConnection implements Runnable { private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) { - // TODO dont increment stanza count if packet = request packet or ack; - ++stanzasSent; + 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); + this.messageReceipts.put(stanzasSent, packet.getId()); + tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion)); + } if (callback != null) { if (packet.getId() == null) { packet.setId(nextRandomId()); @@ -801,6 +837,10 @@ 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); @@ -900,6 +940,14 @@ public class XmppConnection implements Runnable { } } + public boolean csi() { + if (connection.streamFeatures == null) { + return false; + } else { + return connection.streamFeatures.hasChild("csi","urn:xmpp:csi:0"); + } + } + public boolean pubsub() { return hasDiscoFeature(account.getServer(), "http://jabber.org/protocol/pubsub#publish"); } @@ -942,4 +990,12 @@ public class XmppConnection implements Runnable { public long getLastPacketReceived() { return this.lastPaketReceived; } + + public void sendActive() { + this.sendPacket(new ActivePacket(), null); + } + + public void sendInactive() { + this.sendPacket(new InactivePacket(), null); + } } diff --git a/src/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java new file mode 100644 index 00000000..78ab66d8 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java @@ -0,0 +1,10 @@ +package eu.siacs.conversations.xmpp.stanzas.csi; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class ActivePacket extends AbstractStanza { + public ActivePacket() { + super("active"); + setAttribute("xmlns", "urn:xmpp:csi:0"); + } +} diff --git a/src/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java new file mode 100644 index 00000000..f109280f --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java @@ -0,0 +1,10 @@ +package eu.siacs.conversations.xmpp.stanzas.csi; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class InactivePacket extends AbstractStanza { + public InactivePacket() { + super("inactive"); + setAttribute("xmlns", "urn:xmpp:csi:0"); + } +} |