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,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2015 Isode Limited. 2 * Copyright (c) 2015-2016 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
@@ -51,13 +51,14 @@ class DummyFileTransferTransporter extends FileTransferTransporter {
51 TimerFactory timer, 51 TimerFactory timer,
52 CryptoProvider cryptoProvider, 52 CryptoProvider cryptoProvider,
53 IQRouter iqRouter, 53 IQRouter iqRouter,
54 final FileTransferOptions option) { 54 final FileTransferOptions ftOptions) {
55 initiator_ = initiator; 55 initiator_ = initiator;
56 responder_ = responder; 56 responder_ = responder;
57 role_ = role; 57 role_ = role;
58 s5bRegistry_ = s5bRegistry; 58 s5bRegistry_ = s5bRegistry;
59 crypto_ = cryptoProvider; 59 crypto_ = cryptoProvider;
60 iqRouter_ = iqRouter; 60 iqRouter_ = iqRouter;
61 ftOptions_ = new FileTransferOptions(ftOptions);
61 } 62 }
62 63
63 public void initialize() { 64 public void initialize() {
@@ -66,6 +67,12 @@ class DummyFileTransferTransporter extends FileTransferTransporter {
66 67
67 public void startGeneratingLocalCandidates() { 68 public void startGeneratingLocalCandidates() {
68 Vector<JingleS5BTransportPayload.Candidate> candidates = new Vector<JingleS5BTransportPayload.Candidate>(); 69 Vector<JingleS5BTransportPayload.Candidate> candidates = new Vector<JingleS5BTransportPayload.Candidate>();
70 if (ftOptions_.isDirectAllowed()) {
71 JingleS5BTransportPayload.Candidate candidate = new JingleS5BTransportPayload.Candidate();
72 candidate.cid = "123";
73 candidate.priority = 1235;
74 candidates.add(candidate);
75 }
69 onLocalCandidatesGenerated.emit(s5bSessionID_, candidates, getSOCKS5DstAddr()); 76 onLocalCandidatesGenerated.emit(s5bSessionID_, candidates, getSOCKS5DstAddr());
70 } 77 }
71 78
@@ -147,6 +154,7 @@ class DummyFileTransferTransporter extends FileTransferTransporter {
147 private CryptoProvider crypto_; 154 private CryptoProvider crypto_;
148 private String s5bSessionID_; 155 private String s5bSessionID_;
149 private IQRouter iqRouter_; 156 private IQRouter iqRouter_;
157 private final FileTransferOptions ftOptions_;
150}; 158};
151 159
152public class DummyFileTransferTransporterFactory implements FileTransferTransporterFactory { 160public class DummyFileTransferTransporterFactory implements FileTransferTransporterFactory {
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,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2010-2015 Isode Limited. 2 * Copyright (c) 2010-2016 Isode Limited.
3 * All rights reserved. 3 * All rights reserved.
4 * See the COPYING file for more information. 4 * See the COPYING file for more information.
5 */ 5 */
@@ -15,6 +15,7 @@ import com.isode.stroke.signals.Signal1;
15import com.isode.stroke.jingle.IncomingJingleSessionHandler; 15import com.isode.stroke.jingle.IncomingJingleSessionHandler;
16import com.isode.stroke.jingle.JingleSessionManager; 16import com.isode.stroke.jingle.JingleSessionManager;
17import com.isode.stroke.jingle.JingleSession; 17import com.isode.stroke.jingle.JingleSession;
18import com.isode.stroke.elements.JingleIBBTransportPayload;
18import com.isode.stroke.elements.JinglePayload; 19import com.isode.stroke.elements.JinglePayload;
19import com.isode.stroke.elements.JingleContentPayload; 20import com.isode.stroke.elements.JingleContentPayload;
20import com.isode.stroke.elements.JingleFileTransferDescription; 21import com.isode.stroke.elements.JingleFileTransferDescription;
@@ -24,6 +25,7 @@ import com.isode.stroke.network.TimerFactory;
24import com.isode.stroke.crypto.CryptoProvider; 25import com.isode.stroke.crypto.CryptoProvider;
25import com.isode.stroke.queries.IQRouter; 26import com.isode.stroke.queries.IQRouter;
26import com.isode.stroke.jid.JID; 27import com.isode.stroke.jid.JID;
28
27import java.util.logging.Logger; 29import java.util.logging.Logger;
28import java.util.Vector; 30import java.util.Vector;
29 31
@@ -55,7 +57,8 @@ public class IncomingFileTransferManager implements IncomingJingleSessionHandler
55 final JID recipient) { 57 final JID recipient) {
56 if (Jingle.getContentWithDescription(contents, new JingleFileTransferDescription()) != null) { 58 if (Jingle.getContentWithDescription(contents, new JingleFileTransferDescription()) != null) {
57 JingleContentPayload content = Jingle.getContentWithDescription(contents, new JingleFileTransferDescription()); 59 JingleContentPayload content = Jingle.getContentWithDescription(contents, new JingleFileTransferDescription());
58 if (content.getTransport(new JingleS5BTransportPayload()) != null) { 60 if ( (content.getTransport(new JingleS5BTransportPayload()) != null)
61 || (content.getTransport(new JingleIBBTransportPayload()) != null) ) {
59 JingleFileTransferDescription description = content.getDescription(new JingleFileTransferDescription()); 62 JingleFileTransferDescription description = content.getDescription(new JingleFileTransferDescription());
60 if (description != null) { 63 if (description != null) {
61 IncomingJingleFileTransfer transfer = new IncomingJingleFileTransfer( 64 IncomingJingleFileTransfer transfer = new IncomingJingleFileTransfer(
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
@@ -171,16 +171,16 @@ public class IncomingJingleFileTransfer extends JingleFileTransfer implements In
171 } 171 }
172 }); 172 });
173 173
174 if (initialContent.getTransport(new JingleS5BTransportPayload()) != null) { 174 JingleS5BTransportPayload s5bTransport = initialContent.getTransport(new JingleS5BTransportPayload());
175 JingleS5BTransportPayload s5bTransport = initialContent.getTransport(new JingleS5BTransportPayload()); 175 JingleIBBTransportPayload ibbTransport = initialContent.getTransport(new JingleIBBTransportPayload());
176 if (s5bTransport != null) {
176 logger_.fine("Got S5B transport as initial payload.\n"); 177 logger_.fine("Got S5B transport as initial payload.\n");
177 setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), s5bTransport.getSessionID(), options)); 178 setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), s5bTransport.getSessionID(), options));
178 transporter.addRemoteCandidates(s5bTransport.getCandidates(), s5bTransport.getDstAddr()); 179 transporter.addRemoteCandidates(s5bTransport.getCandidates(), s5bTransport.getDstAddr());
179 setInternalState(State.GeneratingInitialLocalCandidates); 180 setInternalState(State.GeneratingInitialLocalCandidates);
180 transporter.startGeneratingLocalCandidates(); 181 transporter.startGeneratingLocalCandidates();
181 } 182 }
182 else if(initialContent.getTransport(new JingleIBBTransportPayload()) != null) { 183 else if(ibbTransport != null && options.isInBandAllowed()) {
183 JingleIBBTransportPayload ibbTransport = initialContent.getTransport(new JingleIBBTransportPayload());
184 logger_.fine("Got IBB transport as initial payload.\n"); 184 logger_.fine("Got IBB transport as initial payload.\n");
185 setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), ibbTransport.getSessionID(), options)); 185 setTransporter(transporterFactory.createResponderTransporter(getInitiator(), getResponder(), ibbTransport.getSessionID(), options));
186 186
@@ -189,8 +189,9 @@ public class IncomingJingleFileTransfer extends JingleFileTransfer implements In
189 session.sendAccept(getContentID(), initialContent.getDescriptions().get(0), ibbTransport); 189 session.sendAccept(getContentID(), initialContent.getDescriptions().get(0), ibbTransport);
190 } 190 }
191 else { 191 else {
192 // Can't happen, because the transfer would have been rejected automatically 192 // This might happen on incoming transfer which only list transport methods we are not allowed to use due to file-transfer options.
193 assert(false); 193 session.sendTerminate(JinglePayload.Reason.Type.UnsupportedTransports);
194 setFinishedState(FileTransfer.State.Type.Failed, new FileTransferError(FileTransferError.Type.PeerError));
194 } 195 }
195 } 196 }
196 197
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
@@ -179,10 +179,19 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
179 logger_.warning("Incorrect state\n"); 179 logger_.warning("Incorrect state\n");
180 return; 180 return;
181 } 181 }
182 182
183 setTransporter(transporterFactory.createInitiatorTransporter(getInitiator(), getResponder(), options)); 183 if (!options.isInBandAllowed() && !options.isDirectAllowed()
184 setInternalState(State.GeneratingInitialLocalCandidates); 184 && !options.isAssistedAllowed() && !options.isProxiedAllowed()) {
185 transporter.startGeneratingLocalCandidates(); 185 // Started outgoing file transfer while not supporting transport methods.
186 setFinishedState(FileTransfer.State.Type.Failed,
187 new FileTransferError(FileTransferError.Type.UnknownError));
188 }
189 else {
190 setTransporter(transporterFactory.createInitiatorTransporter(getInitiator(), getResponder(), options));
191 setInternalState(State.GeneratingInitialLocalCandidates);
192 transporter.startGeneratingLocalCandidates();
193 }
194
186 } 195 }
187 196
188 /** 197 /**
@@ -217,6 +226,13 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
217 setInternalState(State.TryingCandidates); 226 setInternalState(State.TryingCandidates);
218 transporter.startTryingRemoteCandidates(); 227 transporter.startTryingRemoteCandidates();
219 } 228 }
229 else if (transportPayload instanceof JingleIBBTransportPayload) {
230 JingleIBBTransportPayload ibbPayload = (JingleIBBTransportPayload) transportPayload;
231 int blockSize = ibbPayload.getBlockSize() != null ?
232 ibbPayload.getBlockSize().intValue() : DEFAULT_BLOCK_SIZE;
233 startTransferring(transporter.createIBBSendSession(ibbPayload.getSessionID(),
234 blockSize, stream));
235 }
220 else { 236 else {
221 logger_.fine("Unknown transport payload. Falling back.\n"); 237 logger_.fine("Unknown transport payload. Falling back.\n");
222 fallback(); 238 fallback();
@@ -310,14 +326,25 @@ public class OutgoingJingleFileTransfer extends JingleFileTransfer implements Ou
310 fileInfo.addHash(new HashElement("md5", new ByteArray())); 326 fileInfo.addHash(new HashElement("md5", new ByteArray()));
311 description.setFileInfo(fileInfo); 327 description.setFileInfo(fileInfo);
312 328
313 JingleS5BTransportPayload transport = new JingleS5BTransportPayload(); 329 JingleTransportPayload transport = null;
314 transport.setSessionID(s5bSessionID); 330 if (candidates.isEmpty()) {
315 transport.setMode(JingleS5BTransportPayload.Mode.TCPMode); 331 logger_.fine("no S5B candidate generated. Send IBB transport candidate.\n");
316 transport.setDstAddr(dstAddr); 332 JingleIBBTransportPayload ibbTransport = new JingleIBBTransportPayload();
317 for(JingleS5BTransportPayload.Candidate candidate : candidates) { 333 ibbTransport.setBlockSize(DEFAULT_BLOCK_SIZE);
318 transport.addCandidate(candidate); 334 ibbTransport.setSessionID(idGenerator.generateID());
319 logger_.fine("\t" + "S5B candidate: " + candidate.hostPort.toString() + "\n"); 335 transport = ibbTransport;
320 } 336 }
337 else {
338 JingleS5BTransportPayload s5bTransport = new JingleS5BTransportPayload();
339 s5bTransport.setSessionID(s5bSessionID);
340 s5bTransport.setMode(JingleS5BTransportPayload.Mode.TCPMode);
341 s5bTransport.setDstAddr(dstAddr);
342 for (JingleS5BTransportPayload.Candidate candidate : candidates) {
343 s5bTransport.addCandidate(candidate);
344 logger_.fine("\tS5B candidate: "+candidate.hostPort +"\n");
345 }
346 transport = s5bTransport;
347 }
321 setInternalState(State.WaitingForAccept); 348 setInternalState(State.WaitingForAccept);
322 session.sendInitiate(contentID, description, transport); 349 session.sendInitiate(contentID, description, transport);
323 } 350 }
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
@@ -126,6 +126,10 @@ public class SOCKS5BytestreamServerManager {
126 forwardPortRequest.stop(); 126 forwardPortRequest.stop();
127 forwardPortRequest = null; 127 forwardPortRequest = null;
128 } 128 }
129 if (unforwardPortRequest != null) {
130 unforwardPortRequest.stop();
131 unforwardPortRequest = null;
132 }
129 if (server != null) { 133 if (server != null) {
130 server.stop(); 134 server.stop();
131 server = null; 135 server = null;
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
@@ -98,20 +98,25 @@ public class OutgoingJingleFileTransferTest {
98 assertNotNull(description); 98 assertNotNull(description);
99 assertEquals(1048576,description.getFileInfo().getSize()); 99 assertEquals(1048576,description.getFileInfo().getSize());
100 100
101 JingleS5BTransportPayload transport = null; 101 JingleIBBTransportPayload transport = null;
102 if (call.payload instanceof JingleS5BTransportPayload) { 102 if (call.payload instanceof JingleIBBTransportPayload) {
103 transport = (JingleS5BTransportPayload) call.payload; 103 transport = (JingleIBBTransportPayload) call.payload;
104 }
105 else {
106 System.out.println(call.payload.getClass().getName());
104 } 107 }
105 assertNotNull(transport); 108 assertNotNull(transport);
106 } 109 }
107 110
108 @Test 111 @Test
109 public void test_FallbackToIBBAfterFailingS5b() { 112 public void test_FallbackToIBBAfterFailingS5b() {
110 OutgoingJingleFileTransfer transfer = createTestling(); 113 OutgoingJingleFileTransfer transfer =
114 createTestling(new FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true));
111 transfer.start(); 115 transfer.start();
112 116
113 FakeJingleSession.InitiateCall call = getCall(FakeJingleSession.InitiateCall.class,0); 117 FakeJingleSession.InitiateCall call = getCall(FakeJingleSession.InitiateCall.class,0);
114 118
119 assertTrue(call.payload instanceof JingleS5BTransportPayload);
115 fakeJingleSession.handleSessionAcceptReceived(call.id, call.description, call.payload); 120 fakeJingleSession.handleSessionAcceptReceived(call.id, call.description, call.payload);
116 121
117 // Send candidate failure 122 // Send candidate failure
@@ -211,13 +216,16 @@ public class OutgoingJingleFileTransferTest {
211 } 216 }
212 217
213 private OutgoingJingleFileTransfer createTestling() { 218 private OutgoingJingleFileTransfer createTestling() {
219 return createTestling(new FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false));
220 }
221
222 private OutgoingJingleFileTransfer createTestling(FileTransferOptions options) {
214 JID to = new JID("test@foo.com/bla"); 223 JID to = new JID("test@foo.com/bla");
215 JingleFileTransferFileInfo fileInfo = new JingleFileTransferFileInfo(); 224 JingleFileTransferFileInfo fileInfo = new JingleFileTransferFileInfo();
216 fileInfo.setDescription("some file"); 225 fileInfo.setDescription("some file");
217 fileInfo.setName("test.bin"); 226 fileInfo.setName("test.bin");
218 fileInfo.addHash(new HashElement("sha-1", new ByteArray())); 227 fileInfo.addHash(new HashElement("sha-1", new ByteArray()));
219 fileInfo.setSize(1024 * 1024); 228 fileInfo.setSize(1024 * 1024);
220 FileTransferOptions options = (new FileTransferOptions()).withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false);
221 return new OutgoingJingleFileTransfer(to, fakeJingleSession, stream, 229 return new OutgoingJingleFileTransfer(to, fakeJingleSession, stream,
222 ftTransporterFactory, timeFactory, idGen, fileInfo, options, crypto); 230 ftTransporterFactory, timeFactory, idGen, fileInfo, options, crypto);
223 } 231 }