aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-13 21:10:36 +0200
committerDaniel Gultsch <daniel.gultsch@rwth-aachen.de>2014-04-13 21:10:36 +0200
commit084ab51b1d7625cdf1cca4cc6a31715acffe5ce7 (patch)
treebd1ab4b6d48aaafd4e410b50d7f5f3d7fd8e5f14
parent7dfe4ae0823238da216088f80de40b9ff6b1446d (diff)
transmitting files between two conversations works. no error handling and no ui on the receiving end
-rw-r--r--src/eu/siacs/conversations/persistance/FileBackend.java4
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java2
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java61
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java13
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java73
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java19
6 files changed, 136 insertions, 36 deletions
diff --git a/src/eu/siacs/conversations/persistance/FileBackend.java b/src/eu/siacs/conversations/persistance/FileBackend.java
index 59373e74..f7f986f2 100644
--- a/src/eu/siacs/conversations/persistance/FileBackend.java
+++ b/src/eu/siacs/conversations/persistance/FileBackend.java
@@ -10,7 +10,6 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.util.Log;
import android.util.LruCache;
import eu.siacs.conversations.entities.Conversation;
@@ -81,7 +80,7 @@ public class FileBackend {
Bitmap scalledBitmap = resize(originalBitmap, IMAGE_SIZE);
boolean success = scalledBitmap.compress(Bitmap.CompressFormat.WEBP,75,os);
if (!success) {
- Log.d("xmppService", "couldnt compress");
+ //Log.d("xmppService", "couldnt compress");
}
os.close();
return file;
@@ -104,7 +103,6 @@ public class FileBackend {
public Bitmap getThumbnailFromMessage(Message message, int size) {
Bitmap thumbnail = thumbnailCache.get(message.getUuid());
if (thumbnail==null) {
- Log.d("xmppService","creating new thumbnail" + message.getUuid());
Bitmap fullsize = BitmapFactory.decodeFile(getJingleFile(message)
.getAbsolutePath());
thumbnail = resize(fullsize, size);
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index 63ab0897..e5974c2d 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -1059,12 +1059,10 @@ public class XmppConnectionService extends Service {
OnConversationListChangedListener listener) {
this.convChangedListener = listener;
this.convChangedListenerCount++;
- Log.d(LOGTAG,"registered on conv changed in backend ("+convChangedListenerCount+")");
}
public void removeOnConversationListChangedListener() {
this.convChangedListenerCount--;
- Log.d(LOGTAG,"someone on conv changed listener removed listener ("+convChangedListenerCount+")");
if (this.convChangedListenerCount==0) {
this.convChangedListener = null;
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index a97c3ac3..4551a1ca 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -29,6 +29,7 @@ public class JingleConnection {
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_TRANSMITTING = 5;
public static final int STATUS_FAILED = 99;
private int status = -1;
@@ -64,7 +65,7 @@ public class JingleConnection {
}
public String getAccountJid() {
- return this.account.getJid();
+ return this.account.getFullJid();
}
public String getCounterPart() {
@@ -113,6 +114,7 @@ public class JingleConnection {
}
public void init(Account account, JinglePacket packet) {
+ this.status = STATUS_INITIATED;
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);
@@ -140,6 +142,7 @@ public class JingleConnection {
} else {
Log.d("xmppService","no file offer was attached. aborting");
}
+ Log.d("xmppService","session Id "+getSessionId());
}
private void sendInitRequest() {
@@ -172,13 +175,12 @@ public class JingleConnection {
JinglePacket packet = bootstrapPacket();
packet.setAction("session-accept");
packet.setContent(content);
- Log.d("xmppService","sending session accept: "+packet.toString());
account.getXmppConnection().sendIqPacket(packet, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (packet.getType() != IqPacket.TYPE_ERROR) {
- Log.d("xmppService","opsing side has acked our session-accept");
+ status = STATUS_ACCEPTED;
connectWithCandidates();
}
}
@@ -209,20 +211,31 @@ public class JingleConnection {
private void transportInfo(JinglePacket packet) {
Content content = packet.getJingleContent();
- Log.d("xmppService","transport info : "+content.toString());
String cid = content.getUsedCandidate();
+ IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
if (cid!=null) {
Log.d("xmppService","candidate used by counterpart:"+cid);
this.candidatesUsedByCounterpart.add(cid);
if (this.connections.containsKey(cid)) {
- this.connect(this.connections.get(cid));
+ SocksConnection connection = this.connections.get(cid);
+ if (connection.isEstablished()) {
+ if (status!=STATUS_TRANSMITTING) {
+ this.connect(connection);
+ } else {
+ Log.d("xmppService","ignoring canditate used because we are already transmitting");
+ }
+ } else {
+ Log.d("xmppService","not yet connected. check when callback comes back");
+ }
+ } else {
+ Log.d("xmppService","candidate not yet in list of connections");
}
}
- IqPacket response = packet.generateRespone(IqPacket.TYPE_RESULT);
account.getXmppConnection().sendIqPacket(response, null);
}
private void connect(final SocksConnection connection) {
+ this.status = STATUS_TRANSMITTING;
final OnFileTransmitted callback = new OnFileTransmitted() {
@Override
@@ -230,12 +243,12 @@ public class JingleConnection {
Log.d("xmppService","sucessfully transmitted file. sha1:"+file.getSha1Sum());
}
};
- if (connection.isProxy()) {
+ if ((connection.isProxy()&&(connection.getCid().equals(mJingleConnectionManager.getPrimaryCandidateId(account))))) {
+ Log.d("xmppService","candidate "+connection.getCid()+" was our proxy and needs activation");
IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
activation.setTo(connection.getJid());
activation.query("http://jabber.org/protocol/bytestreams").setAttribute("sid", this.getSessionId());
activation.query().addChild("activate").setContent(this.getResponder());
- Log.d("xmppService","connection is proxy. need to activate "+activation.toString());
this.account.getXmppConnection().sendIqPacket(activation, new OnIqPacketReceived() {
@Override
@@ -245,9 +258,9 @@ public class JingleConnection {
Log.d("xmppService","we were initiating. sending file");
connection.send(file,callback);
} else {
+ connection.receive(file,callback);
Log.d("xmppService","we were responding. receiving file");
}
-
}
});
} else {
@@ -256,6 +269,7 @@ public class JingleConnection {
connection.send(file,callback);
} else {
Log.d("xmppService","we were responding. receiving file");
+ connection.receive(file,callback);
}
}
}
@@ -273,14 +287,9 @@ public class JingleConnection {
}
private void connectWithCandidates() {
- for(Element canditate : this.candidates) {
-
- String host = canditate.getAttribute("host");
- int port = Integer.parseInt(canditate.getAttribute("port"));
- String type = canditate.getAttribute("type");
- String jid = canditate.getAttribute("jid");
- SocksConnection socksConnection = new SocksConnection(this, host, jid, port,type);
- connections.put(canditate.getAttribute("cid"), socksConnection);
+ for(Element candidate : this.candidates) {
+ final SocksConnection socksConnection = new SocksConnection(this,candidate);
+ connections.put(socksConnection.getCid(), socksConnection);
socksConnection.connect(new OnSocksConnection() {
@Override
@@ -290,7 +299,15 @@ public class JingleConnection {
@Override
public void established() {
- Log.d("xmppService","established socks5");
+ if (candidatesUsedByCounterpart.contains(socksConnection.getCid())) {
+ if (status!=STATUS_TRANSMITTING) {
+ connect(socksConnection);
+ } else {
+ Log.d("xmppService","ignoring cuz already transmitting");
+ }
+ } else {
+ sendCandidateUsed(socksConnection.getCid());
+ }
}
});
}
@@ -306,7 +323,13 @@ public class JingleConnection {
}
private void sendCandidateUsed(String cid) {
-
+ JinglePacket packet = bootstrapPacket();
+ packet.setAction("transport-info");
+ Content content = new Content();
+ content.setUsedCandidate(this.content.getTransportId(), cid);
+ packet.setContent(content);
+ Log.d("xmppService","send using candidate: "+packet.toString());
+ this.account.getXmppConnection().sendIqPacket(packet, responseListener);
}
public String getInitiator() {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
index 7df27d4d..972489d0 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
@@ -35,13 +35,16 @@ public class JingleConnectionManager {
if (packet.isAction("session-initiate")) {
JingleConnection connection = new JingleConnection(this);
connection.init(account,packet);
+ connections.add(connection);
} else {
for (JingleConnection connection : connections) {
- if (connection.getAccountJid().equals(account.getJid()) && connection
+ if (connection.getAccountJid().equals(account.getFullJid()) && connection
.getSessionId().equals(packet.getSessionId()) && connection
.getCounterPart().equals(packet.getFrom())) {
connection.deliverPacket(packet);
return;
+ } else {
+ Log.d("xmppService","no match sid:"+connection.getSessionId()+"="+packet.getSessionId()+" counterpart:"+connection.getCounterPart()+"="+packet.getFrom()+" account:"+connection.getAccountJid()+"="+packet.getTo());
}
}
Log.d("xmppService","delivering packet failed "+packet.toString());
@@ -118,6 +121,14 @@ public class JingleConnectionManager {
this.primaryCandidates.get(account.getJid()));
}
}
+
+ public String getPrimaryCandidateId(Account account) {
+ if (this.primaryCandidates.containsKey(account.getJid())) {
+ return this.primaryCandidates.get(account.getJid()).getAttribute("cid");
+ } else {
+ return null;
+ }
+ }
public String nextRandomId() {
return new BigInteger(50, random).toString(32);
diff --git a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
index d4cb432a..bf7c87ad 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/SocksConnection.java
@@ -2,6 +2,7 @@ package eu.siacs.conversations.xmpp.jingle;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -12,27 +13,29 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import eu.siacs.conversations.utils.CryptoHelper;
+import eu.siacs.conversations.xml.Element;
import android.util.Log;
+import android.widget.Button;
public class SocksConnection {
-
- private JingleConnection jingleConnection;
private Socket socket;
private String host;
private String jid;
+ private String cid;
private int port;
private boolean isProxy = false;
private String destination;
private OutputStream outputStream;
+ private InputStream inputStream;
private boolean isEstablished = false;
- public SocksConnection(JingleConnection jingleConnection, String host,
- String jid, int port, String type) {
- this.jingleConnection = jingleConnection;
- this.host = host;
- this.jid = jid;
- this.port = port;
+ public SocksConnection(JingleConnection jingleConnection, Element candidate) {
+ this.cid = candidate.getAttribute("cid");
+ this.host = candidate.getAttribute("host");
+ this.port = Integer.parseInt(candidate.getAttribute("port"));
+ String type = candidate.getAttribute("type");
+ this.jid = candidate.getAttribute("jid");
this.isProxy = "proxy".equalsIgnoreCase(type);
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
@@ -55,19 +58,19 @@ public class SocksConnection {
public void run() {
try {
socket = new Socket(host, port);
- InputStream is = socket.getInputStream();
+ inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
byte[] login = { 0x05, 0x01, 0x00 };
byte[] expectedReply = { 0x05, 0x00 };
byte[] reply = new byte[2];
outputStream.write(login);
- is.read(reply);
+ inputStream.read(reply);
if (Arrays.equals(reply, expectedReply)) {
String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
+ '\u0028' + destination + '\u0000' + '\u0000';
outputStream.write(connect.getBytes());
byte[] result = new byte[2];
- is.read(result);
+ inputStream.read(result);
int status = result[1];
if (status == 0) {
Log.d("xmppService", "established connection with "+host + ":" + port
@@ -135,6 +138,50 @@ public class SocksConnection {
}).start();
}
+
+ public void receive(final JingleFile file, final OnFileTransmitted callback) {
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ digest.reset();
+ inputStream.skip(45);
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+ FileOutputStream fileOutputStream = new FileOutputStream(file);
+ long remainingSize = file.getExpectedSize();
+ byte[] buffer = new byte[8192];
+ int count = buffer.length;
+ while(remainingSize > 0) {
+ Log.d("xmppService","remaning size:"+remainingSize);
+ if (remainingSize<=count) {
+ count = (int) remainingSize;
+ }
+ count = inputStream.read(buffer, 0, count);
+ fileOutputStream.write(buffer, 0, count);
+ digest.update(buffer, 0, count);
+ remainingSize-=count;
+ }
+ fileOutputStream.flush();
+ fileOutputStream.close();
+ file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
+ Log.d("xmppService","transmitted filename was: "+file.getAbsolutePath());
+ 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();
+ }
+ }
+ }).start();
+ }
public boolean isProxy() {
return this.isProxy;
@@ -143,6 +190,10 @@ public class SocksConnection {
public String getJid() {
return this.jid;
}
+
+ public String getCid() {
+ return this.cid;
+ }
public void disconnect() {
if (this.socket!=null) {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
index c9015d39..79e04610 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
@@ -56,6 +56,14 @@ public class Content extends Element {
}
}
+ public String getTransportId() {
+ Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
+ if (transport==null) {
+ return null;
+ }
+ return transport.getAttribute("sid");
+ }
+
public String getUsedCandidate() {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
if (transport==null) {
@@ -68,6 +76,17 @@ public class Content extends Element {
return usedCandidate.getAttribute("cid");
}
}
+
+ public void setUsedCandidate(String transportId, String cid) {
+ 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.setAttribute("sid", transportId);
+ transport.clearChildren();
+ Element usedCandidate = transport.addChild("candidate-used");
+ usedCandidate.setAttribute("cid",cid);
+ }
public void addCandidate(Element candidate) {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");