aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-08 23:15:55 +0200
committerDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-08 23:15:55 +0200
commit298c7adcd1fabccb06d14905041cb7e008f109ad (patch)
treec4378136a4130854c94f1c55ffe3aab0aab6e0e0 /src/eu
parent92dcf857014bfec919d62a7c0457093bd9056d94 (diff)
disocover stream hosts (xep-0065) cleaned up disco
Diffstat (limited to 'src/eu')
-rw-r--r--src/eu/siacs/conversations/services/JingleConnectionManager.java50
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java5
-rw-r--r--src/eu/siacs/conversations/xmpp/PacketReceived.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java94
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java (renamed from src/eu/siacs/conversations/xmpp/JingleConnection.java)57
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java93
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java (renamed from src/eu/siacs/conversations/xmpp/OnJinglePacketReceived.java)5
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/OnPrimaryCanditateFound.java7
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java (renamed from src/eu/siacs/conversations/xmpp/stanzas/jingle/Content.java)2
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java (renamed from src/eu/siacs/conversations/xmpp/stanzas/jingle/JinglePacket.java)2
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java (renamed from src/eu/siacs/conversations/xmpp/stanzas/jingle/Reason.java)2
11 files changed, 211 insertions, 108 deletions
diff --git a/src/eu/siacs/conversations/services/JingleConnectionManager.java b/src/eu/siacs/conversations/services/JingleConnectionManager.java
deleted file mode 100644
index f2ca927a..00000000
--- a/src/eu/siacs/conversations/services/JingleConnectionManager.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package eu.siacs.conversations.services;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.JingleConnection;
-import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
-
-public class JingleConnectionManager {
-
- private XmppConnectionService xmppConnectionService;
-
- private ConcurrentHashMap<String, JingleConnection> connections = new ConcurrentHashMap<String, JingleConnection>();
-
- public JingleConnectionManager(XmppConnectionService service) {
- this.xmppConnectionService = service;
- }
-
- public void deliverPacket(Account account, JinglePacket packet) {
- String id = generateInternalId(account.getJid(), packet.getFrom(), packet.getSessionId());
- }
-
- public JingleConnection createNewConnection(Message message) {
- Account account = message.getConversation().getAccount();
- JingleConnection connection = new JingleConnection(this,account, message.getCounterpart());
- String id = generateInternalId(account.getJid(), message.getCounterpart(), connection.getSessionId());
- connection.init(message);
- return connection;
- }
-
- private String generateInternalId(String account, String counterpart, String sid) {
- return account+"#"+counterpart+"#"+sid;
-
- }
-
- public XmppConnectionService getXmppConnectionService() {
- return this.xmppConnectionService;
- }
-
- public Element getPrimaryCanditate(String jid) {
- Element canditate = new Element("canditate");
- canditate.setAttribute("cid","122");
- canditate.setAttribute("port","1234");
- canditate.setAttribute("jid", jid);
- canditate.setAttribute("type", "assisted");
- return canditate;
- }
-}
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index e601d9b9..f5b19d53 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -41,16 +41,17 @@ import eu.siacs.conversations.utils.UIHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnBindListener;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
-import eu.siacs.conversations.xmpp.OnJinglePacketReceived;
import eu.siacs.conversations.xmpp.OnMessagePacketReceived;
import eu.siacs.conversations.xmpp.OnPresencePacketReceived;
import eu.siacs.conversations.xmpp.OnStatusChanged;
import eu.siacs.conversations.xmpp.OnTLSExceptionReceived;
import eu.siacs.conversations.xmpp.XmppConnection;
+import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
+import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived;
+import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
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.jingle.JinglePacket;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
diff --git a/src/eu/siacs/conversations/xmpp/PacketReceived.java b/src/eu/siacs/conversations/xmpp/PacketReceived.java
index d9f42459..d4502d73 100644
--- a/src/eu/siacs/conversations/xmpp/PacketReceived.java
+++ b/src/eu/siacs/conversations/xmpp/PacketReceived.java
@@ -1,5 +1,5 @@
package eu.siacs.conversations.xmpp;
-abstract interface PacketReceived {
+public abstract interface PacketReceived {
}
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index 1ca7cd8b..c7bda9ca 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -16,9 +16,13 @@ import java.security.cert.CertPathValidatorException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
@@ -44,11 +48,12 @@ 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.jingle.OnJinglePacketReceived;
+import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
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.jingle.JinglePacket;
import eu.siacs.conversations.xmpp.stanzas.streammgmt.AckPacket;
import eu.siacs.conversations.xmpp.stanzas.streammgmt.EnablePacket;
import eu.siacs.conversations.xmpp.stanzas.streammgmt.RequestPacket;
@@ -70,8 +75,7 @@ public class XmppConnection implements Runnable {
private boolean shouldBind = true;
private boolean shouldAuthenticate = true;
private Element streamFeatures;
- private HashSet<String> discoFeatures = new HashSet<String>();
- private List<String> discoItems = new ArrayList<String>();
+ private HashMap<String, List<String>> disco = new HashMap<String, List<String>>();
private String streamId = null;
private int smVersion = 3;
@@ -644,8 +648,8 @@ public class XmppConnection implements Runnable {
tagWriter.writeStanzaAsync(enable);
}
sendInitialPresence();
- sendServiceDiscoveryInfo();
- sendServiceDiscoveryItems();
+ sendServiceDiscoveryInfo(account.getServer());
+ sendServiceDiscoveryItems(account.getServer());
if (bindListener !=null) {
bindListener.onBind(account);
}
@@ -654,42 +658,54 @@ public class XmppConnection implements Runnable {
});
}
- private void sendServiceDiscoveryInfo() {
+ private void sendServiceDiscoveryInfo(final String server) {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
- iq.setTo(account.getServer());
+ iq.setTo(server);
iq.query("http://jabber.org/protocol/disco#info");
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
- List<Element> elements = packet.query().getChildren();
- for (int i = 0; i < elements.size(); ++i) {
- if (elements.get(i).getName().equals("feature")) {
- discoFeatures.add(elements.get(i).getAttribute(
- "var"));
- }
+ List<Element> elements = packet.query().getChildren();
+ List<String> features = new ArrayList<String>();
+ for (int i = 0; i < elements.size(); ++i) {
+ if (elements.get(i).getName().equals("feature")) {
+ features.add(elements.get(i).getAttribute(
+ "var"));
}
- if (discoFeatures.contains("urn:xmpp:carbons:2")) {
- sendEnableCarbons();
+ }
+ Log.d(LOGTAG,"put "+server+" "+features.toString());
+ disco.put(server, features);
+
+ if (account.getServer().equals(server)) {
+ enableAdvancedStreamFeatures();
}
}
});
}
- private void sendServiceDiscoveryItems() {
+
+ private void enableAdvancedStreamFeatures() {
+ if (hasFeaturesCarbon()) {
+ sendEnableCarbons();
+ }
+ }
+
+ private void sendServiceDiscoveryItems(final String server) {
IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
- iq.setTo(account.getServer());
+ iq.setTo(server);
iq.query("http://jabber.org/protocol/disco#items");
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
- List<Element> elements = packet.query().getChildren();
- for (int i = 0; i < elements.size(); ++i) {
- if (elements.get(i).getName().equals("item")) {
- discoItems.add(elements.get(i).getAttribute(
- "jid"));
- }
+ List<Element> elements = packet.query().getChildren();
+ for (int i = 0; i < elements.size(); ++i) {
+ if (elements.get(i).getName().equals("item")) {
+ String jid = elements.get(i).getAttribute(
+ "jid");
+ sendServiceDiscoveryInfo(jid);
}
+ }
}
});
}
@@ -850,7 +866,26 @@ public class XmppConnection implements Runnable {
}
public boolean hasFeaturesCarbon() {
- return discoFeatures.contains("urn:xmpp:carbons:2");
+ return hasDiscoFeature(account.getServer(), "urn:xmpp:carbons:2");
+ }
+
+ public boolean hasDiscoFeature(String server, String feature) {
+ if (!disco.containsKey(server)) {
+ return false;
+ }
+ return disco.get(server).contains(feature);
+ }
+
+ public String findDiscoItemByFeature(String feature) {
+ Iterator<Entry<String, List<String>>> it = this.disco.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, List<String>> pairs = it.next();
+ if (pairs.getValue().contains(feature)) {
+ return pairs.getKey();
+ }
+ it.remove();
+ }
+ return null;
}
public void r() {
@@ -866,15 +901,6 @@ public class XmppConnection implements Runnable {
}
public String getMucServer() {
- for(int i = 0; i < discoItems.size(); ++i) {
- if (discoItems.get(i).contains("conference.")) {
- return discoItems.get(i);
- } else if (discoItems.get(i).contains("conf.")) {
- return discoItems.get(i);
- } else if (discoItems.get(i).contains("muc.")) {
- return discoItems.get(i);
- }
- }
- return null;
+ return findDiscoItemByFeature("http://jabber.org/protocol/muc");
}
}
diff --git a/src/eu/siacs/conversations/xmpp/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index 34587a93..60ba0291 100644
--- a/src/eu/siacs/conversations/xmpp/JingleConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -1,7 +1,5 @@
-package eu.siacs.conversations.xmpp;
+package eu.siacs.conversations.xmpp.jingle;
-import java.math.BigInteger;
-import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
@@ -9,30 +7,37 @@ import android.util.Log;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.services.JingleConnectionManager;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element;
-import eu.siacs.conversations.xmpp.stanzas.jingle.Content;
-import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
+import eu.siacs.conversations.xmpp.OnIqPacketReceived;
+import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
+import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JingleConnection {
private JingleConnectionManager mJingleConnectionManager;
private XmppConnectionService mXmppConnectionService;
+ private Message message;
private String sessionId;
private Account account;
- private String counterpart;
+ private String initiator;
+ private String responder;
private List<Element> canditates = new ArrayList<Element>();
- public JingleConnection(JingleConnectionManager mJingleConnectionManager, Account account, String counterpart) {
+ private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
+
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Log.d("xmppService",packet.toString());
+ }
+ };
+
+ public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
this.mJingleConnectionManager = mJingleConnectionManager;
this.mXmppConnectionService = mJingleConnectionManager.getXmppConnectionService();
- this.account = account;
- this.counterpart = counterpart;
- SecureRandom random = new SecureRandom();
- sessionId = new BigInteger(100, random).toString(32);
- this.canditates.add(this.mJingleConnectionManager.getPrimaryCanditate(account.getJid()));
+ this.sessionId = this.mJingleConnectionManager.nextRandomId();
}
public String getSessionId() {
@@ -40,26 +45,46 @@ public class JingleConnection {
}
public void init(Message message) {
+ this.message = message;
+ this.account = message.getConversation().getAccount();
+ this.initiator = this.account.getFullJid();
+ if (this.canditates.size() > 0) {
+ this.sendInitRequest();
+ } else {
+ this.mJingleConnectionManager.getPrimaryCanditate(account, new OnPrimaryCanditateFound() {
+
+ @Override
+ public void onPrimaryCanditateFound(boolean success, Element canditate) {
+ if (success) {
+ canditates.add(canditate);
+ }
+ sendInitRequest();
+ }
+ });
+ }
+
+ }
+
+ private void sendInitRequest() {
JinglePacket packet = this.bootstrapPacket();
packet.setAction("session-initiate");
packet.setInitiator(this.account.getFullJid());
Content content = new Content();
if (message.getType() == Message.TYPE_IMAGE) {
- //creator='initiator' name='a-file-offer'
content.setAttribute("creator", "initiator");
content.setAttribute("name", "a-file-offer");
content.offerFile(this.mXmppConnectionService.getFileBackend().getImageFile(message));
content.setCanditates(this.canditates);
packet.setContent(content);
Log.d("xmppService",packet.toString());
- account.getXmppConnection().sendIqPacket(packet, null);
+ account.getXmppConnection().sendIqPacket(packet, this.responseListener);
}
}
private JinglePacket bootstrapPacket() {
JinglePacket packet = new JinglePacket();
packet.setFrom(account.getFullJid());
- packet.setTo(this.counterpart+"/Gajim");
+ packet.setTo(this.message.getCounterpart()+"/Gajim"); //fixme, not right in all cases;
packet.setSessionId(this.sessionId);
return packet;
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
new file mode 100644
index 00000000..784d90d4
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
@@ -0,0 +1,93 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import android.util.Log;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.OnIqPacketReceived;
+import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+public class JingleConnectionManager {
+
+ private XmppConnectionService xmppConnectionService;
+
+ private List<JingleConnection> connections = new ArrayList<JingleConnection>(); //make concurrent
+
+ private ConcurrentHashMap<String, Element> primaryCanditates = new ConcurrentHashMap<String, Element>();
+
+ private SecureRandom random = new SecureRandom();
+
+ public JingleConnectionManager(XmppConnectionService service) {
+ this.xmppConnectionService = service;
+ }
+
+ public void deliverPacket(Account account, JinglePacket packet) {
+ String id = generateInternalId(account.getJid(), packet.getFrom(), packet.getSessionId());
+ }
+
+ public JingleConnection createNewConnection(Message message) {
+ Account account = message.getConversation().getAccount();
+ JingleConnection connection = new JingleConnection(this);
+ String id = generateInternalId(account.getJid(), message.getCounterpart(), connection.getSessionId());
+ connection.init(message);
+ return connection;
+ }
+
+ private String generateInternalId(String account, String counterpart, String sid) {
+ return account+"#"+counterpart+"#"+sid;
+
+ }
+
+ public XmppConnectionService getXmppConnectionService() {
+ return this.xmppConnectionService;
+ }
+
+ public void getPrimaryCanditate(Account account, final OnPrimaryCanditateFound listener) {
+ if (!this.primaryCanditates.containsKey(account.getJid())) {
+ String xmlns = "http://jabber.org/protocol/bytestreams";
+ String proxy = account.getXmppConnection().findDiscoItemByFeature(xmlns);
+ if (proxy!=null) {
+ IqPacket iq = new IqPacket(IqPacket.TYPE_GET);
+ iq.setTo(proxy);
+ iq.query(xmlns);
+ account.getXmppConnection().sendIqPacket(iq, new OnIqPacketReceived() {
+
+ @Override
+ public void onIqPacketReceived(Account account, IqPacket packet) {
+ Element streamhost = packet.query().findChild("streamhost","http://jabber.org/protocol/bytestreams");
+ if (streamhost!=null) {
+ Log.d("xmppService","streamhost found "+streamhost.toString());
+ Element canditate = new Element("canditate");
+ canditate.setAttribute("cid",nextRandomId());
+ canditate.setAttribute("host", streamhost.getAttribute("host"));
+ canditate.setAttribute("port",streamhost.getAttribute("port"));
+ canditate.setAttribute("type", "proxy");
+ primaryCanditates.put(account.getJid(), canditate);
+ listener.onPrimaryCanditateFound(true, canditate);
+ } else {
+ listener.onPrimaryCanditateFound(false, null);
+ }
+ }
+ });
+ } else {
+ listener.onPrimaryCanditateFound(false, null);
+ }
+
+ } else {
+ listener.onPrimaryCanditateFound(true, this.primaryCanditates.get(account.getJid()));
+ }
+ }
+
+ public String nextRandomId() {
+ return new BigInteger(50, random).toString(32);
+ }
+}
diff --git a/src/eu/siacs/conversations/xmpp/OnJinglePacketReceived.java b/src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
index 6705e309..2aaf62a1 100644
--- a/src/eu/siacs/conversations/xmpp/OnJinglePacketReceived.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
@@ -1,7 +1,8 @@
-package eu.siacs.conversations.xmpp;
+package eu.siacs.conversations.xmpp.jingle;
import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.xmpp.stanzas.jingle.JinglePacket;
+import eu.siacs.conversations.xmpp.PacketReceived;
+import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
public interface OnJinglePacketReceived extends PacketReceived {
public void onJinglePacketReceived(Account account, JinglePacket packet);
diff --git a/src/eu/siacs/conversations/xmpp/jingle/OnPrimaryCanditateFound.java b/src/eu/siacs/conversations/xmpp/jingle/OnPrimaryCanditateFound.java
new file mode 100644
index 00000000..25aab118
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/OnPrimaryCanditateFound.java
@@ -0,0 +1,7 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import eu.siacs.conversations.xml.Element;
+
+public interface OnPrimaryCanditateFound {
+ public void onPrimaryCanditateFound(boolean success, Element canditate);
+}
diff --git a/src/eu/siacs/conversations/xmpp/stanzas/jingle/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
index ed51a2a5..941e6559 100644
--- a/src/eu/siacs/conversations/xmpp/stanzas/jingle/Content.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
@@ -1,4 +1,4 @@
-package eu.siacs.conversations.xmpp.stanzas.jingle;
+package eu.siacs.conversations.xmpp.jingle.stanzas;
import java.io.File;
import java.util.List;
diff --git a/src/eu/siacs/conversations/xmpp/stanzas/jingle/JinglePacket.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
index 4c444a74..9cb2b448 100644
--- a/src/eu/siacs/conversations/xmpp/stanzas/jingle/JinglePacket.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
@@ -1,4 +1,4 @@
-package eu.siacs.conversations.xmpp.stanzas.jingle;
+package eu.siacs.conversations.xmpp.jingle.stanzas;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
diff --git a/src/eu/siacs/conversations/xmpp/stanzas/jingle/Reason.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
index 35b81655..195e0db7 100644
--- a/src/eu/siacs/conversations/xmpp/stanzas/jingle/Reason.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
@@ -1,4 +1,4 @@
-package eu.siacs.conversations.xmpp.stanzas.jingle;
+package eu.siacs.conversations.xmpp.jingle.stanzas;
import eu.siacs.conversations.xml.Element;