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:
parent
438fc0e94b
commit
c0e5fcf737
10 changed files with 166 additions and 43 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
||||
final InBandBytestreamManager inBandBytestreamManager = InBandBytestreamManager.getByteStreamManager(connection);
|
||||
|
||||
InBandBytestreamListener bytestreamListener = new InBandBytestreamListener() {
|
||||
@Override
|
||||
public void incomingBytestreamRequest(BytestreamRequest request) {
|
||||
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 | XMPPException.XMPPErrorException e) {
|
||||
listener.onBytestreamSessionFailed(e);
|
||||
} catch (InterruptedException | SmackException e) {
|
||||
getParent().onTransportFailed(e);
|
||||
return;
|
||||
}
|
||||
listener.onBytestreamSessionEstablished(bytestreamSession);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue