aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp/jingle
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/siacs/conversations/xmpp/jingle
parent92dcf857014bfec919d62a7c0457093bd9056d94 (diff)
disocover stream hosts (xep-0065) cleaned up disco
Diffstat (limited to 'src/eu/siacs/conversations/xmpp/jingle')
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java92
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java93
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java9
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/OnPrimaryCanditateFound.java7
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java35
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java76
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java13
7 files changed, 325 insertions, 0 deletions
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
new file mode 100644
index 00000000..60ba0291
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -0,0 +1,92 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import java.util.ArrayList;
+import java.util.List;
+
+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.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 initiator;
+ private String responder;
+ private List<Element> canditates = new ArrayList<Element>();
+
+ 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.sessionId = this.mJingleConnectionManager.nextRandomId();
+ }
+
+ public String getSessionId() {
+ return this.sessionId;
+ }
+
+ 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) {
+ 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, this.responseListener);
+ }
+ }
+
+ private JinglePacket bootstrapPacket() {
+ JinglePacket packet = new JinglePacket();
+ packet.setFrom(account.getFullJid());
+ 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/jingle/OnJinglePacketReceived.java b/src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
new file mode 100644
index 00000000..2aaf62a1
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/OnJinglePacketReceived.java
@@ -0,0 +1,9 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import eu.siacs.conversations.entities.Account;
+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/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
new file mode 100644
index 00000000..941e6559
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
@@ -0,0 +1,35 @@
+package eu.siacs.conversations.xmpp.jingle.stanzas;
+
+import java.io.File;
+import java.util.List;
+
+import eu.siacs.conversations.xml.Element;
+
+public class Content extends Element {
+ private Content(String name) {
+ super(name);
+ }
+
+ public Content() {
+ super("content");
+ }
+
+ public void offerFile(File actualFile) {
+ Element description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
+ Element offer = description.addChild("offer");
+ Element file = offer.addChild("file");
+ file.addChild("size").setContent(""+actualFile.length());
+ file.addChild("name").setContent(actualFile.getName());
+ }
+
+ public void setCanditates(List<Element> canditates) {
+ Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
+ if (transport==null) {
+ transport = this.addChild("transport", "urn:xmpp:jingle:transports:s5b:1");
+ }
+ transport.clearChildren();
+ for(Element canditate : canditates) {
+ transport.addChild(canditate);
+ }
+ }
+}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
new file mode 100644
index 00000000..9cb2b448
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
@@ -0,0 +1,76 @@
+package eu.siacs.conversations.xmpp.jingle.stanzas;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.stanzas.IqPacket;
+
+public class JinglePacket extends IqPacket {
+ Content content = null;
+ Reason reason = null;
+ Element jingle = new Element("jingle");
+
+ @Override
+ public Element addChild(Element child) {
+ if ("jingle".equals(child.getName())) {
+ Element contentElement = child.findChild("content");
+ if (contentElement!=null) {
+ this.content = new Content();
+ this.content.setChildren(contentElement.getChildren());
+ this.content.setAttributes(contentElement.getAttributes());
+ }
+ Element reasonElement = child.findChild("reason");
+ if (reasonElement!=null) {
+ this.reason = new Reason();
+ this.reason.setChildren(reasonElement.getChildren());
+ this.reason.setAttributes(reasonElement.getAttributes());
+ }
+ this.jingle.setAttributes(child.getAttributes());
+ }
+ return child;
+ }
+
+ public JinglePacket setContent(Content content) {
+ this.content = content;
+ return this;
+ }
+
+ public JinglePacket setReason(Reason reason) {
+ this.reason = reason;
+ return this;
+ }
+
+ private void build() {
+ this.children.clear();
+ this.jingle.clearChildren();
+ this.jingle.setAttribute("xmlns", "urn:xmpp:jingle:1");
+ if (this.content!=null) {
+ jingle.addChild(this.content);
+ }
+ if (this.reason != null) {
+ jingle.addChild(this.reason);
+ }
+ this.children.add(jingle);
+ this.setAttribute("type", "set");
+ }
+
+ public String getSessionId() {
+ return this.jingle.getAttribute("sid");
+ }
+
+ public void setSessionId(String sid) {
+ this.jingle.setAttribute("sid", sid);
+ }
+
+ @Override
+ public String toString() {
+ this.build();
+ return super.toString();
+ }
+
+ public void setAction(String action) {
+ this.jingle.setAttribute("action", action);
+ }
+
+ public void setInitiator(String initiator) {
+ this.jingle.setAttribute("initiator", initiator);
+ }
+}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
new file mode 100644
index 00000000..195e0db7
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java
@@ -0,0 +1,13 @@
+package eu.siacs.conversations.xmpp.jingle.stanzas;
+
+import eu.siacs.conversations.xml.Element;
+
+public class Reason extends Element {
+ private Reason(String name) {
+ super(name);
+ }
+
+ public Reason() {
+ super("reason");
+ }
+}