Some work on Jingle File Transfer

This commit is contained in:
vanitasvitae 2017-07-25 20:25:36 +02:00
parent 438fc0e94b
commit c0e5fcf737
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
10 changed files with 166 additions and 43 deletions

View File

@ -1,7 +1,38 @@
package org.jivesoftware.smackx.jft.internal;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
/**
* Created by vanitas on 22.07.17.
*/
public class JingleFileOffer extends JingleFileTransfer {
private static final Logger LOGGER = Logger.getLogger(JingleFileOffer.class.getName());
private File file;
public JingleFileOffer(File file) {
super();
this.file = file;
}
@Override
public void onTransportReady(BytestreamSession bytestreamSession) {
OutputStream outputStream;
try {
outputStream = bytestreamSession.getOutputStream();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error retrieving outputStream: " + e, e);
return;
}
}
}

View File

@ -1,7 +1,14 @@
package org.jivesoftware.smackx.jft.internal;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
/**
* Created by vanitas on 22.07.17.
*/
public class JingleFileRequest extends JingleFileTransfer {
@Override
public void onTransportReady(BytestreamSession bytestreamSession) {
}
}

View File

@ -17,6 +17,8 @@
package org.jivesoftware.smackx.jingle_filetransfer;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.Role;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jxmpp.jid.FullJid;

View File

@ -0,0 +1,13 @@
package org.jivesoftware.smackx.jingle.exception;
/**
* Created by vanitas on 25.07.17.
*/
public class FailedTransportException extends Exception {
protected static final long serialVersionUID = 1L;
public FailedTransportException(Throwable throwable) {
super(throwable);
}
}

View File

@ -23,6 +23,7 @@ import java.util.List;
import java.util.Set;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.adapter.JingleDescriptionAdapter;
import org.jivesoftware.smackx.jingle.adapter.JingleTransportAdapter;
@ -176,6 +177,20 @@ public class JingleContent {
}
}
public void onTransportReady() {
BytestreamSession bytestreamSession = transport.getBytestreamSession();
if (bytestreamSession == null) {
throw new AssertionError("bytestreamSession MUST NOT be null at this point.");
}
description.onTransportReady(bytestreamSession);
}
public void onTransportFailed(Exception e) {
}
public static String randomName() {
return "cont-" + StringUtils.randomString(16);
}

View File

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.internal;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
/**
@ -36,4 +37,6 @@ public abstract class JingleDescription<D extends JingleContentDescriptionElemen
public JingleContent getParent() {
return parent;
}
public abstract void onTransportReady(BytestreamSession bytestreamSession);
}

View File

@ -21,10 +21,10 @@ import java.util.List;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle.transport.BytestreamSessionEstablishedListener;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
/**
* Class that represents a contents transport component.
@ -37,6 +37,8 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
private JingleTransport peersProposal;
private boolean isPeersProposal;
protected BytestreamSession bytestreamSession;
public abstract D getElement();
public void addCandidate(JingleTransportCandidate<?> candidate) {
@ -72,11 +74,11 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
public abstract String getNamespace();
public abstract void establishIncomingBytestreamSession(BytestreamSessionEstablishedListener listener,
XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException;
public abstract void establishIncomingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException;
public abstract void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener,
XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException;
public abstract void establishOutgoingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException;
public void setPeersProposal(JingleTransport peersProposal) {
this.peersProposal = peersProposal;
@ -102,4 +104,8 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
public JingleContent getParent() {
return parent;
}
public BytestreamSession getBytestreamSession() {
return bytestreamSession;
}
}

View File

@ -20,16 +20,16 @@ import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.bytestreams.BytestreamListener;
import org.jivesoftware.smackx.bytestreams.BytestreamRequest;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamListener;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamRequest;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle.internal.JingleSession;
import org.jivesoftware.smackx.jingle.internal.JingleTransport;
import org.jivesoftware.smackx.jingle.internal.JingleTransportCandidate;
import org.jivesoftware.smackx.jingle.transport.BytestreamSessionEstablishedListener;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.internal.JingleSession;
import org.jivesoftware.smackx.jingle.transport.jingle_ibb.element.JingleIBBTransportElement;
/**
@ -71,38 +71,48 @@ public class JingleIBBTransport extends JingleTransport<JingleIBBTransportElemen
}
@Override
public void establishIncomingBytestreamSession(final BytestreamSessionEstablishedListener listener, final XMPPConnection connection) {
public void establishIncomingBytestreamSession(final XMPPConnection connection) {
final JingleSession session = getParent().getParent();
InBandBytestreamManager.getByteStreamManager(connection)
.addIncomingBytestreamListener(new BytestreamListener() {
@Override
public void incomingBytestreamRequest(BytestreamRequest request) {
if (request.getFrom().asFullJidIfPossible().equals(session.getPeer())
&& request.getSessionID().equals(getSid())) {
BytestreamSession bytestreamSession;
try {
bytestreamSession = request.accept();
} catch (InterruptedException | SmackException | XMPPException.XMPPErrorException e) {
listener.onBytestreamSessionFailed(e);
return;
}
listener.onBytestreamSessionEstablished(bytestreamSession);
}
final InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection);
InBandBytestreamListener bytestreamListener = new InBandBytestreamListener() {
@Override
public void incomingBytestreamRequest(InBandBytestreamRequest request) {
if (request.getFrom().asFullJidIfPossible().equals(session.getPeer())
&& request.getSessionID().equals(getSid())) {
BytestreamSession bytestreamSession;
inBandBytestreamManager.removeIncomingBytestreamListener(this);
try {
bytestreamSession = request.accept();
} catch (InterruptedException | SmackException e) {
getParent().onTransportFailed(e);
return;
}
});
JingleIBBTransport.this.bytestreamSession = bytestreamSession;
getParent().onTransportReady();
}
}
};
InBandBytestreamManager.getByteStreamManager(connection)
.addIncomingBytestreamListener(bytestreamListener);
}
@Override
public void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection) {
public void establishOutgoingBytestreamSession(XMPPConnection connection) {
JingleSession session = getParent().getParent();
InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection);
inBandBytestreamManager.setDefaultBlockSize(blockSize);
try {
BytestreamSession bytestreamSession = inBandBytestreamManager.establishSession(session.getPeer(), getSid());
listener.onBytestreamSessionEstablished(bytestreamSession);
JingleIBBTransport.this.bytestreamSession = inBandBytestreamManager.establishSession(session.getPeer(), getSid());
getParent().onTransportReady();
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) {
listener.onBytestreamSessionFailed(e);
getParent().onTransportFailed(e);
}
}

View File

@ -35,11 +35,11 @@ import org.jivesoftware.smackx.bytestreams.socks5.packet.Bytestream;
import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
import org.jivesoftware.smackx.jingle.exception.FailedTransportException;
import org.jivesoftware.smackx.jingle.internal.JingleContent;
import org.jivesoftware.smackx.jingle.internal.JingleSession;
import org.jivesoftware.smackx.jingle.internal.JingleTransport;
import org.jivesoftware.smackx.jingle.internal.JingleTransportCandidate;
import org.jivesoftware.smackx.jingle.transport.BytestreamSessionEstablishedListener;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportCandidateElement;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportElement;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportInfoElement;
@ -124,18 +124,18 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
}
@Override
public void establishIncomingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection)
public void establishIncomingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException {
establishBytestreamSession(listener, connection);
establishBytestreamSession(connection);
}
@Override
public void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection)
public void establishOutgoingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException {
establishBytestreamSession(listener, connection);
establishBytestreamSession(connection);
}
void establishBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection)
void establishBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException {
Socks5Proxy.getSocks5Proxy().addTransfer(dstAddr);
JingleS5BTransportManager transportManager = JingleS5BTransportManager.getInstanceFor(connection);
@ -181,7 +181,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
if (getSelectedCandidate() == CANDIDATE_FAILURE && peers.getSelectedCandidate() == CANDIDATE_FAILURE) {
LOGGER.log(Level.INFO, "Failure.");
//jingleSession.onTransportMethodFailed(getNamespace());
getParent().onTransportFailed(new FailedTransportException(null));
return;
}
@ -190,6 +190,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
//Determine nominated candidate.
JingleS5BTransportCandidate nominated;
if (getSelectedCandidate() != CANDIDATE_FAILURE && peers.getSelectedCandidate() != CANDIDATE_FAILURE) {
if (getSelectedCandidate().getPriority() > peers.getSelectedCandidate().getPriority()) {
nominated = getSelectedCandidate();
} else if (getSelectedCandidate().getPriority() < peers.getSelectedCandidate().getPriority()) {
@ -197,6 +198,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
} else {
nominated = getParent().getParent().isInitiator() ? getSelectedCandidate() : peers.getSelectedCandidate();
}
} else if (getSelectedCandidate() != CANDIDATE_FAILURE) {
nominated = getSelectedCandidate();
} else {
@ -204,17 +206,20 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
}
if (nominated == peers.getSelectedCandidate()) {
LOGGER.log(Level.INFO, "Their choice, so our proposed candidate is used.");
boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
try {
nominated = nominated.connect(MAX_TIMEOUT);
} catch (InterruptedException | IOException | XMPPException | SmackException | TimeoutException e) {
LOGGER.log(Level.INFO, "Could not connect to our candidate.", e);
//TODO: Proxy-Error
getParent().onTransportFailed(new S5BTransportException.CandidateError(e));
return;
}
if (isProxy) {
LOGGER.log(Level.INFO, "Is external proxy. Activate it.");
Bytestream activate = new Bytestream(getSid());
activate.setMode(null);
@ -227,6 +232,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
getParent().getParent().getJingleManager().getConnection().createStanzaCollectorAndSend(activate).nextResultOrThrow();
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
LOGGER.log(Level.WARNING, "Could not activate proxy.", e);
getParent().onTransportFailed(new S5BTransportException.ProxyError(e));
return;
}
@ -238,13 +244,14 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
.nextResultOrThrow();
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
LOGGER.log(Level.WARNING, "Could not send candidate-activated", e);
getParent().onTransportFailed(new S5BTransportException.ProxyError(e));
return;
}
}
LOGGER.log(Level.INFO, "Start transmission.");
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.getSocket(), !isProxy);
//callback.onSessionInitiated(bs);
this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), !isProxy);
getParent().onTransportReady();
}
//Our choice
@ -253,8 +260,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
if (!isProxy) {
LOGGER.log(Level.INFO, "Direct connection.");
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.getSocket(), true);
//callback.onSessionInitiated(bs);
this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), true);
getParent().onTransportReady();
} else {
LOGGER.log(Level.INFO, "Our choice was their external proxy. wait for candidate-activate.");
}

View File

@ -0,0 +1,29 @@
package org.jivesoftware.smackx.jingle.transport.jingle_s5b;
import org.jivesoftware.smackx.jingle.exception.FailedTransportException;
/**
* Created by vanitas on 25.07.17.
*/
public class S5BTransportException extends FailedTransportException {
protected static final long serialVersionUID = 1L;
private S5BTransportException(Throwable throwable) {
super(throwable);
}
public static class CandidateError extends S5BTransportException {
public CandidateError(Throwable throwable) {
super(throwable);
}
}
public static class ProxyError extends S5BTransportException {
public ProxyError(Throwable throwable) {
super(throwable);
}
}
}