From 4feda2ffa9f323a08ca931a712487ac8efd22d22 Mon Sep 17 00:00:00 2001 From: vanitasvitae Date: Mon, 12 Jun 2017 14:44:00 +0200 Subject: [PATCH] Progress --- .../AbstractJingleSession.java | 17 +++ .../JingleFileTransferManager.java | 6 +- .../JingleFileTransferSession.java | 43 +++--- .../jingle_ibb/JingleIBBTransportHandler.java | 17 ++- .../jingle_s5b/JingleS5BTransportHandler.java | 129 ++++++++++++------ .../socks5/Socks5BytestreamSession.java | 2 +- .../smackx/jingle/JingleSessionHandler.java | 4 + .../smackx/jingle/JingleTransportHandler.java | 11 +- .../jingle/JingleTransportInfoListener.java | 27 ++++ 9 files changed, 188 insertions(+), 68 deletions(-) create mode 100644 smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportInfoListener.java diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/AbstractJingleSession.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/AbstractJingleSession.java index 7d5b34e14..725ea7671 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/AbstractJingleSession.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/AbstractJingleSession.java @@ -16,9 +16,12 @@ */ package org.jivesoftware.smackx.jingle_filetransfer; +import java.util.ArrayList; + import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smackx.jingle.JingleSessionHandler; +import org.jivesoftware.smackx.jingle.JingleTransportInfoListener; import org.jivesoftware.smackx.jingle.element.Jingle; /** @@ -28,6 +31,7 @@ public abstract class AbstractJingleSession implements JingleSessionHandler { protected final XMPPConnection connection; protected AbstractJingleSession state; + protected final ArrayList transportInfoListeners = new ArrayList<>(); public AbstractJingleSession(XMPPConnection connection) { this.connection = connection; @@ -120,6 +124,9 @@ public abstract class AbstractJingleSession implements JingleSessionHandler { } protected IQ handleTransportInfo(Jingle transportInfo) { + for (JingleTransportInfoListener l : transportInfoListeners) { + l.onTransportInfoReceived(transportInfo); + } return IQ.createResultIQ(transportInfo); } @@ -131,6 +138,16 @@ public abstract class AbstractJingleSession implements JingleSessionHandler { return IQ.createResultIQ(transportReject); } + @Override + public void addTransportInfoListener(JingleTransportInfoListener listener) { + transportInfoListeners.add(listener); + } + + @Override + public void removeTransportInfoListener(JingleTransportInfoListener listener) { + transportInfoListeners.remove(listener); + } + @Override public XMPPConnection getConnection() { return connection; diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java index b38fbcbd3..e80a1889a 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferManager.java @@ -31,7 +31,7 @@ import org.jivesoftware.smackx.jingle_filetransfer.callback.JingleFileTransferCa import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransferChild; import org.jivesoftware.smackx.jingle_filetransfer.listener.IncomingJingleFileTransferListener; import org.jivesoftware.smackx.jingle_filetransfer.provider.JingleFileTransferContentDescriptionProvider; -import org.jivesoftware.smackx.jingle_ibb.JingleIBBTransportManager; +import org.jivesoftware.smackx.jingle_s5b.JingleS5BTransportManager; import org.jxmpp.jid.FullJid; /** @@ -48,8 +48,8 @@ public final class JingleFileTransferManager extends Manager implements JingleHa super(connection); JingleContentProviderManager.addJingleContentDescriptionProvider(NAMESPACE_V5, new JingleFileTransferContentDescriptionProvider()); JingleManager.getInstanceFor(connection).registerDescriptionHandler(NAMESPACE_V5, this); - JingleIBBTransportManager.getInstanceFor(connection); - //JingleS5BTransportManager.getInstanceFor(connection); + //JingleIBBTransportManager.getInstanceFor(connection); + JingleS5BTransportManager.getInstanceFor(connection); } public static JingleFileTransferManager getInstanceFor(XMPPConnection connection) { diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java index 1ef19eee0..486090f76 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileTransferSession.java @@ -59,7 +59,8 @@ public class JingleFileTransferSession extends AbstractJingleSession { private final File source; private File target; - private final JingleContent proposedContent; + private JingleContent proposedContent; + private JingleContent receivedContent; private final FullJid remote; private final String sessionId; @@ -109,7 +110,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { this.sessionId = initiate.getSessionId(); this.remote = initiate.getInitiator(); this.source = null; - this.proposedContent = initiate.getContents().get(0); + this.receivedContent = initiate.getContents().get(0); this.state = new IncomingFresh(connection, this); } @@ -117,7 +118,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { /** * session-initiate has been sent. */ - public static class OutgoingInitiated extends AbstractJingleSession { + private static class OutgoingInitiated extends AbstractJingleSession { private final JingleFileTransferSession parent; @@ -128,6 +129,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { @Override protected IQ handleSessionAccept(Jingle jingle) { + parent.receivedContent = jingle.getContents().get(0); parent.state = new OutgoingAccepted(connection, parent); //TODO: Notify parent return IQ.createResultIQ(jingle); @@ -142,7 +144,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { } - public static class OutgoingAccepted extends AbstractJingleSession { + private static class OutgoingAccepted extends AbstractJingleSession { private final JingleFileTransferSession parent; public OutgoingAccepted(XMPPConnection connection, final JingleFileTransferSession parent) { @@ -158,12 +160,14 @@ public class JingleFileTransferSession extends AbstractJingleSession { } JingleTransportHandler transportHandler = tm.createJingleTransportHandler(this); - transportHandler.establishOutgoingSession(parent.getFullJidAndSessionId(), + transportHandler.prepareOutgoingSession(parent.getFullJidAndSessionId(), parent.proposedContent); + parent.addTransportInfoListener(transportHandler); + transportHandler.establishOutgoingSession(parent.getFullJidAndSessionId(), parent.receivedContent, parent.proposedContent, parent.outgoingFileTransferSessionEstablishedCallback); } } - public static class IncomingFresh extends AbstractJingleSession { + private static class IncomingFresh extends AbstractJingleSession { private final JingleFileTransferSession parent; public IncomingFresh(XMPPConnection connection, JingleFileTransferSession parent) { @@ -177,8 +181,10 @@ public class JingleFileTransferSession extends AbstractJingleSession { throw new IllegalArgumentException("Jingle action MUST be session-initiate!"); } + parent.receivedContent = initiate.getContents().get(0); + //Get - JingleFileTransferChild file = (JingleFileTransferChild) initiate.getContents().get(0) + JingleFileTransferChild file = (JingleFileTransferChild) parent.receivedContent .getDescription().getJingleContentDescriptionChildren().get(0); final JingleFileTransferCallback callback = new JingleFileTransferCallback() { @@ -186,12 +192,13 @@ public class JingleFileTransferSession extends AbstractJingleSession { public void acceptFileTransfer(File target) throws SmackException.NotConnectedException, InterruptedException { Jingle response = null; try { - response = parent.createSessionAccept(initiate); + response = parent.createSessionAccept(); } catch (Exception e) { LOGGER.log(Level.WARNING, "Could not create accept-session stanza: " + e, e); } connection.sendStanza(response); + parent.proposedContent = response.getContents().get(0); parent.target = target; parent.state = new IncomingAccepted(connection, parent); } @@ -210,7 +217,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { } } - public static class IncomingAccepted extends AbstractJingleSession { + private static class IncomingAccepted extends AbstractJingleSession { public IncomingAccepted(XMPPConnection connection, JingleFileTransferSession parent) { super(connection); @@ -223,7 +230,8 @@ public class JingleFileTransferSession extends AbstractJingleSession { } JingleTransportHandler transportHandler = tm.createJingleTransportHandler(this); - transportHandler.establishIncomingSession(parent.getFullJidAndSessionId(), + parent.addTransportInfoListener(transportHandler); + transportHandler.establishIncomingSession(parent.getFullJidAndSessionId(), parent.receivedContent, parent.proposedContent, parent.incomingFileTransferSessionEstablishedCallback); } } @@ -252,8 +260,7 @@ public class JingleFileTransferSession extends AbstractJingleSession { return jingle; } - protected Jingle createSessionAccept(Jingle jingle) throws Exception { - JingleContent content = jingle.getContents().get(0); + protected Jingle createSessionAccept() throws Exception { Jingle.Builder jb = Jingle.getBuilder(); jb.setAction(JingleAction.session_accept) @@ -265,16 +272,16 @@ public class JingleFileTransferSession extends AbstractJingleSession { AbstractJingleTransportManager tm; try { tm = JingleTransportManager.getJingleContentTransportManager( - connection, jingle); + connection, receivedContent.getJingleTransports().get(0)); } catch (UnsupportedJingleTransportException e) { throw new AssertionError("Should never happen."); //TODO: Make sure. } - cb.addTransport(tm.createJingleContentTransport(jingle)) - .setDescription(content.getDescription()) - .setName(content.getName()) - .setCreator(content.getCreator()) - .setSenders(content.getSenders()); + cb.addTransport(tm.createJingleContentTransport(remote)) + .setDescription(receivedContent.getDescription()) + .setName(receivedContent.getName()) + .setCreator(receivedContent.getCreator()) + .setSenders(receivedContent.getSenders()); jb.addJingleContent(cb.build()); Jingle accept = jb.build(); diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportHandler.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportHandler.java index b69118418..f88049b54 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportHandler.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_ibb/JingleIBBTransportHandler.java @@ -30,6 +30,7 @@ import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleSessionHandler; import org.jivesoftware.smackx.jingle.JingleTransportEstablishedCallback; import org.jivesoftware.smackx.jingle.JingleTransportHandler; +import org.jivesoftware.smackx.jingle.element.Jingle; import org.jivesoftware.smackx.jingle.element.JingleContent; import org.jivesoftware.smackx.jingle.exception.JingleTransportFailureException; import org.jivesoftware.smackx.jingle_ibb.element.JingleIBBTransport; @@ -45,9 +46,15 @@ public class JingleIBBTransportHandler implements JingleTransportHandler(sessionHandler); } + @Override + public void prepareOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, JingleContent content) { + // Nothing to do + } + @Override public void establishOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, - JingleContent content, + JingleContent receivedContent, + JingleContent proposedContent, JingleTransportEstablishedCallback callback) { InBandBytestreamSession session; @@ -64,7 +71,8 @@ public class JingleIBBTransportHandler implements JingleTransportHandler sessionHandler; + private JingleS5BTransport myTransport; + private JingleS5BTransportCandidate receivedCandidateUsed = null; private Socket connectedSocket = null; @@ -60,11 +62,34 @@ public class JingleS5BTransportHandler implements JingleTransportHandler(sessionHandler); } + @Override + public void prepareOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, JingleContent content) { + myTransport = (JingleS5BTransport) content.getJingleTransports().get(0); + Socks5Proxy.getSocks5Proxy().addLocalAddress(myTransport.getDestinationAddress()); + } + @Override public void establishOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, - JingleContent content, + JingleContent receivedContent, + JingleContent proposedContent, JingleTransportEstablishedCallback callback) { - JingleContentTransport hopefullyS5BTransport = content.getJingleTransports().get(0); + establishSession(fullJidAndSessionId, receivedContent, proposedContent, callback); + } + + @Override + public void establishIncomingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, + JingleContent receivedContent, + JingleContent proposedContent, + JingleTransportEstablishedCallback callback) { + establishSession(fullJidAndSessionId, receivedContent, proposedContent, callback); + } + + void establishSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, + JingleContent receivedContent, + JingleContent proposedContent, + JingleTransportEstablishedCallback callback) { + + JingleContentTransport hopefullyS5BTransport = receivedContent.getJingleTransports().get(0); if (!hopefullyS5BTransport.getNamespace().equals(JingleS5BTransport.NAMESPACE_V1)) { throw new IllegalArgumentException("Transport must be a JingleS5BTransport."); } @@ -82,7 +107,7 @@ public class JingleS5BTransportHandler implements JingleTransportHandler streamHosts = new ArrayList<>(); - for (JingleContentTransportCandidate c : transport.getCandidates()) { //TODO Sort - streamHosts.add(((JingleS5BTransportCandidate) c).getStreamHost()); - } + tb = JingleS5BTransport.getBuilder(); + tb.setStreamId(((JingleS5BTransport) receivedContent.getJingleTransports().get(0)).getStreamId()); + tb.setCandidateActivated(usedCandidate.getCandidateId()); - for (Bytestream.StreamHost streamHost : streamHosts) { - String address = streamHost.getAddress() + ":" + streamHost.getPort(); + cb.addTransport(tb.build()); + jb.addJingleContent(cb.build()); + + Jingle activate = jb.build(); + activate.setTo(fullJidAndSessionId.getFullJid()); + activate.setFrom(getConnection().getUser()); - LOGGER.log(Level.INFO, "Connect inwards to " + address); - // establish socket try { - - // build SOCKS5 client - final Socks5Client socks5Client = new Socks5Client(streamHost, transport.getDestinationAddress()); - - // connect to SOCKS5 proxy with a timeout - Socket socket = socks5Client.getSocket(10 * 1000); - - // set selected host - break; - - } - catch (TimeoutException | IOException | SmackException | XMPPException | InterruptedException e) { - LOGGER.log(Level.WARNING, "Could not connect inwards to " + address + ": " + e, e); + getConnection().sendStanza(activate); + } catch (SmackException.NotConnectedException | InterruptedException e) { + LOGGER.log(Level.SEVERE, "Could not send transport-activated: " + e, e); } + callback.onSessionEstablished(new Socks5BytestreamSession(connectedSocket, false)); + } else { + } } @@ -180,4 +207,24 @@ public class JingleS5BTransportHandler implements JingleTransportHandler { +public interface JingleTransportHandler extends JingleTransportInfoListener { + + void prepareOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, + JingleContent content); void establishOutgoingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, - JingleContent content, + JingleContent receivedContent, + JingleContent proposedContent, JingleTransportEstablishedCallback callback); void establishIncomingSession(JingleManager.FullJidAndSessionId fullJidAndSessionId, - JingleContent content, + JingleContent receivedContent, + JingleContent proposedContent, JingleTransportEstablishedCallback callback); XMPPConnection getConnection(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportInfoListener.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportInfoListener.java new file mode 100644 index 000000000..e5c63c5ef --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportInfoListener.java @@ -0,0 +1,27 @@ +/** + * + * Copyright © 2017 Paul Schaub + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jivesoftware.smackx.jingle; + +import org.jivesoftware.smackx.jingle.element.Jingle; + +/** + * Listener for transport-info Jingle stanzas. + */ +public interface JingleTransportInfoListener { + + void onTransportInfoReceived(Jingle transportInfo); +}