diff options
author | Daniel Gultsch <daniel@gultsch.de> | 2014-03-10 19:22:13 +0100 |
---|---|---|
committer | Daniel Gultsch <daniel@gultsch.de> | 2014-03-11 02:53:10 +0100 |
commit | 08023210ba875f3cd088eca2b4b3df7410966344 (patch) | |
tree | 4cfbbe21353559664ccbc4c5ffb7e33cb8e6ea4a /src/eu/siacs/conversations/xmpp | |
parent | e441005c8768091e9e975f3d5f797fab8466861b (diff) |
basic stream managment functionality
Diffstat (limited to 'src/eu/siacs/conversations/xmpp')
13 files changed, 215 insertions, 70 deletions
diff --git a/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java b/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java index 54909f88..a4cff986 100644 --- a/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java +++ b/src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.stanzas.IqPacket; public interface OnIqPacketReceived extends PacketReceived { public void onIqPacketReceived(Account account, IqPacket packet); diff --git a/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java b/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java index 6f0b387d..325e945f 100644 --- a/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java +++ b/src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.stanzas.MessagePacket; public interface OnMessagePacketReceived extends PacketReceived { public void onMessagePacketReceived(Account account, MessagePacket packet); diff --git a/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java b/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java index 55672fff..95c1acfc 100644 --- a/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java +++ b/src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.xmpp; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.xmpp.stanzas.PresencePacket; public interface OnPresencePacketReceived extends PacketReceived { public void onPresencePacketReceived(Account account, PresencePacket packet); diff --git a/src/eu/siacs/conversations/xmpp/PresencePacket.java b/src/eu/siacs/conversations/xmpp/PresencePacket.java deleted file mode 100644 index 3d77ce15..00000000 --- a/src/eu/siacs/conversations/xmpp/PresencePacket.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.siacs.conversations.xmpp; - -import eu.siacs.conversations.xml.Element; - -public class PresencePacket extends Element { - private PresencePacket(String name) { - super("presence"); - } - - public PresencePacket() { - super("presence"); - } -} diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java index 53f9b85a..2ffe21fb 100644 --- a/src/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java @@ -26,8 +26,10 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; +import org.json.JSONException; import org.xmlpull.v1.XmlPullParserException; +import android.content.IntentSender.SendIntentException; import android.os.Bundle; import android.os.PowerManager; import android.util.Log; @@ -38,6 +40,14 @@ import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Tag; import eu.siacs.conversations.xml.TagWriter; import eu.siacs.conversations.xml.XmlReader; +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.streammgmt.AckPacket; +import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket; +import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket; +import eu.siacs.conversations.xmpp.stanzas.streammgmt.ResumePacket; public class XmppConnection implements Runnable { @@ -56,6 +66,11 @@ public class XmppConnection implements Runnable { private boolean shouldAuthenticate = true; private Element streamFeatures; private HashSet<String> discoFeatures = new HashSet<String>(); + + private String streamId = null; + + private int stanzasReceived = 0; + private int stanzasSent = 0; private static final int PACKET_IQ = 0; private static final int PACKET_MESSAGE = 1; @@ -176,6 +191,34 @@ public class XmppConnection implements Runnable { } else if (nextTag.isStart("failure")) { Element failure = tagReader.readElement(nextTag); changeStatus(Account.STATUS_UNAUTHORIZED); + } else if (nextTag.isStart("enabled")) { + this.stanzasSent = 0; + Element enabled = tagReader.readElement(nextTag); + if ("true".equals(enabled.getAttribute("resume"))) { + this.streamId = enabled.getAttribute("id"); + Log.d(LOGTAG,account.getJid()+": stream managment enabled (resumable)"); + } else { + Log.d(LOGTAG,account.getJid()+": stream managment enabled"); + } + this.stanzasReceived = 0; + RequestPacket r = new RequestPacket(); + tagWriter.writeStanzaAsync(r); + } else if (nextTag.isStart("resumed")) { + tagReader.readElement(nextTag); + changeStatus(Account.STATUS_ONLINE); + Log.d(LOGTAG,account.getJid()+": session resumed"); + } else if (nextTag.isStart("r")) { + tagReader.readElement(nextTag); + AckPacket ack = new AckPacket(this.stanzasReceived); + //Log.d(LOGTAG,ack.toString()); + tagWriter.writeStanzaAsync(ack); + } else if (nextTag.isStart("a")) { + Element ack = tagReader.readElement(nextTag); + int serverSequence = Integer.parseInt(ack.getAttribute("h")); + if (serverSequence>this.stanzasSent) { + this.stanzasSent = serverSequence; + } + //Log.d(LOGTAG,"server ack"+ack.toString()+" ("+this.stanzasSent+")"); } else if (nextTag.isStart("iq")) { processIq(nextTag); } else if (nextTag.isStart("message")) { @@ -221,6 +264,7 @@ public class XmppConnection implements Runnable { } nextTag = tagReader.readTag(); } + ++stanzasReceived; return element; } @@ -271,7 +315,7 @@ public class XmppConnection implements Runnable { } } - private void sendStartTLS() { + private void sendStartTLS() throws IOException { Tag startTLS = Tag.empty("starttls"); startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls"); tagWriter.writeTag(startTLS); @@ -378,23 +422,43 @@ public class XmppConnection implements Runnable { } else if (this.streamFeatures.hasChild("mechanisms") && shouldAuthenticate) { sendSaslAuth(); - } - if (this.streamFeatures.hasChild("bind") && shouldBind) { + } else if (this.streamFeatures.hasChild("sm") && streamId != null) { + Log.d(LOGTAG,"found old stream id. trying to remuse"); + ResumePacket resume = new ResumePacket(this.streamId,stanzasReceived); + this.tagWriter.writeStanzaAsync(resume); + } else if (this.streamFeatures.hasChild("bind") && shouldBind) { sendBindRequest(); if (this.streamFeatures.hasChild("session")) { + Log.d(LOGTAG,"sending session"); IqPacket startSession = new IqPacket(IqPacket.TYPE_SET); Element session = new Element("session"); session.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-session"); session.setContent(""); startSession.addChild(session); - sendIqPacket(startSession, null); - tagWriter.writeElement(startSession); + this.sendIqPacket(startSession, null); } - Element presence = new Element("presence"); + } + } - tagWriter.writeElement(presence); + private void sendInitialPresence() { + PresencePacket packet = new PresencePacket(); + packet.setAttribute("from", account.getFullJid()); + if (account.getKeys().has("pgp_signature")) { + try { + String signature = account.getKeys().getString("pgp_signature"); + Element status = new Element("status"); + status.setContent("online"); + packet.addChild(status); + Element x = new Element("x"); + x.setAttribute("xmlns", "jabber:x:signed"); + x.setContent(signature); + packet.addChild(x); + } catch (JSONException e) { + // + } } + this.sendPresencePacket(packet); } private void sendBindRequest() throws IOException { @@ -412,10 +476,15 @@ public class XmppConnection implements Runnable { .getContent().split("/")[1]; account.setResource(resource); account.setStatus(Account.STATUS_ONLINE); + if (streamFeatures.hasChild("sm")) { + EnablePacket enable = new EnablePacket(); + tagWriter.writeStanzaAsync(enable); + } + sendInitialPresence(); + sendServiceDiscovery(); if (statusListener != null) { statusListener.onStatusChanged(account); } - sendServiceDiscovery(); } }); } @@ -471,7 +540,7 @@ public class XmppConnection implements Runnable { Log.d(LOGTAG, "processStreamError"); } - private void sendStartStream() { + private void sendStartStream() throws IOException { Tag stream = Tag.start("stream:stream"); stream.setAttribute("from", account.getJid()); stream.setAttribute("to", account.getServer()); @@ -489,39 +558,36 @@ public class XmppConnection implements Runnable { public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) { String id = nextRandomId(); packet.setAttribute("id", id); - tagWriter.writeElement(packet); - if (callback != null) { - packetCallbacks.put(id, callback); - } + this.sendPacket(packet, callback); } public void sendMessagePacket(MessagePacket packet) { - this.sendMessagePacket(packet, null); + this.sendPacket(packet, null); } public void sendMessagePacket(MessagePacket packet, OnMessagePacketReceived callback) { - String id = nextRandomId(); - packet.setAttribute("id", id); - tagWriter.writeElement(packet); - if (callback != null) { - packetCallbacks.put(id, callback); - } + this.sendPacket(packet, callback); } public void sendPresencePacket(PresencePacket packet) { - this.sendPresencePacket(packet, null); + this.sendPacket(packet, null); } - public PresencePacket sendPresencePacket(PresencePacket packet, + public void sendPresencePacket(PresencePacket packet, OnPresencePacketReceived callback) { - String id = nextRandomId(); - packet.setAttribute("id", id); - tagWriter.writeElement(packet); + this.sendPacket(packet, callback); + } + + private synchronized void sendPacket(final AbstractStanza packet, PacketReceived callback) { + ++stanzasSent; + tagWriter.writeStanzaAsync(packet); if (callback != null) { - packetCallbacks.put(id, callback); + if (packet.getId()==null) { + packet.setId(nextRandomId()); + } + packetCallbacks.put(packet.getId(), callback); } - return packet; } public void setOnMessagePacketReceivedListener( @@ -547,8 +613,23 @@ public class XmppConnection implements Runnable { this.tlsListener = listener; } - public void disconnect() { + public void disconnect(boolean force) { + Log.d(LOGTAG,"disconnecting"); + try { + if (force) { + socket.close(); + } + tagWriter.finish(); + while(!tagWriter.finished()) { + Log.d(LOGTAG,"not yet finished"); + Thread.sleep(100); + } tagWriter.writeTag(Tag.end("stream:stream")); + } catch (IOException e) { + Log.d(LOGTAG,"io exception during disconnect"); + } catch (InterruptedException e) { + Log.d(LOGTAG,"interupted while waiting for disconnect"); + } } public boolean hasFeatureRosterManagment() { @@ -558,4 +639,8 @@ public class XmppConnection implements Runnable { return this.streamFeatures.hasChild("ver"); } } + + public void r() { + this.tagWriter.writeStanzaAsync(new RequestPacket()); + } } diff --git a/src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java b/src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java new file mode 100644 index 00000000..204a6bec --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java @@ -0,0 +1,34 @@ +package eu.siacs.conversations.xmpp.stanzas; + +import eu.siacs.conversations.xml.Element; + +public class AbstractStanza extends Element { + + protected AbstractStanza(String name) { + super(name); + } + + public String getTo() { + return getAttribute("to"); + } + + public String getFrom() { + return getAttribute("from"); + } + + public String getId() { + return this.getAttribute("id"); + } + + public void setTo(String to) { + setAttribute("to", to); + } + + public void setFrom(String from) { + setAttribute("from",from); + } + + public void setId(String id) { + setAttribute("id",id); + } +} diff --git a/src/eu/siacs/conversations/xmpp/IqPacket.java b/src/eu/siacs/conversations/xmpp/stanzas/IqPacket.java index 2319fd28..1675d19d 100644 --- a/src/eu/siacs/conversations/xmpp/IqPacket.java +++ b/src/eu/siacs/conversations/xmpp/stanzas/IqPacket.java @@ -1,8 +1,7 @@ -package eu.siacs.conversations.xmpp; +package eu.siacs.conversations.xmpp.stanzas; -import eu.siacs.conversations.xml.Element; -public class IqPacket extends Element { +public class IqPacket extends AbstractStanza { public static final int TYPE_SET = 0; public static final int TYPE_RESULT = 1; @@ -33,8 +32,4 @@ public class IqPacket extends Element { super("iq"); } - public String getId() { - return this.getAttribute("id"); - } - } diff --git a/src/eu/siacs/conversations/xmpp/MessagePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java index a014155f..f31a78e6 100644 --- a/src/eu/siacs/conversations/xmpp/MessagePacket.java +++ b/src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java @@ -1,30 +1,18 @@ -package eu.siacs.conversations.xmpp; +package eu.siacs.conversations.xmpp.stanzas; import eu.siacs.conversations.xml.Element; -public class MessagePacket extends Element { +public class MessagePacket extends AbstractStanza { public static final int TYPE_CHAT = 0; public static final int TYPE_UNKNOWN = 1; public static final int TYPE_NO = 2; public static final int TYPE_GROUPCHAT = 3; public static final int TYPE_ERROR = 4; - - private MessagePacket(String name) { - super(name); - } public MessagePacket() { super("message"); } - public String getTo() { - return getAttribute("to"); - } - - public String getFrom() { - return getAttribute("from"); - } - public String getBody() { Element body = this.findChild("body"); if (body!=null) { @@ -34,14 +22,6 @@ public class MessagePacket extends Element { } } - public void setTo(String to) { - setAttribute("to", to); - } - - public void setFrom(String from) { - setAttribute("from",from); - } - public void setBody(String text) { this.children.remove(findChild("body")); Element body = new Element("body"); diff --git a/src/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java new file mode 100644 index 00000000..dfbab78c --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java @@ -0,0 +1,9 @@ +package eu.siacs.conversations.xmpp.stanzas; + + +public class PresencePacket extends AbstractStanza { + + public PresencePacket() { + super("presence"); + } +} diff --git a/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java new file mode 100644 index 00000000..7bc66e9b --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java @@ -0,0 +1,13 @@ +package eu.siacs.conversations.xmpp.stanzas.streammgmt; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class AckPacket extends AbstractStanza { + + public AckPacket(int sequence) { + super("a"); + this.setAttribute("xmlns","urn:xmpp:sm:3"); + this.setAttribute("h", ""+sequence); + } + +} diff --git a/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java new file mode 100644 index 00000000..ae6a513a --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java @@ -0,0 +1,13 @@ +package eu.siacs.conversations.xmpp.stanzas.streammgmt; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class EnablePacket extends AbstractStanza { + + public EnablePacket() { + super("enable"); + this.setAttribute("xmlns","urn:xmpp:sm:3"); + this.setAttribute("resume", "true"); + } + +} diff --git a/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java new file mode 100644 index 00000000..4d409fd2 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java @@ -0,0 +1,12 @@ +package eu.siacs.conversations.xmpp.stanzas.streammgmt; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class RequestPacket extends AbstractStanza { + + public RequestPacket() { + super("r"); + this.setAttribute("xmlns","urn:xmpp:sm:3"); + } + +} diff --git a/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java new file mode 100644 index 00000000..bebfa1a2 --- /dev/null +++ b/src/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java @@ -0,0 +1,14 @@ +package eu.siacs.conversations.xmpp.stanzas.streammgmt; + +import eu.siacs.conversations.xmpp.stanzas.AbstractStanza; + +public class ResumePacket extends AbstractStanza { + + public ResumePacket(String id, int sequence) { + super("resume"); + this.setAttribute("xmlns","urn:xmpp:sm:3"); + this.setAttribute("previd", id); + this.setAttribute("h", ""+sequence); + } + +} |