diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileOffer.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/IncomingJingleFileOffer.java similarity index 73% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileOffer.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/IncomingJingleFileOffer.java index 9f9cae55b..bd725cd3f 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/JingleFileOffer.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/IncomingJingleFileOffer.java @@ -24,7 +24,6 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.jingle.JingleManager; import org.jivesoftware.smackx.jingle.JingleTransportMethodManager; import org.jivesoftware.smackx.jingle.Role; import org.jivesoftware.smackx.jingle.element.Jingle; @@ -32,45 +31,37 @@ import org.jivesoftware.smackx.jingle.element.JingleContent; import org.jivesoftware.smackx.jingle.element.JingleContentTransport; import org.jivesoftware.smackx.jingle.transports.JingleTransportManager; import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingFileOfferCallback; -import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingFileRequestCallback; -import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransfer; import org.jxmpp.jid.FullJid; /** - * Offer. + * We are the responder and we are the recipient. */ -public class JingleFileOffer extends JingleFileTransferSession implements IncomingFileOfferCallback, IncomingFileRequestCallback { +public class IncomingJingleFileOffer extends JingleFileTransferSession implements IncomingFileOfferCallback { + private static final Logger LOGGER = Logger.getLogger(IncomingJingleFileOffer.class.getName()); - private static final Logger LOGGER = Logger.getLogger(JingleFileOffer.class.getName()); - - public JingleFileOffer(XMPPConnection connection, FullJid initiator, FullJid responder, Role role, String sid) { - super(connection, initiator, responder, role, sid, Type.offer); + public IncomingJingleFileOffer(XMPPConnection connection, FullJid initiator, String sid) { + super(connection, initiator, connection.getUser().asFullJidOrThrow(), Role.responder, sid, Type.offer); } - public static JingleFileOffer createOutgoingFileOffer(XMPPConnection connection, FullJid recipient) { - return new JingleFileOffer(connection, connection.getUser().asFullJidOrThrow(), recipient, - Role.initiator, JingleManager.randomSid()); - } - - public static JingleFileOffer createIncomingFileOffer(XMPPConnection connection, Jingle request) { - return new JingleFileOffer(connection, request.getInitiator(), connection.getUser().asFullJidOrThrow(), - Role.responder, request.getSid()); + public IncomingJingleFileOffer(XMPPConnection connection, Jingle request) { + this(connection, request.getInitiator(), request.getSid()); } @Override public IQ handleSessionInitiate(Jingle initiate) { - setState(State.pending); if (role == Role.initiator) { - //TODO: Illegal stanza. Figure out, if we handle it correct. + //TODO: Is tie-break the correct way to tackle this? return jutil.createErrorTieBreak(initiate); } if (getState() != State.fresh) { + //Out of order (initiate after accept) return jutil.createErrorOutOfOrder(initiate); } JingleFileTransferManager.getInstanceFor(connection).notifyIncomingFileOffer(initiate, this); + setState(State.pending); return jutil.createAck(initiate); } @@ -115,14 +106,4 @@ public class JingleFileOffer extends JingleFileTransferSession implements Incomi LOGGER.log(Level.SEVERE, "Could not send session-terminate: " + e, e); } } - - @Override - public void acceptIncomingFileRequest(JingleFileTransfer file, File source) { - - } - - @Override - public void declineIncomingFileRequest() { - - } } 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 e1fa492c7..568f5cee6 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 @@ -16,6 +16,7 @@ */ package org.jivesoftware.smackx.jingle_filetransfer; +import java.util.ArrayList; import java.util.WeakHashMap; import org.jivesoftware.smack.Manager; @@ -30,6 +31,7 @@ import org.jivesoftware.smackx.jingle.element.JingleAction; import org.jivesoftware.smackx.jingle.element.JingleContent; import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingFileOfferCallback; import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransfer; +import org.jivesoftware.smackx.jingle_filetransfer.listener.JingleFileTransferOfferListener; import org.jxmpp.jid.FullJid; @@ -40,6 +42,7 @@ public final class JingleFileTransferManager extends Manager implements JingleHa private static final WeakHashMap INSTANCES = new WeakHashMap<>(); private final JingleUtil jutil; + private final ArrayList jingleFileTransferOfferListeners = new ArrayList<>(); private JingleFileTransferManager(XMPPConnection connection) { super(connection); @@ -90,7 +93,7 @@ public final class JingleFileTransferManager extends Manager implements JingleHa JingleContent content = request.getContents().get(0); //File Offer if (content.getSenders() == JingleContent.Senders.initiator) { - return JingleFileOffer.createIncomingFileOffer(connection(), request); + return new IncomingJingleFileOffer(connection(), request); } //File Request else if (content.getSenders() == JingleContent.Senders.responder) { return JingleFileRequest.createIncomingFileRequest(connection(), request); @@ -101,6 +104,16 @@ public final class JingleFileTransferManager extends Manager implements JingleHa } public void notifyIncomingFileOffer(Jingle initiate, IncomingFileOfferCallback callback) { + for (JingleFileTransferOfferListener l : jingleFileTransferOfferListeners) { + l.onFileOffer(initiate, callback); + } + } + public void addJingleFileTransferOfferListener(JingleFileTransferOfferListener listener) { + jingleFileTransferOfferListeners.add(listener); + } + + public void remove(JingleFileTransferOfferListener listener) { + jingleFileTransferOfferListeners.remove(listener); } } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/OutgoingJingleFileOffer.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/OutgoingJingleFileOffer.java new file mode 100644 index 000000000..60096adf6 --- /dev/null +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/OutgoingJingleFileOffer.java @@ -0,0 +1,63 @@ +/** + * + * 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_filetransfer; + +import java.util.logging.Logger; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smackx.jingle.JingleManager; +import org.jivesoftware.smackx.jingle.JingleTransportMethodManager; +import org.jivesoftware.smackx.jingle.Role; +import org.jivesoftware.smackx.jingle.element.JingleContent; +import org.jivesoftware.smackx.jingle.element.JingleContentTransport; +import org.jivesoftware.smackx.jingle.transports.JingleTransportManager; +import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransfer; + +import org.jxmpp.jid.FullJid; + +/** + * We are the initiator and we are the sender. + */ +public class OutgoingJingleFileOffer extends JingleFileTransferSession { + + private static final Logger LOGGER = Logger.getLogger(OutgoingJingleFileOffer.class.getName()); + + public OutgoingJingleFileOffer(XMPPConnection connection, FullJid responder, String sid) { + super(connection, connection.getUser().asFullJidOrThrow(), responder, Role.initiator, sid, Type.offer); + } + + public OutgoingJingleFileOffer(XMPPConnection connection, FullJid recipient) { + this(connection, recipient, JingleManager.randomSid()); + } + + public void sendFile(JingleFileTransfer file, JingleContent.Creator creator, String name) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException { + if (getState() == State.fresh) { + JingleTransportManager transportManager = JingleTransportMethodManager.getInstanceFor(connection) + .getBestAvailableTransportManager(); + + if (transportManager == null) { + throw new IllegalStateException("There must be at least one workable transport method."); + } + + JingleContentTransport transport = transportManager.createTransport(); + + jutil.sendSessionInitiateFileOffer(getResponder(), getSessionId(), creator, name, file, transport); + } + } +} diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingFileRequestCallback.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingFileRequestCallback.java index 54aaf466a..0b4deea86 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingFileRequestCallback.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/callback/IncomingFileRequestCallback.java @@ -18,14 +18,14 @@ package org.jivesoftware.smackx.jingle_filetransfer.callback; import java.io.File; -import org.jivesoftware.smackx.jingle_filetransfer.element.JingleFileTransfer; +import org.jivesoftware.smackx.jingle.element.Jingle; /** * Callback used to accept/decline file requests. */ public interface IncomingFileRequestCallback { - void acceptIncomingFileRequest(JingleFileTransfer file, File source); + void acceptIncomingFileRequest(Jingle request, File source); - void declineIncomingFileRequest(); + void declineIncomingFileRequest(Jingle request); } diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/IncomingFileTransferListener.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/JingleFileTransferOfferListener.java similarity index 72% rename from smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/IncomingFileTransferListener.java rename to smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/JingleFileTransferOfferListener.java index dff6e0dff..39927ed91 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/IncomingFileTransferListener.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/jingle_filetransfer/listener/JingleFileTransferOfferListener.java @@ -17,11 +17,12 @@ package org.jivesoftware.smackx.jingle_filetransfer.listener; import org.jivesoftware.smackx.jingle.element.Jingle; +import org.jivesoftware.smackx.jingle_filetransfer.callback.IncomingFileOfferCallback; /** - * Created by vanitas on 18.06.17. + * Listener for incoming Jingle File Transfer (XEP-0234) file offers. */ -public interface IncomingFileTransferListener { +public interface JingleFileTransferOfferListener { - void onIncomingJingleFileTransfer(Jingle request); + void onFileOffer(Jingle request, IncomingFileOfferCallback callback); } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportMethodManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportMethodManager.java index 7da2dac1e..92d957793 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportMethodManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/JingleTransportMethodManager.java @@ -1,6 +1,23 @@ +/** + * + * 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 java.util.HashMap; +import java.util.Iterator; import java.util.WeakHashMap; import org.jivesoftware.smack.Manager; @@ -9,15 +26,22 @@ import org.jivesoftware.smackx.jingle.element.Jingle; import org.jivesoftware.smackx.jingle.element.JingleContent; import org.jivesoftware.smackx.jingle.element.JingleContentTransport; import org.jivesoftware.smackx.jingle.transports.JingleTransportManager; +import org.jivesoftware.smackx.jingle.transports.jingle_ibb.element.JingleIBBTransport; +import org.jivesoftware.smackx.jingle.transports.jingle_s5b.elements.JingleS5BTransport; /** - * Created by vanitas on 19.06.17. + * Manager where TransportMethods are registered. */ public final class JingleTransportMethodManager extends Manager { private static final WeakHashMap INSTANCES = new WeakHashMap<>(); private final HashMap> transportManagers = new HashMap<>(); + private static final String[] transportPreference = new String[] { + JingleS5BTransport.NAMESPACE_V1, + JingleIBBTransport.NAMESPACE_V1 + }; + private JingleTransportMethodManager(XMPPConnection connection) { super(connection); } @@ -44,4 +68,25 @@ public final class JingleTransportMethodManager extends Manager { JingleContentTransport transport = content.getJingleTransports().get(0); return getTransportManager(transport.getNamespace()); } + + /** + * TODO: Find better solution. + * @return + */ + public JingleTransportManager getBestAvailableTransportManager() { + JingleTransportManager tm; + for (String ns : transportPreference) { + tm = getTransportManager(ns); + if (tm != null) { + return tm; + } + } + + Iterator it = transportManagers.keySet().iterator(); + if (it.hasNext()) { + return getTransportManager(it.next()); + } + + return null; + } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java index 701a5cddd..70f318c5f 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/JingleTransportManager.java @@ -1,10 +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.transports; import org.jivesoftware.smackx.jingle.element.Jingle; import org.jivesoftware.smackx.jingle.element.JingleContentTransport; /** - * Created by vanitas on 19.06.17. + * Manager for a JingleTransport method. + * @param JingleContentTransport. */ public abstract class JingleTransportManager { diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/package-info.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/package-info.java new file mode 100644 index 000000000..9cfe634a5 --- /dev/null +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/jingle/transports/package-info.java @@ -0,0 +1,21 @@ +/** + * + * 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. + */ + +/** + * Smack's API for XEP-0261: Jingle In-Band Bytestreams. + */ +package org.jivesoftware.smackx.jingle.transports; diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle/JingleSessionTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle/JingleSessionTest.java deleted file mode 100644 index d9868b1d1..000000000 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/jingle/JingleSessionTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * - * 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 static junit.framework.TestCase.assertEquals; -import static junit.framework.TestCase.assertNotSame; - -import org.jivesoftware.smack.test.util.SmackTestSuite; -import org.jivesoftware.smack.util.StringUtils; - -import org.junit.Test; -import org.jxmpp.jid.FullJid; -import org.jxmpp.jid.impl.JidCreate; -import org.jxmpp.stringprep.XmppStringprepException; - -/** - * Test JingleSession class. - */ -public class JingleSessionTest extends SmackTestSuite { - - @Test - public void sessionTest() throws XmppStringprepException { - FullJid romeo = JidCreate.fullFrom("romeo@montague.lit/r"); - FullJid juliet = JidCreate.fullFrom("juliet@capulet.lit/j"); - String sid = StringUtils.randomString(24); - - JingleSession s1 = new JingleSession(romeo, juliet, Role.initiator, sid); - JingleSession s2 = new JingleSession(juliet, romeo, Role.responder, sid); - JingleSession s3 = new JingleSession(romeo, juliet, Role.responder, StringUtils.randomString(23)); - JingleSession s4 = new JingleSession(juliet, romeo, Role.responder, sid); - JingleSession s5 = new JingleSession(juliet, romeo, Role.initiator, sid); - - assertNotSame(s1, s2); - assertNotSame(s1, s3); - assertNotSame(s2, s3); - assertNotSame(s4, s5); - assertEquals(s2, s4); - assertEquals(s2.hashCode(), s4.hashCode()); - } -}