Split JingleFileTransferSession in incoming and outgoing

This commit is contained in:
vanitasvitae 2017-06-19 17:55:04 +02:00
parent 73f9af474e
commit 2bac6297ee
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
9 changed files with 179 additions and 92 deletions

View File

@ -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() {
}
}

View File

@ -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<XMPPConnection, JingleFileTransferManager> INSTANCES = new WeakHashMap<>();
private final JingleUtil jutil;
private final ArrayList<JingleFileTransferOfferListener> 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);
}
}

View File

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

View File

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

View File

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

View File

@ -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<XMPPConnection, JingleTransportMethodManager> INSTANCES = new WeakHashMap<>();
private final HashMap<String, JingleTransportManager<?>> 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<String> it = transportManagers.keySet().iterator();
if (it.hasNext()) {
return getTransportManager(it.next());
}
return null;
}
}

View File

@ -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 <D> JingleContentTransport.
*/
public abstract class JingleTransportManager<D extends JingleContentTransport> {

View File

@ -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 <a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261: Jingle In-Band Bytestreams</a>.
*/
package org.jivesoftware.smackx.jingle.transports;

View File

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