summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Clayton <alex.clayton@isode.com>2016-03-16 15:45:11 (GMT)
committerAlex Clayton <alex.clayton@isode.com>2016-03-16 15:57:40 (GMT)
commitf693c8e0fa9c6a051cdf6260f131db3d9355b49f (patch)
tree10ca50f0c3494566e005f9c202f7d3b6c6d036f9
parent8b9891afc85d114ff1e9c9a0291a4aaee8baeb09 (diff)
downloadstroke-f693c8e0fa9c6a051cdf6260f131db3d9355b49f.zip
stroke-f693c8e0fa9c6a051cdf6260f131db3d9355b49f.tar.bz2
Support early IBB use in Jingle File Transfer
As per swiften patch of the same name (75703db2de5bbfb6622286600362016edb42dfb0). Previously Jingle File Transfer in Stroke only used IBB transport as fallback mechanism. With this patch Stroke will use IBB transport candidates directly in the first session-initate/session-accept message if the other party only supports IBB. Test-information: Unit tests all pass. Change-Id: Ice73a6028f10c63490bdb775a0a407fad48f587a
-rw-r--r--src/com/isode/stroke/filetransfer/DummyFileTransferTransporterFactory.java12
-rw-r--r--src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java7
-rw-r--r--src/com/isode/stroke/filetransfer/IncomingJingleFileTransfer.java13
-rw-r--r--src/com/isode/stroke/filetransfer/OutgoingJingleFileTransfer.java51
-rw-r--r--src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java4
-rw-r--r--test/com/isode/stroke/filetransfer/OutgoingJingleFileTransferTest.java18
6 files changed, 78 insertions, 27 deletions
diff --git a/src/com/isode/stroke/filetransfer/DummyFileTransferTransporterFactory.java b/src/com/isode/stroke/filetransfer/DummyFileTransferTransporterFactory.java
index 10b630d..1904944 100644
--- a/src/com/isode/stroke/filetransfer/DummyFileTransferTransporterFactory.java
+++ b/src/com/isode/stroke/filetransfer/DummyFileTransferTransporterFactory.java
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2015 Isode Limited.
+ * Copyright (c) 2015-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
/*
* Copyright (c) 2015 Tarun Gupta.
* Licensed under the simplified BSD license.
@@ -48,27 +48,34 @@ class DummyFileTransferTransporter extends FileTransferTransporter {
SOCKS5BytestreamProxiesManager s5bProxy,
IDGenerator idGenerator,
ConnectionFactory connectionFactory,
TimerFactory timer,
CryptoProvider cryptoProvider,
IQRouter iqRouter,
- final FileTransferOptions option) {
+ final FileTransferOptions ftOptions) {
initiator_ = initiator;
responder_ = responder;
role_ = role;
s5bRegistry_ = s5bRegistry;
crypto_ = cryptoProvider;
iqRouter_ = iqRouter;
+ ftOptions_ = new FileTransferOptions(ftOptions);
}
public void initialize() {
s5bSessionID_ = s5bRegistry_.generateSessionID();
}
public void startGeneratingLocalCandidates() {
Vector<JingleS5BTransportPayload.Candidate> candidates = new Vector<JingleS5BTransportPayload.Candidate>();
+ if (ftOptions_.isDirectAllowed()) {
+ JingleS5BTransportPayload.Candidate candidate = new JingleS5BTransportPayload.Candidate();
+ candidate.cid = "123";
+ candidate.priority = 1235;
+ candidates.add(candidate);
+ }
onLocalCandidatesGenerated.emit(s5bSessionID_, candidates, getSOCKS5DstAddr());
}
public void stopGeneratingLocalCandidates() {
}
@@ -144,12 +151,13 @@ class DummyFileTransferTransporter extends FileTransferTransporter {
private JID responder_;
private Role role_;
private SOCKS5BytestreamRegistry s5bRegistry_;
private CryptoProvider crypto_;
private String s5bSessionID_;
private IQRouter iqRouter_;
+ private final FileTransferOptions ftOptions_;
};
public class DummyFileTransferTransporterFactory implements FileTransferTransporterFactory {
public DummyFileTransferTransporterFactory(
SOCKS5BytestreamRegistry s5bRegistry,
diff --git a/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java b/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java
index 7166d67..06ed3ab 100644
--- a/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java
+++ b/src/com/isode/stroke/filetransfer/IncomingFileTransferManager.java
@@ -1,8 +1,8 @@
/*
- * Copyright (c) 2010-2015 Isode Limited.
+ * Copyright (c) 2010-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
/*
* Copyright (c) 2015 Tarun Gupta.
* Licensed under the simplified BSD license.
@@ -12,21 +12,23 @@
package com.isode.stroke.filetransfer;
import com.isode.stroke.signals.Signal1;
import com.isode.stroke.jingle.IncomingJingleSessionHandler;
import com.isode.stroke.jingle.JingleSessionManager;
import com.isode.stroke.jingle.JingleSession;
+import com.isode.stroke.elements.JingleIBBTransportPayload;
import com.isode.stroke.elements.JinglePayload;
import com.isode.stroke.elements.JingleContentPayload;
import com.isode.stroke.elements.JingleFileTransferDescription;
import com.isode.stroke.elements.JingleS5BTransportPayload;
import com.isode.stroke.jingle.Jingle;
import com.isode.stroke.network.TimerFactory;
import com.isode.stroke.crypto.CryptoProvider;
import com.isode.stroke.queries.IQRouter;
import com.isode.stroke.jid.JID;
+
import java.util.logging.Logger;
import java.util.Vector;
public class IncomingFileTransferManager implements IncomingJingleSessionHandler {
private JingleSessionManager jingleSessionManager;
@@ -52,13 +54,14 @@ public class IncomingFileTransferManager implements IncomingJingleSessionHandler
public boolean handleIncomingJingleSession(
JingleSession session,
final Vector<JingleContentPayload> contents,
final JID recipient) {
if (Jingle.getContentWithDescription(contents, new JingleFileTransferDescription()) != null) {
JingleContentPayload content = Jingle.getContentWithDescription(contents, new JingleFileTransferDescription());
- if (content.getTransport(new JingleS5BTransportPayload()) != null) {
+ if ( (content.getTransport(new JingleS5BTransportPayload()) != null)
+ || (content.getTransport(new JingleIBBTransportPayload()) != null) ) {
JingleFileTransferDescription description = content.getDescription(new JingleFileTransferDescription());
if (description != null) {
IncomingJingleFileTransfer transfer = new IncomingJingleFileTransfer(
recipient, session, content, transporterFactory, timerFactory, crypto);
onIncomingFileTransfer.emit(transfer);
}
diff --git a/src/com/isode/stroke/filetransfer/IncomingJingleFileTransfer.java b/src/com/isode/stroke/filetransfer/IncomingJingleFileTransfer.java
index 1c67014..f6aa01f 100644
--- a/src/com/isode/stroke/filetransfer/IncomingJingleFileTransfer.java
+++ b/src/com/isode/stroke/filetransfer/IncomingJingleFileTransfer.java
@@ -168,32 +168,33 @@ public class IncomingJingleFileTransfer extends JingleFileTransfer implements In
@Override
public void call(ByteArray b) {
handleWriteStreamDataReceived(b);
}
});
- if (initialContent.getTransport(new JingleS5BTransportPayload()) != null) {
- JingleS5BTransportPayload s5bTransport = initialContent.getTransport(new JingleS5BTransportPayload());
+ JingleS5BTransportPayload s5bTransport = initialContent.getTransport(new JingleS5BTransportPayload());
+ JingleIBBTransportPayload ibbTransport = initialContent.getTransport(new JingleIBBTransportPayload());
+ if (s5bTransport != null) {
logger_.fine("Got S5B transport as initial payload.\n");
setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), s5bTransport.getSessionID(), options));
transporter.addRemoteCandidates(s5bTransport.getCandidates(), s5bTransport.getDstAddr());
setInternalState(State.GeneratingInitialLocalCandidates);
transporter.startGeneratingLocalCandidates();
}
- else if(initialContent.getTransport(new JingleIBBTransportPayload()) != null) {
- JingleIBBTransportPayload ibbTransport = initialContent.getTransport(new JingleIBBTransportPayload());
+ else if(ibbTransport != null && options.isInBandAllowed()) {
logger_.fine("Got IBB transport as initial payload.\n");
setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), ibbTransport.getSessionID(), options));
startTransferring(transporter.createIBBReceiveSession(ibbTransport.getSessionID(), (int)description.getFileInfo().getSize(), stream));
session.sendAccept(getContentID(), initialContent.getDescriptions().get(0), ibbTransport);
}
else {
- // Can't happen, because the transfer would have been rejected automatically
- assert(false);
+ // This might happen on incoming transfer which only list transport methods we are not allowed to use due to file-transfer options.
+ session.sendTerminate(JinglePayload.Reason.Type.UnsupportedTransports);
+ setFinishedState(FileTransfer.State.Type.Failed, new FileTransferError(FileTransferError.Type.PeerError));
}
}
/**
* IncomingFileTransferMethod.
*/
diff --git a/src/com/isode/stroke/filetransfer/OutgoingJingleFileTransfer.java b/src/com/isode/stroke/filetransfer/OutgoingJingleFileTransfer.java
index aa38022..e2117b6 100644
--- a/src/com/isode/stroke/filetransfer/OutgoingJingleFileTransfer.java
+++ b/src/com/isode/stroke/filetransfer/OutgoingJingleFileTransfer.java
@@ -176,16 +176,25 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
public void start() {
logger_.fine("\n");
if (!State.Initial.equals(internalState)) {
logger_.warning("Incorrect state\n");
return;
}
-
- setTransporter(transporterFactory.createInitiatorTransporter(getInitiator(), getResponder(), options));
- setInternalState(State.GeneratingInitialLocalCandidates);
- transporter.startGeneratingLocalCandidates();
+
+ if (!options.isInBandAllowed() && !options.isDirectAllowed()
+ && !options.isAssistedAllowed() && !options.isProxiedAllowed()) {
+ // Started outgoing file transfer while not supporting transport methods.
+ setFinishedState(FileTransfer.State.Type.Failed,
+ new FileTransferError(FileTransferError.Type.UnknownError));
+ }
+ else {
+ setTransporter(transporterFactory.createInitiatorTransporter(getInitiator(), getResponder(), options));
+ setInternalState(State.GeneratingInitialLocalCandidates);
+ transporter.startGeneratingLocalCandidates();
+ }
+
}
/**
* JingleFileTransferMethod.
*/
@Override
@@ -214,12 +223,19 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
if (transportPayload instanceof JingleS5BTransportPayload) {
JingleS5BTransportPayload s5bPayload = (JingleS5BTransportPayload)transportPayload;
transporter.addRemoteCandidates(s5bPayload.getCandidates(), s5bPayload.getDstAddr());
setInternalState(State.TryingCandidates);
transporter.startTryingRemoteCandidates();
}
+ else if (transportPayload instanceof JingleIBBTransportPayload) {
+ JingleIBBTransportPayload ibbPayload = (JingleIBBTransportPayload) transportPayload;
+ int blockSize = ibbPayload.getBlockSize() != null ?
+ ibbPayload.getBlockSize().intValue() : DEFAULT_BLOCK_SIZE;
+ startTransferring(transporter.createIBBSendSession(ibbPayload.getSessionID(),
+ blockSize, stream));
+ }
else {
logger_.fine("Unknown transport payload. Falling back.\n");
fallback();
}
}
@@ -307,20 +323,31 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
JingleFileTransferDescription description = new JingleFileTransferDescription();
fileInfo.addHash(new HashElement("sha-1", new ByteArray()));
fileInfo.addHash(new HashElement("md5", new ByteArray()));
description.setFileInfo(fileInfo);
- JingleS5BTransportPayload transport = new JingleS5BTransportPayload();
- transport.setSessionID(s5bSessionID);
- transport.setMode(JingleS5BTransportPayload.Mode.TCPMode);
- transport.setDstAddr(dstAddr);
- for(JingleS5BTransportPayload.Candidate candidate : candidates) {
- transport.addCandidate(candidate);
- logger_.fine("\t" + "S5B candidate: " + candidate.hostPort.toString() + "\n");
- }
+ JingleTransportPayload transport = null;
+ if (candidates.isEmpty()) {
+ logger_.fine("no S5B candidate generated. Send IBB transport candidate.\n");
+ JingleIBBTransportPayload ibbTransport = new JingleIBBTransportPayload();
+ ibbTransport.setBlockSize(DEFAULT_BLOCK_SIZE);
+ ibbTransport.setSessionID(idGenerator.generateID());
+ transport = ibbTransport;
+ }
+ else {
+ JingleS5BTransportPayload s5bTransport = new JingleS5BTransportPayload();
+ s5bTransport.setSessionID(s5bSessionID);
+ s5bTransport.setMode(JingleS5BTransportPayload.Mode.TCPMode);
+ s5bTransport.setDstAddr(dstAddr);
+ for (JingleS5BTransportPayload.Candidate candidate : candidates) {
+ s5bTransport.addCandidate(candidate);
+ logger_.fine("\tS5B candidate: "+candidate.hostPort +"\n");
+ }
+ transport = s5bTransport;
+ }
setInternalState(State.WaitingForAccept);
session.sendInitiate(contentID, description, transport);
}
public void handleTransportInfoAcknowledged(final String id) {
if (id.equals(candidateSelectRequestID)) {
diff --git a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
index 590ee60..0d1f0a9 100644
--- a/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
+++ b/src/com/isode/stroke/filetransfer/SOCKS5BytestreamServerManager.java
@@ -123,12 +123,16 @@ public class SOCKS5BytestreamServerManager {
getPublicIPRequest = null;
}
if (forwardPortRequest != null) {
forwardPortRequest.stop();
forwardPortRequest = null;
}
+ if (unforwardPortRequest != null) {
+ unforwardPortRequest.stop();
+ unforwardPortRequest = null;
+ }
if (server != null) {
server.stop();
server = null;
}
if (connectionServer != null) {
connectionServer.stop();
diff --git a/test/com/isode/stroke/filetransfer/OutgoingJingleFileTransferTest.java b/test/com/isode/stroke/filetransfer/OutgoingJingleFileTransferTest.java
index 4532efb..f8b76b8 100644
--- a/test/com/isode/stroke/filetransfer/OutgoingJingleFileTransferTest.java
+++ b/test/com/isode/stroke/filetransfer/OutgoingJingleFileTransferTest.java
@@ -95,26 +95,31 @@ public class OutgoingJingleFileTransferTest {
if (call.description instanceof JingleFileTransferDescription) {
description = (JingleFileTransferDescription) call.description;
}
assertNotNull(description);
assertEquals(1048576,description.getFileInfo().getSize());
- JingleS5BTransportPayload transport = null;
- if (call.payload instanceof JingleS5BTransportPayload) {
- transport = (JingleS5BTransportPayload) call.payload;
+ JingleIBBTransportPayload transport = null;
+ if (call.payload instanceof JingleIBBTransportPayload) {
+ transport = (JingleIBBTransportPayload) call.payload;
+ }
+ else {
+ System.out.println(call.payload.getClass().getName());
}
assertNotNull(transport);
}
@Test
public void test_FallbackToIBBAfterFailingS5b() {
- OutgoingJingleFileTransfer transfer = createTestling();
+ OutgoingJingleFileTransfer transfer =
+ createTestling(new FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true));
transfer.start();
FakeJingleSession.InitiateCall call = getCall(FakeJingleSession.InitiateCall.class,0);
+ assertTrue(call.payload instanceof JingleS5BTransportPayload);
fakeJingleSession.handleSessionAcceptReceived(call.id, call.description, call.payload);
// Send candidate failure
JingleS5BTransportPayload candiateFailurePayload = new JingleS5BTransportPayload();
candiateFailurePayload.setCandidateError(true);
candiateFailurePayload.setSessionID(call.payload.getSessionID());
@@ -208,19 +213,22 @@ public class OutgoingJingleFileTransferTest {
private boolean finishedCalled = false;
private Type errorType = Type.UnknownError;
private State state = null;
}
private OutgoingJingleFileTransfer createTestling() {
+ return createTestling(new FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false));
+ }
+
+ private OutgoingJingleFileTransfer createTestling(FileTransferOptions options) {
JID to = new JID("test@foo.com/bla");
JingleFileTransferFileInfo fileInfo = new JingleFileTransferFileInfo();
fileInfo.setDescription("some file");
fileInfo.setName("test.bin");
fileInfo.addHash(new HashElement("sha-1", new ByteArray()));
fileInfo.setSize(1024 * 1024);
- FileTransferOptions options = (new FileTransferOptions()).withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false);
return new OutgoingJingleFileTransfer(to, fakeJingleSession, stream,
ftTransporterFactory, timeFactory, idGen, fileInfo, options, crypto);
}
private IQ createIBBRequest(IBB ibb,JID from,String id) {
IQ request = IQ.createRequest(IQ.Type.Set, new JID("foo@bar.com/baz"), id, ibb);