diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index fd299d801..930458b2b 100644
--- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -142,7 +142,7 @@ public class JingleConnection implements Transferable {
@Override
public void onFileTransferAborted() {
- JingleConnection.this.sendCancel();
+ JingleConnection.this.sendCancel(); //TODO probably send connectivity error instead?
JingleConnection.this.fail();
}
};
@@ -222,12 +222,12 @@ public class JingleConnection implements Transferable {
return this.message.getCounterpart();
}
- public void deliverPacket(JinglePacket packet) {
- boolean returnResult = true;
+ void deliverPacket(JinglePacket packet) {
if (packet.isAction("session-terminate")) {
Reason reason = packet.getReason();
if (reason != null) {
if (reason.hasChild("cancel")) {
+ //TODO mark as 'cancelled'
this.fail();
} else if (reason.hasChild("success")) {
this.receiveSuccess();
@@ -238,11 +238,11 @@ public class JingleConnection implements Transferable {
this.fail();
}
} else if (packet.isAction("session-accept")) {
- returnResult = receiveAccept(packet);
+ receiveAccept(packet);
} else if (packet.isAction("session-info")) {
- Element checksum = packet.getChecksum();
- Element file = checksum == null ? null : checksum.findChild("file");
- Element hash = file == null ? null : file.findChild("hash", "urn:xmpp:hashes:2");
+ final Element checksum = packet.getChecksum();
+ final Element file = checksum == null ? null : checksum.findChild("file");
+ final Element hash = file == null ? null : file.findChild("hash", "urn:xmpp:hashes:2");
if (hash != null && "sha-1".equalsIgnoreCase(hash.getAttribute("algo"))) {
try {
this.expectedHash = Base64.decode(hash.getContent(), Base64.DEFAULT);
@@ -250,25 +250,27 @@ public class JingleConnection implements Transferable {
this.expectedHash = new byte[0];
}
}
+ respondToIq(packet, true);
} else if (packet.isAction("transport-info")) {
- returnResult = receiveTransportInfo(packet);
+ receiveTransportInfo(packet);
} else if (packet.isAction("transport-replace")) {
if (packet.getJingleContent().hasIbbTransport()) {
- returnResult = this.receiveFallbackToIbb(packet);
+ receiveFallbackToIbb(packet);
} else {
- returnResult = false;
- Log.d(Config.LOGTAG, "trying to fallback to something unknown"
- + packet.toString());
+ Log.d(Config.LOGTAG, "trying to fallback to something unknown" + packet.toString());
+ respondToIq(packet, false);
}
} else if (packet.isAction("transport-accept")) {
- returnResult = this.receiveTransportAccept(packet);
+ receiveTransportAccept(packet);
} else {
- Log.d(Config.LOGTAG, "packet arrived in connection. action was "
- + packet.getAction());
- returnResult = false;
+ Log.d(Config.LOGTAG, "packet arrived in connection. action was " + packet.getAction());
+ respondToIq(packet, false);
}
- IqPacket response;
- if (returnResult) {
+ }
+
+ private void respondToIq(final IqPacket packet, final boolean result) {
+ final IqPacket response;
+ if (result) {
response = packet.generateResponse(IqPacket.TYPE.RESULT);
} else {
response = packet.generateResponse(IqPacket.TYPE.ERROR);
@@ -278,6 +280,14 @@ public class JingleConnection implements Transferable {
mXmppConnectionService.sendIqPacket(account, response, null);
}
+ private void respondToIqWithOutOfOrder(final IqPacket packet) {
+ final IqPacket response = packet.generateResponse(IqPacket.TYPE.ERROR);
+ final Element error = response.addChild("error").setAttribute("type", "wait");
+ error.addChild("unexpected-request", "urn:ietf:params:xml:ns:xmpp-stanzas");
+ error.addChild("out-of-order", "urn:xmpp:jingle:errors:1");
+ mXmppConnectionService.sendIqPacket(account, response, null);
+ }
+
public void init(final Message message) {
if (message.getEncryption() == Message.ENCRYPTION_AXOLOTL) {
Conversation conversation = (Conversation) message.getConversation();
@@ -401,6 +411,7 @@ public class JingleConnection implements Transferable {
this.contentName = content.getAttribute("name");
this.transportId = content.getTransportId();
+ //TODO change this to positive or negative response instead of fail directly
mXmppConnectionService.sendIqPacket(account, packet.generateResponse(IqPacket.TYPE.RESULT), null);
if (this.initialTransport == Transport.SOCKS) {
@@ -686,18 +697,19 @@ public class JingleConnection implements Transferable {
mXmppConnectionService.sendIqPacket(account, packet, callback);
}
- private boolean receiveAccept(JinglePacket packet) {
+ private void receiveAccept(JinglePacket packet) {
if (this.mJingleStatus != JINGLE_STATUS_INITIATED) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received out of order session-accept");
- return false;
+ respondToIqWithOutOfOrder(packet);
+ return;
}
this.mJingleStatus = JINGLE_STATUS_ACCEPTED;
mXmppConnectionService.markMessage(message, Message.STATUS_UNSEND);
Content content = packet.getJingleContent();
if (content.hasSocks5Transport()) {
+ respondToIq(packet, true);
mergeCandidates(JingleCandidate.parse(content.socks5transport().getChildren()));
this.connectNextCandidate();
- return true;
} else if (content.hasIbbTransport()) {
String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
if (receivedBlockSize != null) {
@@ -710,18 +722,19 @@ public class JingleConnection implements Transferable {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to parse block size in session-accept");
}
}
+ respondToIq(packet, true);
this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize);
this.transport.connect(onIbbTransportConnected);
- return true;
} else {
- return false;
+ respondToIq(packet, false);
}
}
- private boolean receiveTransportInfo(JinglePacket packet) {
- Content content = packet.getJingleContent();
+ private void receiveTransportInfo(JinglePacket packet) {
+ final Content content = packet.getJingleContent();
if (content.hasSocks5Transport()) {
if (content.socks5transport().hasChild("activated")) {
+ respondToIq(packet, true);
if ((this.transport != null) && (this.transport instanceof JingleSocks5Transport)) {
onProxyActivated.success();
} else {
@@ -737,17 +750,16 @@ public class JingleConnection implements Transferable {
this.fail();
}
}
- return true;
} else if (content.socks5transport().hasChild("proxy-error")) {
+ respondToIq(packet, true);
onProxyActivated.failed();
- return true;
} else if (content.socks5transport().hasChild("candidate-error")) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received candidate error");
+ respondToIq(packet, true);
this.receivedCandidate = true;
if (mJingleStatus == JINGLE_STATUS_ACCEPTED && this.sentCandidate) {
this.connect();
}
- return true;
} else if (content.socks5transport().hasChild("candidate-used")) {
String cid = content.socks5transport().findChild("candidate-used").getAttribute("cid");
if (cid != null) {
@@ -755,8 +767,10 @@ public class JingleConnection implements Transferable {
JingleCandidate candidate = getCandidate(cid);
if (candidate == null) {
Log.d(Config.LOGTAG, "could not find candidate with cid=" + cid);
- return false;
+ respondToIq(packet, false);
+ return;
}
+ respondToIq(packet, true);
candidate.flagAsUsedByCounterpart();
this.receivedCandidate = true;
if (mJingleStatus == JINGLE_STATUS_ACCEPTED && this.sentCandidate) {
@@ -764,15 +778,14 @@ public class JingleConnection implements Transferable {
} else {
Log.d(Config.LOGTAG, "ignoring because file is already in transmission or we haven't sent our candidate yet status=" + mJingleStatus + " sentCandidate=" + sentCandidate);
}
- return true;
} else {
- return false;
+ respondToIq(packet, false);
}
} else {
- return false;
+ respondToIq(packet, false);
}
} else {
- return true;
+ respondToIq(packet, true);
}
}
@@ -897,7 +910,7 @@ public class JingleConnection implements Transferable {
}
- private boolean receiveFallbackToIbb(JinglePacket packet) {
+ private void receiveFallbackToIbb(JinglePacket packet) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": receiving fallback to ibb");
final String receivedBlockSize = packet.getJingleContent().ibbTransport().getAttribute("block-size");
if (receivedBlockSize != null) {
@@ -920,6 +933,7 @@ public class JingleConnection implements Transferable {
content.ibbTransport().setAttribute("sid", this.transportId);
answer.setContent(content);
+ respondToIq(packet, true);
if (initiating()) {
this.sendJinglePacket(answer, (account, response) -> {
@@ -932,10 +946,9 @@ public class JingleConnection implements Transferable {
this.transport.receive(file, onFileTransmissionStatusChanged);
this.sendJinglePacket(answer);
}
- return true;
}
- private boolean receiveTransportAccept(JinglePacket packet) {
+ private void receiveTransportAccept(JinglePacket packet) {
if (packet.getJingleContent().hasIbbTransport()) {
final Element ibbTransport = packet.getJingleContent().ibbTransport();
final String receivedBlockSize = ibbTransport.getAttribute("block-size");
@@ -955,17 +968,16 @@ public class JingleConnection implements Transferable {
if (sid == null || !sid.equals(this.transportId)) {
Log.w(Config.LOGTAG, String.format("%s: sid in transport-accept (%s) did not match our sid (%s) ", account.getJid().asBareJid(), sid, transportId));
}
-
+ respondToIq(packet, true);
//might be receive instead if we are not initiating
if (initiating()) {
this.transport.connect(onIbbTransportConnected);
} else {
this.transport.receive(file, onFileTransmissionStatusChanged);
}
- return true;
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received invalid transport-accept");
- return false;
+ respondToIq(packet, false);
}
}
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 11bbb6cf5..0aa3f5418 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -337,6 +337,7 @@
%s offered for download
Cancel transmission
file transmission failed
+ file transmission cancelled
The file has been deleted
No application found to open file
No application found to open link