mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-27 14:32:06 +01:00
progress
This commit is contained in:
parent
a395b11ee9
commit
59a600a0b6
10 changed files with 217 additions and 33 deletions
|
@ -126,6 +126,11 @@ public class IncomingJingleFileOffer extends JingleFileTransferSession implement
|
||||||
return jutil.createAck(transportAccept);
|
return jutil.createAck(transportAccept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransportMethodFailed(String namespace) {
|
||||||
|
//Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void acceptIncomingFileOffer(final Jingle request, final File target) {
|
public void acceptIncomingFileOffer(final Jingle request, final File target) {
|
||||||
LOGGER.log(Level.INFO, "Client accepted incoming file offer. Try to start receiving.");
|
LOGGER.log(Level.INFO, "Client accepted incoming file offer. Try to start receiving.");
|
||||||
|
|
|
@ -41,4 +41,9 @@ public class JingleFileRequest extends JingleFileTransferSession {
|
||||||
return new JingleFileRequest(connection, request.getInitiator(), connection.getUser().asFullJidOrThrow(), Role.responder,
|
return new JingleFileRequest(connection, request.getInitiator(), connection.getUser().asFullJidOrThrow(), Role.responder,
|
||||||
request.getSid());
|
request.getSid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransportMethodFailed(String namespace) {
|
||||||
|
//Not implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,8 +118,8 @@ public final class JingleFileTransferManager extends Manager implements JingleHa
|
||||||
} //File Request
|
} //File Request
|
||||||
else if (content.getSenders() == JingleContent.Senders.responder) {
|
else if (content.getSenders() == JingleContent.Senders.responder) {
|
||||||
return JingleFileRequest.createIncomingFileRequest(connection(), request);
|
return JingleFileRequest.createIncomingFileRequest(connection(), request);
|
||||||
|
}
|
||||||
} else {
|
else {
|
||||||
// If senders is neither initiator, nor responder, consider session malformed.
|
// If senders is neither initiator, nor responder, consider session malformed.
|
||||||
// See XEP-0166 §6.3 Example 16 and XEP-0234 §4.1
|
// See XEP-0166 §6.3 Example 16 and XEP-0234 §4.1
|
||||||
LOGGER.log(Level.WARNING, "Jingle has invalid sender value. Only initiator and responder are allowed.");
|
LOGGER.log(Level.WARNING, "Jingle has invalid sender value. Only initiator and responder are allowed.");
|
||||||
|
|
|
@ -27,6 +27,7 @@ import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
||||||
import org.jivesoftware.smackx.jingle.JingleManager;
|
import org.jivesoftware.smackx.jingle.JingleManager;
|
||||||
import org.jivesoftware.smackx.jingle.JingleTransportMethodManager;
|
import org.jivesoftware.smackx.jingle.JingleTransportMethodManager;
|
||||||
|
import org.jivesoftware.smackx.jingle.JingleUtil;
|
||||||
import org.jivesoftware.smackx.jingle.Role;
|
import org.jivesoftware.smackx.jingle.Role;
|
||||||
import org.jivesoftware.smackx.jingle.element.Jingle;
|
import org.jivesoftware.smackx.jingle.element.Jingle;
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleContent;
|
import org.jivesoftware.smackx.jingle.element.JingleContent;
|
||||||
|
@ -161,4 +162,38 @@ public class OutgoingJingleFileOffer extends JingleFileTransferSession {
|
||||||
|
|
||||||
return jutil.createAck(transportReplace);
|
return jutil.createAck(transportReplace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IQ handleTransportAccept(Jingle transportAccept)
|
||||||
|
throws SmackException.NotConnectedException, InterruptedException {
|
||||||
|
return handleSessionAccept(transportAccept);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransportMethodFailed(String namespace) {
|
||||||
|
state = State.pending;
|
||||||
|
JingleContent content = contents.get(0);
|
||||||
|
failedTransportMethods.add(namespace);
|
||||||
|
JingleTransportMethodManager tm = JingleTransportMethodManager.getInstanceFor(getConnection());
|
||||||
|
JingleTransportManager<?> next = tm.getBestAvailableTransportManager(failedTransportMethods);
|
||||||
|
|
||||||
|
if (next == null) {
|
||||||
|
//Failure
|
||||||
|
try {
|
||||||
|
new JingleUtil(getConnection()).sendSessionTerminateUnsupportedTransports(getRemote(), getSessionId());
|
||||||
|
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Could not send session-terminate.", e);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Replace transport
|
||||||
|
this.transportSession = next.transportSession(this);
|
||||||
|
try {
|
||||||
|
jutil.sendTransportReplace(getRemote(), getInitiator(), getSessionId(), content.getCreator(), content.getName(),
|
||||||
|
transportSession.createTransport());
|
||||||
|
} catch (SmackException.NotConnectedException | SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException e) {
|
||||||
|
LOGGER.log(Level.WARNING, "Could not send transport-replace.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class ReceiveTask implements Runnable {
|
||||||
byte[] filebuf = new byte[transfer.getSize()];
|
byte[] filebuf = new byte[transfer.getSize()];
|
||||||
int read = 0;
|
int read = 0;
|
||||||
byte[] bufbuf = new byte[2048];
|
byte[] bufbuf = new byte[2048];
|
||||||
|
LOGGER.log(Level.INFO, "Begin receiving.");
|
||||||
while (read < filebuf.length) {
|
while (read < filebuf.length) {
|
||||||
int r = inputStream.read(bufbuf);
|
int r = inputStream.read(bufbuf);
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
|
@ -68,6 +68,7 @@ public class ReceiveTask implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.write(filebuf);
|
outputStream.write(filebuf);
|
||||||
|
LOGGER.log(Level.INFO, "File successfully received.");
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOGGER.log(Level.SEVERE, "Error while receiving data: ", e);
|
LOGGER.log(Level.SEVERE, "Error while receiving data: ", e);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jivesoftware.smackx.jingle;
|
package org.jivesoftware.smackx.jingle;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
@ -35,6 +36,7 @@ import org.jxmpp.jid.FullJid;
|
||||||
|
|
||||||
public abstract class JingleSession implements JingleSessionHandler {
|
public abstract class JingleSession implements JingleSessionHandler {
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleSession.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleSession.class.getName());
|
||||||
|
protected HashSet<String> failedTransportMethods = new HashSet<>();
|
||||||
|
|
||||||
protected final FullJid local;
|
protected final FullJid local;
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ public abstract class JingleSession implements JingleSessionHandler {
|
||||||
|
|
||||||
protected final List<JingleContent> contents = new ArrayList<>();
|
protected final List<JingleContent> contents = new ArrayList<>();
|
||||||
|
|
||||||
protected ExecutorService threadPool = Executors.newSingleThreadExecutor();
|
protected static ExecutorService threadPool = Executors.newSingleThreadExecutor();
|
||||||
protected ArrayList<Future<?>> queued = new ArrayList<>();
|
protected ArrayList<Future<?>> queued = new ArrayList<>();
|
||||||
protected JingleTransportSession<?> transportSession;
|
protected JingleTransportSession<?> transportSession;
|
||||||
|
|
||||||
|
@ -220,7 +222,7 @@ public abstract class JingleSession implements JingleSessionHandler {
|
||||||
return IQ.createResultIQ(securityInfo);
|
return IQ.createResultIQ(securityInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IQ handleTransportAccept(Jingle transportAccept) {
|
protected IQ handleTransportAccept(Jingle transportAccept) throws SmackException.NotConnectedException, InterruptedException {
|
||||||
return IQ.createResultIQ(transportAccept);
|
return IQ.createResultIQ(transportAccept);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,4 +238,6 @@ public abstract class JingleSession implements JingleSessionHandler {
|
||||||
|
|
||||||
public abstract XMPPConnection getConnection();
|
public abstract XMPPConnection getConnection();
|
||||||
|
|
||||||
|
public abstract void onTransportMethodFailed(String namespace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.jivesoftware.smackx.jingle;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import org.jivesoftware.smack.Manager;
|
import org.jivesoftware.smack.Manager;
|
||||||
|
@ -106,4 +107,26 @@ public final class JingleTransportMethodManager extends Manager {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JingleTransportManager<?> getBestAvailableTransportManager(Set<String> except) {
|
||||||
|
JingleTransportManager<?> tm;
|
||||||
|
for (String ns : transportPreference) {
|
||||||
|
tm = getTransportManager(ns);
|
||||||
|
if (tm != null) {
|
||||||
|
if (except.contains(tm.getNamespace())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String ns : transportManagers.keySet()) {
|
||||||
|
if (except.contains(ns)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return getTransportManager(ns);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTr
|
||||||
import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportInfo;
|
import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransportInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by vanitas on 26.06.17.
|
* Handler that handles Jingle Socks5Bytestream transports (XEP-0260).
|
||||||
*/
|
*/
|
||||||
public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BTransport> {
|
public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BTransport> {
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleS5BTransportSession.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleS5BTransportSession.class.getName());
|
||||||
|
@ -78,9 +78,9 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
Socks5Utils.createDigest(sid, jingleSession.getLocal(), jingleSession.getRemote()));
|
Socks5Utils.createDigest(sid, jingleSession.getLocal(), jingleSession.getRemote()));
|
||||||
|
|
||||||
//Local host
|
//Local host
|
||||||
//for (Bytestream.StreamHost host : transportManager().getLocalStreamHosts()) {
|
for (Bytestream.StreamHost host : transportManager().getLocalStreamHosts()) {
|
||||||
// jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 100));
|
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 100, JingleS5BTransportCandidate.Type.direct));
|
||||||
//}
|
}
|
||||||
|
|
||||||
List<Bytestream.StreamHost> remoteHosts;
|
List<Bytestream.StreamHost> remoteHosts;
|
||||||
try {
|
try {
|
||||||
|
@ -91,7 +91,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Bytestream.StreamHost host : remoteHosts) {
|
for (Bytestream.StreamHost host : remoteHosts) {
|
||||||
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 0));
|
jb.addTransportCandidate(new JingleS5BTransportCandidate(host, 0, JingleS5BTransportCandidate.Type.proxy));
|
||||||
}
|
}
|
||||||
|
|
||||||
return jb.build();
|
return jb.build();
|
||||||
|
@ -222,7 +222,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
}
|
}
|
||||||
|
|
||||||
public IQ handleCandidateActivate(Jingle jingle) {
|
public IQ handleCandidateActivate(Jingle jingle) {
|
||||||
LOGGER.log(Level.INFO, "handleChandidateActivate");
|
LOGGER.log(Level.INFO, "handleCandidateActivate");
|
||||||
Socks5BytestreamSession bs = new Socks5BytestreamSession(ourChoice.socket,
|
Socks5BytestreamSession bs = new Socks5BytestreamSession(ourChoice.socket,
|
||||||
ourChoice.candidate.getJid().asBareJid().equals(jingleSession.getRemote().asBareJid()));
|
ourChoice.candidate.getJid().asBareJid().equals(jingleSession.getRemote().asBareJid()));
|
||||||
callback.onSessionInitiated(bs);
|
callback.onSessionInitiated(bs);
|
||||||
|
@ -256,7 +256,7 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
|
|
||||||
if (ourChoice == CANDIDATE_FAILURE && theirChoice == CANDIDATE_FAILURE) {
|
if (ourChoice == CANDIDATE_FAILURE && theirChoice == CANDIDATE_FAILURE) {
|
||||||
LOGGER.log(Level.INFO, "Failure.");
|
LOGGER.log(Level.INFO, "Failure.");
|
||||||
// TODO: Transport failed.
|
jingleSession.onTransportMethodFailed(getNamespace());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,19 +278,18 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
nominated = theirChoice;
|
nominated = theirChoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ourExternalProxy = !nominated.candidate.getJid().asBareJid().equals(jingleSession.getLocal().asBareJid());
|
|
||||||
boolean theirExternalProxy = !nominated.candidate.getJid().asBareJid().equals(jingleSession.getRemote().asBareJid());
|
|
||||||
|
|
||||||
if (nominated == theirChoice) {
|
if (nominated == theirChoice) {
|
||||||
LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used.");
|
LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used.");
|
||||||
|
boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
|
||||||
try {
|
try {
|
||||||
nominated = connectToOurCandidate(nominated.candidate);
|
nominated = connectToOurCandidate(nominated.candidate);
|
||||||
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
|
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
|
||||||
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
|
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
|
||||||
|
//TODO: Proxy-Error
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ourExternalProxy) {
|
if (isProxy) {
|
||||||
LOGGER.log(Level.INFO, "Is external proxy. Activate it.");
|
LOGGER.log(Level.INFO, "Is external proxy. Activate it.");
|
||||||
Bytestream activate = new Bytestream(ourProposal.getStreamId());
|
Bytestream activate = new Bytestream(ourProposal.getStreamId());
|
||||||
activate.setMode(null);
|
activate.setMode(null);
|
||||||
|
@ -304,7 +303,6 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
LOGGER.log(Level.WARNING, "Could not activate proxy.", e);
|
LOGGER.log(Level.WARNING, "Could not activate proxy.", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.log(Level.INFO, "Send candidate-activate.");
|
LOGGER.log(Level.INFO, "Send candidate-activate.");
|
||||||
Jingle candidateActivate = transportManager().createCandidateActivated(
|
Jingle candidateActivate = transportManager().createCandidateActivated(
|
||||||
|
@ -318,18 +316,20 @@ public class JingleS5BTransportSession extends JingleTransportSession<JingleS5BT
|
||||||
LOGGER.log(Level.WARNING, "Could not send candidate-activated", e);
|
LOGGER.log(Level.WARNING, "Could not send candidate-activated", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOGGER.log(Level.INFO, "Start transmission.");
|
LOGGER.log(Level.INFO, "Start transmission.");
|
||||||
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, !ourExternalProxy);
|
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, !isProxy);
|
||||||
callback.onSessionInitiated(bs);
|
callback.onSessionInitiated(bs);
|
||||||
|
|
||||||
}
|
}
|
||||||
//Our choice
|
//Our choice
|
||||||
else {
|
else {
|
||||||
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
|
LOGGER.log(Level.INFO, "Our choice, so their candidate was used.");
|
||||||
if (!theirExternalProxy) {
|
boolean isProxy = nominated.candidate.getType() == JingleS5BTransportCandidate.Type.proxy;
|
||||||
|
if (!isProxy) {
|
||||||
LOGGER.log(Level.INFO, "Direct connection.");
|
LOGGER.log(Level.INFO, "Direct connection.");
|
||||||
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, !ourExternalProxy);
|
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.socket, true);
|
||||||
callback.onSessionInitiated(bs);
|
callback.onSessionInitiated(bs);
|
||||||
} else {
|
} else {
|
||||||
LOGGER.log(Level.INFO, "Our choice was their external proxy. wait for candidate-activate.");
|
LOGGER.log(Level.INFO, "Our choice was their external proxy. wait for candidate-activate.");
|
||||||
|
|
|
@ -66,8 +66,8 @@ public final class JingleS5BTransportCandidate extends JingleContentTransportCan
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JingleS5BTransportCandidate(Bytestream.StreamHost streamHost, int priority) {
|
public JingleS5BTransportCandidate(Bytestream.StreamHost streamHost, int priority, Type type) {
|
||||||
this(StringUtils.randomString(24), streamHost.getAddress(), streamHost.getJID(), streamHost.getPort(), priority, Type.proxy);
|
this(StringUtils.randomString(24), streamHost.getAddress(), streamHost.getJID(), streamHost.getPort(), priority, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
package org.jivesoftware.smackx.jingle_filetransfer;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.fail;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
|
||||||
|
import org.jivesoftware.smackx.jingle.element.Jingle;
|
||||||
|
import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingFileOfferCallback;
|
||||||
|
import org.jivesoftware.smackx.jingle_filetransfer.listener.JingleFileTransferOfferListener;
|
||||||
|
|
||||||
|
import org.igniterealtime.smack.inttest.AbstractSmackIntegrationTest;
|
||||||
|
import org.igniterealtime.smack.inttest.SmackIntegrationTest;
|
||||||
|
import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.jxmpp.jid.FullJid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by vanitas on 29.06.17.
|
||||||
|
*/
|
||||||
|
public class FileTransferTest extends AbstractSmackIntegrationTest {
|
||||||
|
|
||||||
|
private static final File tempDir;
|
||||||
|
|
||||||
|
static {
|
||||||
|
String userHome = System.getProperty("user.home");
|
||||||
|
if (userHome != null) {
|
||||||
|
File f = new File(userHome);
|
||||||
|
tempDir = new File(f, ".config/smack-integration-test/");
|
||||||
|
} else {
|
||||||
|
tempDir = new File("int_test_jingle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileTransferTest(SmackIntegrationTestEnvironment environment) {
|
||||||
|
super(environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SmackIntegrationTest
|
||||||
|
public void basicFileTransferTest() {
|
||||||
|
|
||||||
|
FullJid alice = conOne.getUser().asFullJidOrThrow();
|
||||||
|
FullJid bob = conTwo.getUser().asFullJidOrThrow();
|
||||||
|
|
||||||
|
File source = prepareNewTestFile("source");
|
||||||
|
final File target = new File(tempDir, "target");
|
||||||
|
|
||||||
|
JingleFileTransferManager aftm = JingleFileTransferManager.getInstanceFor(conOne);
|
||||||
|
JingleFileTransferManager bftm = JingleFileTransferManager.getInstanceFor(conTwo);
|
||||||
|
|
||||||
|
bftm.addJingleFileTransferOfferListener(new JingleFileTransferOfferListener() {
|
||||||
|
@Override
|
||||||
|
public void onFileOffer(Jingle request, IncomingFileOfferCallback callback) {
|
||||||
|
callback.acceptIncomingFileOffer(request, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
aftm.sendFile(bob, source);
|
||||||
|
} catch (InterruptedException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] sBytes = new byte[(int) source.length()];
|
||||||
|
byte[] tBytes = new byte[(int) target.length()];
|
||||||
|
try {
|
||||||
|
FileInputStream fi = new FileInputStream(source);
|
||||||
|
fi.read(sBytes);
|
||||||
|
fi.close();
|
||||||
|
fi = new FileInputStream(target);
|
||||||
|
fi.read(tBytes);
|
||||||
|
fi.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Could not read files.");
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertArrayEquals(sBytes, tBytes);
|
||||||
|
LOGGER.log(Level.INFO, "SUCCESSFULLY SENT AND RECEIVED");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private File prepareNewTestFile(String name) {
|
||||||
|
File testFile = new File(tempDir, name);
|
||||||
|
try {
|
||||||
|
if (!testFile.exists()) {
|
||||||
|
testFile.createNewFile();
|
||||||
|
}
|
||||||
|
FileOutputStream fo = new FileOutputStream(testFile);
|
||||||
|
byte[] rand = new byte[16000];
|
||||||
|
INSECURE_RANDOM.nextBytes(rand);
|
||||||
|
fo.write(rand);
|
||||||
|
fo.close();
|
||||||
|
return testFile;
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public void cleanup() {
|
||||||
|
Socks5Proxy.getSocks5Proxy().stop();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue