1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-23 20:42:06 +01:00

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; 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. * Created by vanitas on 22.07.17.
*/ */
public class JingleFileOffer extends JingleFileTransfer { 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; package org.jivesoftware.smackx.jft.internal;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
/** /**
* Created by vanitas on 22.07.17. * Created by vanitas on 22.07.17.
*/ */
public class JingleFileRequest extends JingleFileTransfer { public class JingleFileRequest extends JingleFileTransfer {
@Override
public void onTransportReady(BytestreamSession bytestreamSession) {
}
} }

View file

@ -17,6 +17,8 @@
package org.jivesoftware.smackx.jingle_filetransfer; package org.jivesoftware.smackx.jingle_filetransfer;
import org.jivesoftware.smack.XMPPConnection; 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.jivesoftware.smackx.jingle.element.JingleElement;
import org.jxmpp.jid.FullJid; 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 java.util.Set;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleManager;
import org.jivesoftware.smackx.jingle.adapter.JingleDescriptionAdapter; import org.jivesoftware.smackx.jingle.adapter.JingleDescriptionAdapter;
import org.jivesoftware.smackx.jingle.adapter.JingleTransportAdapter; 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() { public static String randomName() {
return "cont-" + StringUtils.randomString(16); return "cont-" + StringUtils.randomString(16);
} }

View file

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.jingle.internal; package org.jivesoftware.smackx.jingle.internal;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement; import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
/** /**
@ -36,4 +37,6 @@ public abstract class JingleDescription<D extends JingleContentDescriptionElemen
public JingleContent getParent() { public JingleContent getParent() {
return parent; 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.SmackException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement; 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.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement;
/** /**
* Class that represents a contents transport component. * Class that represents a contents transport component.
@ -37,6 +37,8 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
private JingleTransport peersProposal; private JingleTransport peersProposal;
private boolean isPeersProposal; private boolean isPeersProposal;
protected BytestreamSession bytestreamSession;
public abstract D getElement(); public abstract D getElement();
public void addCandidate(JingleTransportCandidate<?> candidate) { public void addCandidate(JingleTransportCandidate<?> candidate) {
@ -72,11 +74,11 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
public abstract String getNamespace(); public abstract String getNamespace();
public abstract void establishIncomingBytestreamSession(BytestreamSessionEstablishedListener listener, public abstract void establishIncomingBytestreamSession(XMPPConnection connection)
XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException; throws SmackException.NotConnectedException, InterruptedException;
public abstract void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener, public abstract void establishOutgoingBytestreamSession(XMPPConnection connection)
XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException; throws SmackException.NotConnectedException, InterruptedException;
public void setPeersProposal(JingleTransport peersProposal) { public void setPeersProposal(JingleTransport peersProposal) {
this.peersProposal = peersProposal; this.peersProposal = peersProposal;
@ -102,4 +104,8 @@ public abstract class JingleTransport<D extends JingleContentTransportElement> {
public JingleContent getParent() { public JingleContent getParent() {
return parent; 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.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.StringUtils; 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.BytestreamSession;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamListener;
import org.jivesoftware.smackx.bytestreams.ibb.InBandBytestreamManager; 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.element.JingleElement;
import org.jivesoftware.smackx.jingle.internal.JingleSession;
import org.jivesoftware.smackx.jingle.internal.JingleTransport; import org.jivesoftware.smackx.jingle.internal.JingleTransport;
import org.jivesoftware.smackx.jingle.internal.JingleTransportCandidate; import org.jivesoftware.smackx.jingle.internal.JingleTransportCandidate;
import org.jivesoftware.smackx.jingle.transport.BytestreamSessionEstablishedListener; 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; import org.jivesoftware.smackx.jingle.transport.jingle_ibb.element.JingleIBBTransportElement;
/** /**
@ -71,38 +71,48 @@ public class JingleIBBTransport extends JingleTransport<JingleIBBTransportElemen
} }
@Override @Override
public void establishIncomingBytestreamSession(final BytestreamSessionEstablishedListener listener, final XMPPConnection connection) { public void establishIncomingBytestreamSession(final XMPPConnection connection) {
final JingleSession session = getParent().getParent(); 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 { final InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection);
bytestreamSession = request.accept();
} catch (InterruptedException | SmackException | XMPPException.XMPPErrorException e) { InBandBytestreamListener bytestreamListener = new InBandBytestreamListener() {
listener.onBytestreamSessionFailed(e); @Override
return; public void incomingBytestreamRequest(InBandBytestreamRequest request) {
} if (request.getFrom().asFullJidIfPossible().equals(session.getPeer())
listener.onBytestreamSessionEstablished(bytestreamSession); && 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 @Override
public void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection) { public void establishOutgoingBytestreamSession(XMPPConnection connection) {
JingleSession session = getParent().getParent(); JingleSession session = getParent().getParent();
InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection); InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection);
inBandBytestreamManager.setDefaultBlockSize(blockSize); inBandBytestreamManager.setDefaultBlockSize(blockSize);
try { try {
BytestreamSession bytestreamSession = inBandBytestreamManager.establishSession(session.getPeer(), getSid()); JingleIBBTransport.this.bytestreamSession = inBandBytestreamManager.establishSession(session.getPeer(), getSid());
listener.onBytestreamSessionEstablished(bytestreamSession); getParent().onTransportReady();
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) { } 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.JingleManager;
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement; import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
import org.jivesoftware.smackx.jingle.element.JingleElement; 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.JingleContent;
import org.jivesoftware.smackx.jingle.internal.JingleSession; import org.jivesoftware.smackx.jingle.internal.JingleSession;
import org.jivesoftware.smackx.jingle.internal.JingleTransport; import org.jivesoftware.smackx.jingle.internal.JingleTransport;
import org.jivesoftware.smackx.jingle.internal.JingleTransportCandidate; 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.JingleS5BTransportCandidateElement;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportElement; import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportElement;
import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportInfoElement; import org.jivesoftware.smackx.jingle.transport.jingle_s5b.element.JingleS5BTransportInfoElement;
@ -124,18 +124,18 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
} }
@Override @Override
public void establishIncomingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection) public void establishIncomingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException { throws SmackException.NotConnectedException, InterruptedException {
establishBytestreamSession(listener, connection); establishBytestreamSession(connection);
} }
@Override @Override
public void establishOutgoingBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection) public void establishOutgoingBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException { throws SmackException.NotConnectedException, InterruptedException {
establishBytestreamSession(listener, connection); establishBytestreamSession(connection);
} }
void establishBytestreamSession(BytestreamSessionEstablishedListener listener, XMPPConnection connection) void establishBytestreamSession(XMPPConnection connection)
throws SmackException.NotConnectedException, InterruptedException { throws SmackException.NotConnectedException, InterruptedException {
Socks5Proxy.getSocks5Proxy().addTransfer(dstAddr); Socks5Proxy.getSocks5Proxy().addTransfer(dstAddr);
JingleS5BTransportManager transportManager = JingleS5BTransportManager.getInstanceFor(connection); JingleS5BTransportManager transportManager = JingleS5BTransportManager.getInstanceFor(connection);
@ -181,7 +181,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
if (getSelectedCandidate() == CANDIDATE_FAILURE && peers.getSelectedCandidate() == CANDIDATE_FAILURE) { if (getSelectedCandidate() == CANDIDATE_FAILURE && peers.getSelectedCandidate() == CANDIDATE_FAILURE) {
LOGGER.log(Level.INFO, "Failure."); LOGGER.log(Level.INFO, "Failure.");
//jingleSession.onTransportMethodFailed(getNamespace()); getParent().onTransportFailed(new FailedTransportException(null));
return; return;
} }
@ -190,6 +190,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
//Determine nominated candidate. //Determine nominated candidate.
JingleS5BTransportCandidate nominated; JingleS5BTransportCandidate nominated;
if (getSelectedCandidate() != CANDIDATE_FAILURE && peers.getSelectedCandidate() != CANDIDATE_FAILURE) { if (getSelectedCandidate() != CANDIDATE_FAILURE && peers.getSelectedCandidate() != CANDIDATE_FAILURE) {
if (getSelectedCandidate().getPriority() > peers.getSelectedCandidate().getPriority()) { if (getSelectedCandidate().getPriority() > peers.getSelectedCandidate().getPriority()) {
nominated = getSelectedCandidate(); nominated = getSelectedCandidate();
} else if (getSelectedCandidate().getPriority() < peers.getSelectedCandidate().getPriority()) { } else if (getSelectedCandidate().getPriority() < peers.getSelectedCandidate().getPriority()) {
@ -197,6 +198,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
} else { } else {
nominated = getParent().getParent().isInitiator() ? getSelectedCandidate() : peers.getSelectedCandidate(); nominated = getParent().getParent().isInitiator() ? getSelectedCandidate() : peers.getSelectedCandidate();
} }
} else if (getSelectedCandidate() != CANDIDATE_FAILURE) { } else if (getSelectedCandidate() != CANDIDATE_FAILURE) {
nominated = getSelectedCandidate(); nominated = getSelectedCandidate();
} else { } else {
@ -204,17 +206,20 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
} }
if (nominated == peers.getSelectedCandidate()) { if (nominated == peers.getSelectedCandidate()) {
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.getType() == JingleS5BTransportCandidateElement.Type.proxy; boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
try { try {
nominated = nominated.connect(MAX_TIMEOUT); nominated = nominated.connect(MAX_TIMEOUT);
} 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 getParent().onTransportFailed(new S5BTransportException.CandidateError(e));
return; return;
} }
if (isProxy) { if (isProxy) {
LOGGER.log(Level.INFO, "Is external proxy. Activate it."); LOGGER.log(Level.INFO, "Is external proxy. Activate it.");
Bytestream activate = new Bytestream(getSid()); Bytestream activate = new Bytestream(getSid());
activate.setMode(null); activate.setMode(null);
@ -227,6 +232,7 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
getParent().getParent().getJingleManager().getConnection().createStanzaCollectorAndSend(activate).nextResultOrThrow(); getParent().getParent().getJingleManager().getConnection().createStanzaCollectorAndSend(activate).nextResultOrThrow();
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) { } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
LOGGER.log(Level.WARNING, "Could not activate proxy.", e); LOGGER.log(Level.WARNING, "Could not activate proxy.", e);
getParent().onTransportFailed(new S5BTransportException.ProxyError(e));
return; return;
} }
@ -238,13 +244,14 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
.nextResultOrThrow(); .nextResultOrThrow();
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) { } catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
LOGGER.log(Level.WARNING, "Could not send candidate-activated", e); LOGGER.log(Level.WARNING, "Could not send candidate-activated", e);
getParent().onTransportFailed(new S5BTransportException.ProxyError(e));
return; return;
} }
} }
LOGGER.log(Level.INFO, "Start transmission."); LOGGER.log(Level.INFO, "Start transmission.");
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.getSocket(), !isProxy); this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), !isProxy);
//callback.onSessionInitiated(bs); getParent().onTransportReady();
} }
//Our choice //Our choice
@ -253,8 +260,8 @@ public class JingleS5BTransport extends JingleTransport<JingleS5BTransportElemen
boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy; boolean isProxy = nominated.getType() == JingleS5BTransportCandidateElement.Type.proxy;
if (!isProxy) { if (!isProxy) {
LOGGER.log(Level.INFO, "Direct connection."); LOGGER.log(Level.INFO, "Direct connection.");
Socks5BytestreamSession bs = new Socks5BytestreamSession(nominated.getSocket(), true); this.bytestreamSession = new Socks5BytestreamSession(nominated.getSocket(), true);
//callback.onSessionInitiated(bs); getParent().onTransportReady();
} 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.");
} }

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);
}
}
}