aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel@gultsch.de>2014-03-10 19:22:13 +0100
committerDaniel Gultsch <daniel@gultsch.de>2014-03-11 02:53:10 +0100
commit08023210ba875f3cd088eca2b4b3df7410966344 (patch)
tree4cfbbe21353559664ccbc4c5ffb7e33cb8e6ea4a /src/eu/siacs/conversations/xmpp
parente441005c8768091e9e975f3d5f797fab8466861b (diff)
basic stream managment functionality
Diffstat (limited to 'src/eu/siacs/conversations/xmpp')
-rw-r--r--src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java1
-rw-r--r--src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java1
-rw-r--r--src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java1
-rw-r--r--src/eu/siacs/conversations/xmpp/PresencePacket.java13
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java141
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/AbstractStanza.java34
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/IqPacket.java (renamed from src/eu/siacs/conversations/xmpp/IqPacket.java)9
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/MessagePacket.java (renamed from src/eu/siacs/conversations/xmpp/MessagePacket.java)24
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/PresencePacket.java9
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java13
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java13
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java12
-rw-r--r--src/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java14
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);
+ }
+
+}