aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp/jingle
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs/conversations/xmpp/jingle')
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java74
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java19
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleFile.java35
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/OnFileTransmitted.java5
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java107
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java7
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java4
7 files changed, 193 insertions, 58 deletions
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index 31b643c0..c5b7b60c 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -1,19 +1,23 @@
package eu.siacs.conversations.xmpp.jingle;
-import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import android.util.Log;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Conversation;
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.jingle.stanzas.Reason;
import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JingleConnection {
@@ -24,6 +28,8 @@ public class JingleConnection {
public static final int STATUS_INITIATED = 0;
public static final int STATUS_ACCEPTED = 1;
public static final int STATUS_TERMINATED = 2;
+ public static final int STATUS_CANCELED = 3;
+ public static final int STATUS_FINISHED = 4;
public static final int STATUS_FAILED = 99;
private int status = -1;
@@ -34,7 +40,7 @@ public class JingleConnection {
private String responder;
private List<Element> candidates = new ArrayList<Element>();
private HashMap<String, SocksConnection> connections = new HashMap<String, SocksConnection>();
- private File file = null;
+ private JingleFile file = null;
private OnIqPacketReceived responseListener = new OnIqPacketReceived() {
@@ -50,7 +56,6 @@ public class JingleConnection {
public JingleConnection(JingleConnectionManager mJingleConnectionManager) {
this.mJingleConnectionManager = mJingleConnectionManager;
this.mXmppConnectionService = mJingleConnectionManager.getXmppConnectionService();
- this.sessionId = this.mJingleConnectionManager.nextRandomId();
}
public String getSessionId() {
@@ -68,10 +73,12 @@ public class JingleConnection {
public void deliverPacket(JinglePacket packet) {
if (packet.isAction("session-terminate")) {
- if (status == STATUS_INITIATED) {
- mXmppConnectionService.markMessage(message, Message.STATUS_SEND_REJECTED);
+ Reason reason = packet.getReason();
+ if (reason.hasChild("cancel")) {
+ this.cancel();
+ } else if (reason.hasChild("success")) {
+ this.finish();
}
- status = STATUS_TERMINATED;
} else if (packet.isAction("session-accept")) {
accept(packet);
} else if (packet.isAction("transport-info")) {
@@ -86,6 +93,7 @@ public class JingleConnection {
this.account = message.getConversation().getAccount();
this.initiator = this.account.getFullJid();
this.responder = this.message.getCounterpart();
+ this.sessionId = this.mJingleConnectionManager.nextRandomId();
if (this.candidates.size() > 0) {
this.sendInitRequest();
} else {
@@ -103,6 +111,19 @@ public class JingleConnection {
}
+ public void init(Account account, JinglePacket packet) {
+ Conversation conversation = this.mXmppConnectionService.findOrCreateConversation(account, packet.getFrom().split("/")[0], false);
+ this.message = new Message(conversation, "receiving image file", Message.ENCRYPTION_NONE);
+ this.message.setType(Message.TYPE_IMAGE);
+ this.message.setStatus(Message.STATUS_RECIEVING);
+ this.account = account;
+ this.initiator = packet.getFrom();
+ this.responder = this.account.getFullJid();
+ this.sessionId = packet.getSessionId();
+ this.candidates.addAll(packet.getJingleContent().getCanditates());
+ Log.d("xmppService","new incomming jingle session "+this.sessionId+" num canditaes:"+this.candidates.size());
+ }
+
private void sendInitRequest() {
JinglePacket packet = this.bootstrapPacket();
packet.setAction("session-initiate");
@@ -145,8 +166,16 @@ public class JingleConnection {
Log.d("xmppService","transport info : "+content.toString());
String cid = content.getUsedCandidate();
if (cid!=null) {
- final File file = this.mXmppConnectionService.getFileBackend().getImageFile(this.message);
+ final JingleFile file = this.mXmppConnectionService.getFileBackend().getImageFile(this.message);
final SocksConnection connection = this.connections.get(cid);
+ final OnFileTransmitted callback = new OnFileTransmitted() {
+
+ @Override
+ public void onFileTransmitted(JingleFile file) {
+ Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum());
+ }
+ };
+ final IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
if (connection.isProxy()) {
IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
activation.setTo(connection.getJid());
@@ -157,16 +186,30 @@ public class JingleConnection {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
+ account.getXmppConnection().sendIqPacket(response, null);
Log.d("xmppService","activation result: "+packet.toString());
- connection.send(file);
+ connection.send(file,callback);
}
});
} else {
- connection.send(file);
+ account.getXmppConnection().sendIqPacket(response, null);
+ connection.send(file,callback);
}
}
}
+ private void finish() {
+ this.status = STATUS_FINISHED;
+ this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND);
+ this.disconnect();
+ }
+
+ public void cancel() {
+ this.disconnect();
+ this.status = STATUS_CANCELED;
+ this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_REJECTED);
+ }
+
private void connectWithCandidates() {
for(Element canditate : this.candidates) {
String host = canditate.getAttribute("host");
@@ -179,6 +222,15 @@ public class JingleConnection {
}
}
+ private void disconnect() {
+ Iterator<Entry<String, SocksConnection>> it = this.connections.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<String, SocksConnection> pairs = it.next();
+ pairs.getValue().disconnect();
+ it.remove();
+ }
+ }
+
private void sendCandidateUsed(String cid) {
}
@@ -190,4 +242,8 @@ public class JingleConnection {
public String getResponder() {
return this.responder;
}
+
+ public int getStatus() {
+ return this.status;
+ }
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
index 89ff717d..45323e44 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
@@ -32,15 +32,20 @@ public class JingleConnectionManager {
}
public void deliverPacket(Account account, JinglePacket packet) {
- for (JingleConnection connection : connections) {
- if (connection.getAccountJid().equals(account.getJid()) && connection
- .getSessionId().equals(packet.getSessionId()) && connection
- .getCounterPart().equals(packet.getFrom())) {
- connection.deliverPacket(packet);
- return;
+ if (packet.isAction("session-initiate")) {
+ JingleConnection connection = new JingleConnection(this);
+ connection.init(account,packet);
+ } else {
+ for (JingleConnection connection : connections) {
+ if (connection.getAccountJid().equals(account.getJid()) && connection
+ .getSessionId().equals(packet.getSessionId()) && connection
+ .getCounterPart().equals(packet.getFrom())) {
+ connection.deliverPacket(packet);
+ return;
+ }
}
+ Log.d("xmppService","delivering packet failed "+packet.toString());
}
- Log.d("xmppService","delivering packet failed "+packet.toString());
}
public JingleConnection createNewConnection(Message message) {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java b/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java
new file mode 100644
index 00000000..21cbd716
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java
@@ -0,0 +1,35 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+import java.io.File;
+
+public class JingleFile extends File {
+
+ private static final long serialVersionUID = 2247012619505115863L;
+
+ private long expectedSize = 0;
+ private String sha1sum;
+
+ public JingleFile(String path) {
+ super(path);
+ }
+
+ public long getSize() {
+ return super.length();
+ }
+
+ public long getExpectedSize() {
+ return this.expectedSize;
+ }
+
+ public void setExpectedSize(long size) {
+ this.expectedSize = size;
+ }
+
+ public String getSha1Sum() {
+ return this.sha1sum;
+ }
+
+ public void setSha1Sum(String sum) {
+ this.sha1sum = sum;
+ }
+}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmitted.java b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmitted.java
new file mode 100644
index 00000000..fd5fd2f7
--- /dev/null
+++ b/src/eu/siacs/conversations/xmpp/jingle/OnFileTransmitted.java
@@ -0,0 +1,5 @@
+package eu.siacs.conversations.xmpp.jingle;
+
+public interface OnFileTransmitted {
+ public void onFileTransmitted(JingleFile file);
+}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
index c1219ff7..6a3a3648 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
@@ -1,6 +1,5 @@
package eu.siacs.conversations.xmpp.jingle;
-import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -17,7 +16,7 @@ import eu.siacs.conversations.utils.CryptoHelper;
import android.util.Log;
public class SocksConnection {
-
+
private JingleConnection jingleConnection;
private Socket socket;
private String host;
@@ -26,8 +25,9 @@ public class SocksConnection {
private boolean isProxy = false;
private String destination;
private OutputStream outputStream;
-
- public SocksConnection(JingleConnection jingleConnection, String host, String jid, int port, String type) {
+
+ public SocksConnection(JingleConnection jingleConnection, String host,
+ String jid, int port, String type) {
this.jingleConnection = jingleConnection;
this.host = host;
this.jid = jid;
@@ -40,30 +40,33 @@ public class SocksConnection {
destBuilder.append(jingleConnection.getInitiator());
destBuilder.append(jingleConnection.getResponder());
mDigest.reset();
- this.destination = CryptoHelper.bytesToHex(mDigest.digest(destBuilder.toString().getBytes()));
- Log.d("xmppService","host="+host+", port="+port+", destination: "+destination);
+ this.destination = CryptoHelper.bytesToHex(mDigest
+ .digest(destBuilder.toString().getBytes()));
+ Log.d("xmppService", "host=" + host + ", port=" + port
+ + ", destination: " + destination);
} catch (NoSuchAlgorithmException e) {
-
+
}
}
-
+
public boolean connect() {
try {
this.socket = new Socket(this.host, this.port);
InputStream is = socket.getInputStream();
this.outputStream = socket.getOutputStream();
- byte[] login = {0x05, 0x01, 0x00};
- byte[] expectedReply = {0x05,0x00};
+ byte[] login = { 0x05, 0x01, 0x00 };
+ byte[] expectedReply = { 0x05, 0x00 };
byte[] reply = new byte[2];
this.outputStream.write(login);
is.read(reply);
if (Arrays.equals(reply, expectedReply)) {
- String connect = ""+'\u0005'+'\u0001'+'\u0000'+'\u0003'+'\u0028'+this.destination+'\u0000'+'\u0000';
+ String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
+ + '\u0028' + this.destination + '\u0000' + '\u0000';
this.outputStream.write(connect.getBytes());
byte[] result = new byte[2];
is.read(result);
int status = result[0];
- return (status==0);
+ return (status == 0);
} else {
socket.close();
return false;
@@ -75,39 +78,67 @@ public class SocksConnection {
}
}
- public void send(File file) {
- FileInputStream fileInputStream = null;
- try {
- fileInputStream = new FileInputStream(file);
- int count;
- byte[] buffer = new byte[8192];
- while ((count = fileInputStream.read(buffer)) > 0) {
- this.outputStream.write(buffer, 0, count);
- }
-
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- try {
- if (fileInputStream!=null) {
- fileInputStream.close();
+ public void send(final JingleFile file, final OnFileTransmitted callback) {
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ FileInputStream fileInputStream = null;
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ digest.reset();
+ fileInputStream = new FileInputStream(file);
+ int count;
+ byte[] buffer = new byte[8192];
+ while ((count = fileInputStream.read(buffer)) > 0) {
+ outputStream.write(buffer, 0, count);
+ digest.update(buffer, 0, count);
+ }
+ outputStream.flush();
+ file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
+ if (callback!=null) {
+ callback.onFileTransmitted(file);
+ }
+ } catch (FileNotFoundException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ try {
+ if (fileInputStream != null) {
+ fileInputStream.close();
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
}
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
}
- }
+ }).start();
+
}
-
+
public boolean isProxy() {
return this.isProxy;
}
-
+
public String getJid() {
return this.jid;
}
+
+ public void disconnect() {
+ if (this.socket!=null) {
+ try {
+ this.socket.close();
+ Log.d("xmppService","cloesd socket with "+this.host);
+ } catch (IOException e) {
+ Log.d("xmppService","error closing socket with "+this.host);
+ }
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
index 304656ee..cefcde36 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
@@ -1,10 +1,10 @@
package eu.siacs.conversations.xmpp.jingle.stanzas;
-import java.io.File;
import java.util.ArrayList;
import java.util.List;
import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.jingle.JingleFile;
public class Content extends Element {
private Content(String name) {
@@ -15,13 +15,12 @@ public class Content extends Element {
super("content");
}
- public void offerFile(File actualFile, String hash) {
+ public void offerFile(JingleFile actualFile, String hash) {
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("size").setContent(""+actualFile.getSize());
file.addChild("name").setContent(actualFile.getName());
- file.addChild("hash","urn:xmpp:hashes:1").setAttribute("algo", "sha-1").setContent(hash);
}
public void setCandidates(String transportId, List<Element> canditates) {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
index 83f0aec6..55700609 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/JinglePacket.java
@@ -45,6 +45,10 @@ public class JinglePacket extends IqPacket {
return this;
}
+ public Reason getReason() {
+ return this.reason;
+ }
+
private void build() {
this.children.clear();
this.jingle.clearChildren();